[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Merge.
# HG changeset patch # User adsharma@xxxxxxxxxxxxxxxxxxxx # Node ID 81576d3d1ca891cdcd81fada9025b2279a974458 # Parent 99914b54f7bffc8c27757a1ac2bc7a0d97597ac8 # Parent 0608852073c86cfa432ac32cb9223531950be896 Merge. diff -r 99914b54f7bf -r 81576d3d1ca8 Config.mk --- a/Config.mk Thu Aug 18 18:40:02 2005 +++ b/Config.mk Fri Aug 19 18:19:28 2005 @@ -35,3 +35,11 @@ # Choose the best mirror to download linux kernel KERNEL_REPO = http://www.kernel.org + +# ACM_USE_SECURITY_POLICY is set to security policy of Xen +# Supported models are: +# ACM_NULL_POLICY (ACM will not be built with this policy) +# ACM_CHINESE_WALL_POLICY +# ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY +# ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY +ACM_USE_SECURITY_POLICY ?= ACM_NULL_POLICY diff -r 99914b54f7bf -r 81576d3d1ca8 docs/src/user.tex --- a/docs/src/user.tex Thu Aug 18 18:40:02 2005 +++ b/docs/src/user.tex Fri Aug 19 18:19:28 2005 @@ -1763,7 +1763,7 @@ physical address in the memory map will be ignored. This parameter may be specified with a B, K, M or G suffix, representing bytes, kilobytes, megabytes and gigabytes respectively. The - default unit, if no suffix is specified, is bytes. + default unit, if no suffix is specified, is kilobytes. \item [dom0\_mem=xxx ] Set the amount of memory to be allocated to domain0. In Xen 3.x the parameter diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile Fri Aug 19 18:19:28 2005 @@ -14,8 +14,7 @@ c-obj-y := semaphore.o vm86.o \ ptrace.o sys_i386.o \ - i387.o dmi_scan.o bootflag.o \ - doublefault.o + i387.o dmi_scan.o bootflag.o s-obj-y := obj-y += cpu/ @@ -85,7 +84,7 @@ $(obj)/vsyscall-sysenter.o FORCE $(call if_changed,syscall) -c-link := init_task.o +c-link := s-link := vsyscall-int80.o vsyscall-sysenter.o vsyscall-sigreturn.o vsyscall.lds.o syscall_table.o $(patsubst %.o,$(obj)/%.c,$(c-obj-y) $(c-obj-m) $(c-link)) $(patsubst %.o,$(obj)/%.S,$(s-obj-y) $(s-link)): diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/common.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/common.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/common.c Fri Aug 19 18:19:28 2005 @@ -569,7 +569,7 @@ for (va = gdt_descr->address, f = 0; va < gdt_descr->address + gdt_descr->size; va += PAGE_SIZE, f++) { - frames[f] = virt_to_machine(va) >> PAGE_SHIFT; + frames[f] = virt_to_mfn(va); make_page_readonly((void *)va); } if (HYPERVISOR_set_gdt(frames, gdt_descr->size / 8)) diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S Fri Aug 19 18:19:28 2005 @@ -136,9 +136,6 @@ ENTRY(empty_zero_page) .org 0x2000 -ENTRY(swapper_pg_dir) - -.org 0x3000 ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ .quad 0x0000000000000000 /* 0x0b reserved */ @@ -190,10 +187,10 @@ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ .fill GDT_ENTRIES-32,8,0 -.org 0x4000 +.org 0x3000 ENTRY(default_ldt) -.org 0x5000 +.org 0x4000 /* * Real beginning of normal "text" segment */ diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/ioport.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/ioport.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/ioport.c Fri Aug 19 18:19:28 2005 @@ -80,7 +80,7 @@ t->io_bitmap_ptr = bitmap; op.cmd = PHYSDEVOP_SET_IOBITMAP; - op.u.set_iobitmap.bitmap = (unsigned long)bitmap; + op.u.set_iobitmap.bitmap = (char *)bitmap; op.u.set_iobitmap.nr_ports = IO_BITMAP_BITS; HYPERVISOR_physdev_op(&op); } diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c Fri Aug 19 18:19:28 2005 @@ -198,7 +198,7 @@ { struct mm_struct * mm = current->mm; __u32 entry_1, entry_2, *lp; - unsigned long mach_lp; + maddr_t mach_lp; int error; struct user_desc ldt_info; @@ -245,7 +245,8 @@ /* Install the new entry ... */ install: - error = HYPERVISOR_update_descriptor(mach_lp, entry_1, entry_2); + error = HYPERVISOR_update_descriptor( + mach_lp, (u64)entry_1 | ((u64)entry_2<<32)); out_unlock: up(&mm->context.sem); diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Fri Aug 19 18:19:28 2005 @@ -115,20 +115,12 @@ /* We don't actually take CPU down, just spin without interrupts. */ static inline void play_dead(void) { - /* Ack it */ - __get_cpu_var(cpu_state) = CPU_DEAD; - - /* We shouldn't have to disable interrupts while dead, but - * some interrupts just don't seem to go away, and this makes - * it "work" for testing purposes. */ /* Death loop */ while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) HYPERVISOR_yield(); - local_irq_disable(); __flush_tlb_all(); cpu_set(smp_processor_id(), cpu_online_map); - local_irq_enable(); } #else static inline void play_dead(void) @@ -156,12 +148,19 @@ rmb(); if (cpu_is_offline(cpu)) { + local_irq_disable(); + /* Ack it. From this point on until + we get woken up, we're not allowed + to take any locks. In particular, + don't printk. */ + __get_cpu_var(cpu_state) = CPU_DEAD; #if defined(CONFIG_XEN) && defined(CONFIG_HOTPLUG_CPU) /* Tell hypervisor to take vcpu down. */ HYPERVISOR_vcpu_down(cpu); #endif play_dead(); - } + local_irq_enable(); + } __get_cpu_var(irq_stat).idle_timestamp = jiffies; xen_idle(); @@ -523,16 +522,15 @@ * Load the per-thread Thread-Local Storage descriptor. * This is load_TLS(next, cpu) with multicalls. */ -#define C(i) do { \ - if (unlikely(next->tls_array[i].a != prev->tls_array[i].a || \ - next->tls_array[i].b != prev->tls_array[i].b)) { \ - mcl->op = __HYPERVISOR_update_descriptor; \ - mcl->args[0] = virt_to_machine(&get_cpu_gdt_table(cpu) \ - [GDT_ENTRY_TLS_MIN + i]); \ - mcl->args[1] = ((u32 *)&next->tls_array[i])[0]; \ - mcl->args[2] = ((u32 *)&next->tls_array[i])[1]; \ - mcl++; \ - } \ +#define C(i) do { \ + if (unlikely(next->tls_array[i].a != prev->tls_array[i].a || \ + next->tls_array[i].b != prev->tls_array[i].b)) { \ + mcl->op = __HYPERVISOR_update_descriptor; \ + *(u64 *)&mcl->args[0] = virt_to_machine( \ + &get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]);\ + *(u64 *)&mcl->args[2] = *(u64 *)&next->tls_array[i]; \ + mcl++; \ + } \ } while (0) C(0); C(1); C(2); #undef C @@ -549,7 +547,7 @@ iobmp_op.cmd = PHYSDEVOP_SET_IOBITMAP; iobmp_op.u.set_iobitmap.bitmap = - (unsigned long)next->io_bitmap_ptr; + (char *)next->io_bitmap_ptr; iobmp_op.u.set_iobitmap.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0; mcl->op = __HYPERVISOR_physdev_op; @@ -791,3 +789,10 @@ sp -= get_random_int() % 8192; return sp & ~0xf; } + + +#ifndef CONFIG_X86_SMP +void _restore_vcpu(void) +{ +} +#endif diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Fri Aug 19 18:19:28 2005 @@ -1604,11 +1604,10 @@ for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ ) { pfn_to_mfn_frame_list[j] = - virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT; + virt_to_mfn(&phys_to_machine_mapping[i]); } HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list = - virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT; - + virt_to_mfn(pfn_to_mfn_frame_list); /* * NOTE: at this point the bootmem allocator is fully available. diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Fri Aug 19 18:19:28 2005 @@ -904,7 +904,7 @@ for (va = cpu_gdt_descr[cpu].address, f = 0; va < cpu_gdt_descr[cpu].address + cpu_gdt_descr[cpu].size; va += PAGE_SIZE, f++) { - ctxt.gdt_frames[f] = virt_to_machine(va) >> PAGE_SHIFT; + ctxt.gdt_frames[f] = virt_to_mfn(va); make_page_readonly((void *)va); } ctxt.gdt_ents = cpu_gdt_descr[cpu].size / 8; @@ -920,7 +920,7 @@ ctxt.failsafe_callback_cs = __KERNEL_CS; ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback; - ctxt.ctrlreg[3] = (unsigned long)virt_to_machine(swapper_pg_dir); + ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT; boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt); printk("boot error: %ld\n", boot_error); @@ -1616,3 +1616,21 @@ smp_intr_init(); local_setup_timer_irq(); } + +DECLARE_PER_CPU(int, timer_irq); + +void _restore_vcpu(void) +{ + int cpu = smp_processor_id(); + extern atomic_t vcpus_rebooting; + + /* We are the first thing the vcpu runs when it comes back, + and we are supposed to restore the IPIs and timer + interrupts etc. When we return, the vcpu's idle loop will + start up again. */ + _bind_virq_to_irq(VIRQ_TIMER, cpu, per_cpu(timer_irq, cpu)); + _bind_virq_to_irq(VIRQ_DEBUG, cpu, per_cpu(ldebug_irq, cpu)); + _bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu, per_cpu(resched_irq, cpu) ); + _bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu, per_cpu(callfunc_irq, cpu) ); + atomic_dec(&vcpus_rebooting); +} diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Fri Aug 19 18:19:28 2005 @@ -94,9 +94,6 @@ iotlb_nslabs = simple_strtoul(str, &str, 0) << (20 - IO_TLB_SHIFT); iotlb_nslabs = ALIGN(iotlb_nslabs, IO_TLB_SEGSIZE); - /* Round up to power of two (xen_create_contiguous_region). */ - while (iotlb_nslabs & (iotlb_nslabs-1)) - iotlb_nslabs += iotlb_nslabs & ~(iotlb_nslabs-1); } if (*str == ',') ++str; @@ -123,9 +120,6 @@ if (!iotlb_nslabs) { iotlb_nslabs = (default_size >> IO_TLB_SHIFT); iotlb_nslabs = ALIGN(iotlb_nslabs, IO_TLB_SEGSIZE); - /* Round up to power of two (xen_create_contiguous_region). */ - while (iotlb_nslabs & (iotlb_nslabs-1)) - iotlb_nslabs += iotlb_nslabs & ~(iotlb_nslabs-1); } bytes = iotlb_nslabs * (1UL << IO_TLB_SHIFT); @@ -135,10 +129,14 @@ */ iotlb_virt_start = alloc_bootmem_low_pages(bytes); if (!iotlb_virt_start) - panic("Cannot allocate SWIOTLB buffer"); - - xen_create_contiguous_region( - (unsigned long)iotlb_virt_start, get_order(bytes)); + panic("Cannot allocate SWIOTLB buffer!\n" + "Use dom0_mem Xen boot parameter to reserve\n" + "some DMA memory (e.g., dom0_mem=-128M).\n"); + + for (i = 0; i < iotlb_nslabs; i += IO_TLB_SEGSIZE) + xen_create_contiguous_region( + (unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT), + get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT)); iotlb_virt_end = iotlb_virt_start + bytes; diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Fri Aug 19 18:19:28 2005 @@ -745,7 +745,7 @@ #endif /* Dynamically-mapped IRQ. */ -static DEFINE_PER_CPU(int, timer_irq); +DEFINE_PER_CPU(int, timer_irq); static struct irqaction irq_timer = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer0", diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/mm/init.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c Fri Aug 19 18:19:28 2005 @@ -342,11 +342,15 @@ extern void __init remap_numa_kva(void); #endif +pgd_t *swapper_pg_dir; + static void __init pagetable_init (void) { unsigned long vaddr; - pgd_t *pgd_base = swapper_pg_dir; - pgd_t *old_pgd = (pgd_t *)xen_start_info.pt_base; + pgd_t *pgd_base = (pgd_t *)xen_start_info.pt_base; + + swapper_pg_dir = pgd_base; + init_mm.pgd = pgd_base; #ifdef CONFIG_X86_PAE int i; @@ -366,44 +370,6 @@ __PAGE_KERNEL |= _PAGE_GLOBAL; __PAGE_KERNEL_EXEC |= _PAGE_GLOBAL; } - - /* - * Switch to proper mm_init page directory. Initialise from the current - * page directory, write-protect the new page directory, then switch to - * it. We clean up by write-enabling and then freeing the old page dir. - */ -#ifndef CONFIG_X86_PAE - memcpy(pgd_base, old_pgd, PTRS_PER_PGD_NO_HV*sizeof(pgd_t)); - make_page_readonly(pgd_base); - xen_pgd_pin(__pa(pgd_base)); - load_cr3(pgd_base); - xen_pgd_unpin(__pa(old_pgd)); - make_page_writable(old_pgd); - __flush_tlb_all(); - free_bootmem(__pa(old_pgd), PAGE_SIZE); -#else - { - pud_t *old_pud = pud_offset(old_pgd+3, PAGE_OFFSET); - pmd_t *old_pmd = pmd_offset(old_pud, PAGE_OFFSET); - pmd_t *new_pmd = alloc_bootmem_low_pages(PAGE_SIZE); - - memcpy(new_pmd, old_pmd, PAGE_SIZE); - memcpy(pgd_base, old_pgd, PTRS_PER_PGD_NO_HV*sizeof(pgd_t)); - set_pgd(&pgd_base[3], __pgd(__pa(new_pmd) | _PAGE_PRESENT)); - - make_page_readonly(new_pmd); - make_page_readonly(pgd_base); - xen_pgd_pin(__pa(pgd_base)); - load_cr3(pgd_base); - xen_pgd_unpin(__pa(old_pgd)); - make_page_writable(old_pgd); - make_page_writable(old_pmd); - __flush_tlb_all(); - - free_bootmem(__pa(old_pgd), PAGE_SIZE); - free_bootmem(__pa(old_pmd), PAGE_SIZE); - } -#endif init_mm.context.pinned = 1; kernel_physical_mapping_init(pgd_base); diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Fri Aug 19 18:19:28 2005 @@ -306,7 +306,7 @@ { mmu_update_t **v = (mmu_update_t **)data; - (*v)->ptr = ((physaddr_t)pfn_to_mfn(page_to_pfn(pte_page)) << + (*v)->ptr = ((maddr_t)pfn_to_mfn(page_to_pfn(pte_page)) << PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK); (*v)++; diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c Fri Aug 19 18:19:28 2005 @@ -170,7 +170,7 @@ __flush_tlb_one(vaddr); } -void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags) +void __set_fixmap (enum fixed_addresses idx, maddr_t phys, pgprot_t flags) { unsigned long address = __fix_to_virt(idx); diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Fri Aug 19 18:19:28 2005 @@ -144,7 +144,7 @@ vcpu_info_t *vcpu_info = &s->vcpu_data[cpu]; vcpu_info->evtchn_upcall_pending = 0; - + /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); while ( l1 != 0 ) @@ -158,9 +158,9 @@ l2 &= ~(1 << l2i); port = (l1i << 5) + l2i; - if ( (irq = evtchn_to_irq[port]) != -1 ) + if ( (irq = evtchn_to_irq[port]) != -1 ) { do_IRQ(irq, regs); - else + } else evtchn_device_upcall(port); } } @@ -243,6 +243,74 @@ } spin_unlock(&irq_mapping_update_lock); +} + +/* This is only used when a vcpu from an xm save. The ipi is expected + to have been bound before we suspended, and so all of the xenolinux + state is set up; we only need to restore the Xen side of things. + The irq number has to be the same, but the evtchn number can + change. */ +void _bind_ipi_to_irq(int ipi, int vcpu, int irq) +{ + evtchn_op_t op; + int evtchn; + + spin_lock(&irq_mapping_update_lock); + + op.cmd = EVTCHNOP_bind_ipi; + if ( HYPERVISOR_event_channel_op(&op) != 0 ) + panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, vcpu); + evtchn = op.u.bind_ipi.port; + + printk("<0>IPI %d, old evtchn %d, evtchn %d.\n", + ipi, per_cpu(ipi_to_evtchn, vcpu)[ipi], + evtchn); + + evtchn_to_irq[irq_to_evtchn[irq]] = -1; + irq_to_evtchn[irq] = -1; + + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + + printk("<0>evtchn_to_irq[%d] = %d.\n", evtchn, + evtchn_to_irq[evtchn]); + per_cpu(ipi_to_evtchn, vcpu)[ipi] = evtchn; + + bind_evtchn_to_cpu(evtchn, vcpu); + + spin_unlock(&irq_mapping_update_lock); + + clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask); + clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending); +} + +void _bind_virq_to_irq(int virq, int cpu, int irq) +{ + evtchn_op_t op; + int evtchn; + + spin_lock(&irq_mapping_update_lock); + + op.cmd = EVTCHNOP_bind_virq; + op.u.bind_virq.virq = virq; + if ( HYPERVISOR_event_channel_op(&op) != 0 ) + panic("Failed to bind virtual IRQ %d\n", virq); + evtchn = op.u.bind_virq.port; + + evtchn_to_irq[irq_to_evtchn[irq]] = -1; + irq_to_evtchn[irq] = -1; + + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + + per_cpu(virq_to_irq, cpu)[virq] = irq; + + bind_evtchn_to_cpu(evtchn, cpu); + + spin_unlock(&irq_mapping_update_lock); + + clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask); + clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending); } int bind_ipi_to_irq(int ipi) diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/kernel/reboot.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Fri Aug 19 18:19:28 2005 @@ -16,6 +16,8 @@ #include <asm-xen/queues.h> #include <asm-xen/xenbus.h> #include <asm-xen/ctrl_if.h> +#include <linux/cpu.h> +#include <linux/kthread.h> #define SHUTDOWN_INVALID -1 #define SHUTDOWN_POWEROFF 0 @@ -58,20 +60,74 @@ /* Ignore multiple shutdown requests. */ static int shutting_down = SHUTDOWN_INVALID; -static void __do_suspend(void) +#ifndef CONFIG_HOTPLUG_CPU +#define cpu_down(x) (-EOPNOTSUPP) +#define cpu_up(x) (-EOPNOTSUPP) +#endif + +static void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) +{ + int r; + int gdt_pages; + r = HYPERVISOR_vcpu_pickle(vcpu, ctxt); + if (r != 0) + panic("pickling vcpu %d -> %d!\n", vcpu, r); + + /* Translate from machine to physical addresses where necessary, + so that they can be translated to our new machine address space + after resume. libxc is responsible for doing this to vcpu0, + but we do it to the others. */ + gdt_pages = (ctxt->gdt_ents + 511) / 512; + ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]); + for (r = 0; r < gdt_pages; r++) + ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]); +} + +void _restore_vcpu(int cpu); + +atomic_t vcpus_rebooting; + +static int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) +{ + int r; + int gdt_pages = (ctxt->gdt_ents + 511) / 512; + + /* This is kind of a hack, and implicitly relies on the fact that + the vcpu stops in a place where all of the call clobbered + registers are already dead. */ + ctxt->user_regs.esp -= 4; + ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip; + ctxt->user_regs.eip = (unsigned long)_restore_vcpu; + + /* De-canonicalise. libxc handles this for vcpu 0, but we need + to do it for the other vcpus. */ + ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]); + for (r = 0; r < gdt_pages; r++) + ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]); + + atomic_set(&vcpus_rebooting, 1); + r = HYPERVISOR_boot_vcpu(vcpu, ctxt); + if (r != 0) { + printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r); + return -1; + } + + /* Make sure we wait for the new vcpu to come up before trying to do + anything with it or starting the next one. */ + while (atomic_read(&vcpus_rebooting)) + barrier(); + + return 0; +} + +static int __do_suspend(void *ignore) { int i, j; suspend_record_t *suspend_record; + static vcpu_guest_context_t suspended_cpu_records[NR_CPUS]; /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */ /* XXX SMH: yes it would :-( */ -#ifdef CONFIG_XEN_BLKDEV_FRONTEND - extern void blkdev_suspend(void); - extern void blkdev_resume(void); -#else -#define blkdev_suspend() do{}while(0) -#define blkdev_resume() do{}while(0) -#endif #ifdef CONFIG_XEN_NETDEV_FRONTEND extern void netif_suspend(void); @@ -104,13 +160,63 @@ extern unsigned long max_pfn; extern unsigned int *pfn_to_mfn_frame_list; + cpumask_t prev_online_cpus, prev_present_cpus; + int err = 0; + + BUG_ON(smp_processor_id() != 0); + BUG_ON(in_interrupt()); + +#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU) + if (num_online_cpus() > 1) { + printk(KERN_WARNING "Can't suspend SMP guests without CONFIG_HOTPLUG_CPU\n"); + return -EOPNOTSUPP; + } +#endif + suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL); if ( suspend_record == NULL ) goto out; + /* Take all of the other cpus offline. We need to be careful not + to get preempted between the final test for num_online_cpus() + == 1 and disabling interrupts, since otherwise userspace could + bring another cpu online, and then we'd be stuffed. At the + same time, cpu_down can reschedule, so we need to enable + preemption while doing that. This kind of sucks, but should be + correct. */ + /* (We don't need to worry about other cpus bringing stuff up, + since by the time num_online_cpus() == 1, there aren't any + other cpus) */ + cpus_clear(prev_online_cpus); + preempt_disable(); + while (num_online_cpus() > 1) { + preempt_enable(); + for_each_online_cpu(i) { + if (i == 0) + continue; + err = cpu_down(i); + if (err != 0) { + printk(KERN_CRIT "Failed to take all CPUs down: %d.\n", err); + goto out_reenable_cpus; + } + cpu_set(i, prev_online_cpus); + } + preempt_disable(); + } + suspend_record->nr_pfns = max_pfn; /* final number of pfns */ __cli(); + + preempt_enable(); + + cpus_clear(prev_present_cpus); + for_each_present_cpu(i) { + if (i == 0) + continue; + save_vcpu_context(i, &suspended_cpu_records[i]); + cpu_set(i, prev_present_cpus); + } #ifdef __i386__ mm_pin_all(); @@ -119,8 +225,6 @@ netif_suspend(); - blkdev_suspend(); - time_suspend(); #ifdef CONFIG_SMP @@ -141,7 +245,9 @@ memcpy(&suspend_record->resume_info, &xen_start_info, sizeof(xen_start_info)); - HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT); + /* We'll stop somewhere inside this hypercall. When it returns, + we'll start resuming after the restore. */ + HYPERVISOR_suspend(virt_to_mfn(suspend_record)); shutting_down = SHUTDOWN_INVALID; @@ -157,10 +263,10 @@ for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ ) { pfn_to_mfn_frame_list[j] = - virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT; + virt_to_mfn(&phys_to_machine_mapping[i]); } HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list = - virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT; + virt_to_mfn(pfn_to_mfn_frame_list); gnttab_resume(); @@ -176,17 +282,30 @@ time_resume(); - blkdev_resume(); - netif_resume(); usbif_resume(); + for_each_cpu_mask(i, prev_present_cpus) { + restore_vcpu_context(i, &suspended_cpu_records[i]); + } + __sti(); + + out_reenable_cpus: + for_each_cpu_mask(i, prev_online_cpus) { + j = cpu_up(i); + if (j != 0) { + printk(KERN_CRIT "Failed to bring cpu %d back up (%d).\n", + i, j); + err = j; + } + } out: if ( suspend_record != NULL ) free_page((unsigned long)suspend_record); + return err; } static int shutdown_process(void *__unused) @@ -233,6 +352,18 @@ return 0; } +static struct task_struct *kthread_create_on_cpu(int (*f)(void *arg), + void *arg, + const char *name, + int cpu) +{ + struct task_struct *p; + p = kthread_create(f, arg, name); + kthread_bind(p, cpu); + wake_up_process(p); + return p; +} + static void __shutdown_handler(void *unused) { int err; @@ -245,7 +376,7 @@ } else { - __do_suspend(); + kthread_create_on_cpu(__do_suspend, NULL, "suspender", 0); } } diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/process.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/process.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/process.c Fri Aug 19 18:19:28 2005 @@ -453,8 +453,8 @@ #define C(i) do { \ if (unlikely(next->tls_array[i] != prev->tls_array[i])) { \ mcl->op = __HYPERVISOR_update_descriptor; \ - mcl->args[0] = virt_to_machine(&get_cpu_gdt_table(cpu) \ - [GDT_ENTRY_TLS_MIN + i]); \ + mcl->args[0] = virt_to_machine( \ + &get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]);\ mcl->args[1] = next->tls_array[i]; \ mcl++; \ } \ @@ -474,7 +474,7 @@ iobmp_op.cmd = PHYSDEVOP_SET_IOBITMAP; iobmp_op.u.set_iobitmap.bitmap = - (unsigned long)next->io_bitmap_ptr; + (char *)next->io_bitmap_ptr; iobmp_op.u.set_iobitmap.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0; mcl->op = __HYPERVISOR_physdev_op; @@ -743,3 +743,9 @@ sp -= get_random_int() % 8192; return sp & ~0xf; } + +#ifndef CONFIG_SMP +void _restore_vcpu(void) +{ +} +#endif diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Fri Aug 19 18:19:28 2005 @@ -795,7 +795,7 @@ for ( i=0, j=0; i < end_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ ) { pfn_to_mfn_frame_list[j] = - virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT; + virt_to_mfn(&phys_to_machine_mapping[i]); } } diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c Fri Aug 19 18:19:28 2005 @@ -139,7 +139,7 @@ for (va = gdt_descr->address, f = 0; va < gdt_descr->address + gdt_descr->size; va += PAGE_SIZE, f++) { - frames[f] = virt_to_machine(va) >> PAGE_SHIFT; + frames[f] = virt_to_mfn(va); make_page_readonly((void *)va); } if (HYPERVISOR_set_gdt(frames, gdt_descr->size / @@ -280,19 +280,16 @@ if (cpu) { memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE); } -#endif cpu_gdt_descr[cpu].size = GDT_SIZE; cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu]; - cpu_gdt_init(&cpu_gdt_descr[cpu]); - -#ifndef CONFIG_XEN memcpy(me->thread.tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8); - #else memcpy(me->thread.tls_array, &get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN], GDT_ENTRY_TLS_ENTRIES * 8); + + cpu_gdt_init(&cpu_gdt_descr[cpu]); #endif /* diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Fri Aug 19 18:19:28 2005 @@ -780,7 +780,7 @@ for (va = cpu_gdt_descr[cpu].address, f = 0; va < cpu_gdt_descr[cpu].address + cpu_gdt_descr[cpu].size; va += PAGE_SIZE, f++) { - ctxt.gdt_frames[f] = virt_to_machine(va) >> PAGE_SHIFT; + ctxt.gdt_frames[f] = virt_to_mfn(va); make_page_readonly((void *)va); } ctxt.gdt_ents = GDT_ENTRIES; @@ -795,7 +795,7 @@ ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback; ctxt.syscall_callback_eip = (unsigned long)system_call; - ctxt.ctrlreg[3] = (unsigned long)virt_to_machine(init_level4_pgt); + ctxt.ctrlreg[3] = virt_to_mfn(init_level4_pgt) << PAGE_SHIFT; boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt); @@ -1286,4 +1286,10 @@ smp_intr_init(); local_setup_timer_irq(); } -#endif + +void _restore_vcpu(void) +{ + /* XXX need to write this */ +} + +#endif diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c Fri Aug 19 18:19:28 2005 @@ -742,7 +742,7 @@ set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE); else __set_fixmap(FIX_ISAMAP_BEGIN - i, - virt_to_machine(empty_zero_page), + virt_to_mfn(empty_zero_page) << PAGE_SHIFT, PAGE_KERNEL_RO); } #endif diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkback/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/blkback/Makefile Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/Makefile Fri Aug 19 18:19:28 2005 @@ -1,2 +1,2 @@ -obj-y := blkback.o control.o interface.o vbd.o +obj-y := blkback.o xenbus.o interface.o vbd.o diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Fri Aug 19 18:19:28 2005 @@ -104,7 +104,6 @@ #endif static int do_block_io_op(blkif_t *blkif, int max_to_do); -static void dispatch_probe(blkif_t *blkif, blkif_request_t *req); static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req); static void make_response(blkif_t *blkif, unsigned long id, unsigned short op, int st); @@ -349,10 +348,6 @@ dispatch_rw_block_io(blkif, req); break; - case BLKIF_OP_PROBE: - dispatch_probe(blkif, req); - break; - default: DPRINTK("error: unknown block io operation [%d]\n", req->operation); @@ -363,66 +358,6 @@ blk_ring->req_cons = i; return more_to_do; -} - -static void dispatch_probe(blkif_t *blkif, blkif_request_t *req) -{ - int rsp = BLKIF_RSP_ERROR; - int pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; - - /* We expect one buffer only. */ - if ( unlikely(req->nr_segments != 1) ) - goto out; - - /* Make sure the buffer is page-sized. */ - if ( (blkif_first_sect(req->frame_and_sects[0]) != 0) || - (blkif_last_sect(req->frame_and_sects[0]) != ((PAGE_SIZE/512)-1)) ) - goto out; - -#ifdef CONFIG_XEN_BLKDEV_GRANT - { - struct gnttab_map_grant_ref map; - - map.host_addr = MMAP_VADDR(pending_idx, 0); - map.flags = GNTMAP_host_map; - map.ref = blkif_gref_from_fas(req->frame_and_sects[0]); - map.dom = blkif->domid; - - if ( unlikely(HYPERVISOR_grant_table_op( - GNTTABOP_map_grant_ref, &map, 1))) - BUG(); - - if ( map.handle < 0 ) - goto out; - - pending_handle(pending_idx, 0) = map.handle; - } -#else /* else CONFIG_XEN_BLKDEV_GRANT */ - -#ifdef CONFIG_XEN_BLKDEV_TAP_BE - /* Grab the real frontend out of the probe message. */ - if (req->frame_and_sects[1] == BLKTAP_COOKIE) - blkif->is_blktap = 1; -#endif - - - if ( HYPERVISOR_update_va_mapping_otherdomain( - MMAP_VADDR(pending_idx, 0), - pfn_pte_ma(req->frame_and_sects[0] >> PAGE_SHIFT, PAGE_KERNEL), -#ifdef CONFIG_XEN_BLKDEV_TAP_BE - 0, (blkif->is_blktap ? ID_TO_DOM(req->id) : blkif->domid) ) ) -#else - 0, blkif->domid) ) -#endif - goto out; -#endif /* endif CONFIG_XEN_BLKDEV_GRANT */ - - rsp = vbd_probe(blkif, (vdisk_t *)MMAP_VADDR(pending_idx, 0), - PAGE_SIZE / sizeof(vdisk_t)); - - out: - fast_flush_area(pending_idx, 1); - make_response(blkif, req->id, req->operation, rsp); } static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req) @@ -460,7 +395,7 @@ goto bad_descriptor; } - preq.dev = req->device; + preq.dev = req->handle; preq.sector_number = req->sector_number; preq.nr_sects = 0; @@ -730,8 +665,8 @@ 0, SLAB_HWCACHE_ALIGN, NULL, NULL); #endif - blkif_ctrlif_init(); - + blkif_xenbus_init(); + #ifdef CONFIG_XEN_BLKDEV_GRANT memset( pending_grant_handles, BLKBACK_INVALID_HANDLE, MMAP_PAGES ); printk(KERN_ALERT "Blkif backend is using grant tables.\n"); diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Fri Aug 19 18:19:28 2005 @@ -13,7 +13,6 @@ #include <asm/io.h> #include <asm/setup.h> #include <asm/pgalloc.h> -#include <asm-xen/ctrl_if.h> #include <asm-xen/evtchn.h> #include <asm-xen/hypervisor.h> #include <asm-xen/xen-public/io/blkif.h> @@ -47,6 +46,7 @@ /* Physical parameters of the comms window. */ unsigned long shmem_frame; unsigned int evtchn; + unsigned int remote_evtchn; /* Comms information. */ blkif_back_ring_t blk_ring; /* VBDs attached to this interface. */ @@ -71,7 +71,7 @@ struct work_struct work; #ifdef CONFIG_XEN_BLKDEV_GRANT u16 shmem_handle; - memory_t shmem_vaddr; + unsigned long shmem_vaddr; grant_ref_t shmem_ref; #endif } blkif_t; @@ -81,17 +81,29 @@ void blkif_connect(blkif_be_connect_t *connect); int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id); void blkif_disconnect_complete(blkif_t *blkif); -blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle); +blkif_t *blkif_find(domid_t domid); +void free_blkif(blkif_t *blkif); +int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn); + #define blkif_get(_b) (atomic_inc(&(_b)->refcnt)) #define blkif_put(_b) \ do { \ if ( atomic_dec_and_test(&(_b)->refcnt) ) \ - blkif_disconnect_complete(_b); \ + free_blkif(_b); \ } while (0) -void vbd_create(blkif_be_vbd_create_t *create); +struct vbd; +void vbd_free(blkif_t *blkif, struct vbd *vbd); + +/* Creates inactive vbd. */ +struct vbd *vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, blkif_pdev_t pdevice, int readonly); +int vbd_is_active(struct vbd *vbd); +void vbd_activate(blkif_t *blkif, struct vbd *vbd); + +unsigned long vbd_size(struct vbd *vbd); +unsigned int vbd_info(struct vbd *vbd); +unsigned long vbd_secsize(struct vbd *vbd); void vbd_destroy(blkif_be_vbd_destroy_t *delete); -int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds); void destroy_all_vbds(blkif_t *blkif); struct phys_req { @@ -104,9 +116,10 @@ int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation); void blkif_interface_init(void); -void blkif_ctrlif_init(void); void blkif_deschedule(blkif_t *blkif); + +void blkif_xenbus_init(void); irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs); diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Fri Aug 19 18:19:28 2005 @@ -7,24 +7,135 @@ */ #include "common.h" +#include <asm-xen/ctrl_if.h> +#include <asm-xen/evtchn.h> #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) #endif #define BLKIF_HASHSZ 1024 -#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1)) +#define BLKIF_HASH(_d) (((int)(_d))&(BLKIF_HASHSZ-1)) static kmem_cache_t *blkif_cachep; static blkif_t *blkif_hash[BLKIF_HASHSZ]; -blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle) -{ - blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)]; - while ( (blkif != NULL) && - ((blkif->domid != domid) || (blkif->handle != handle)) ) +blkif_t *blkif_find(domid_t domid) +{ + blkif_t *blkif = blkif_hash[BLKIF_HASH(domid)]; + + while (blkif) { + if (blkif->domid == domid) { + blkif_get(blkif); + return blkif; + } blkif = blkif->hash_next; + } + + blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL); + if (!blkif) + return ERR_PTR(-ENOMEM); + + memset(blkif, 0, sizeof(*blkif)); + blkif->domid = domid; + blkif->status = DISCONNECTED; + spin_lock_init(&blkif->vbd_lock); + spin_lock_init(&blkif->blk_ring_lock); + atomic_set(&blkif->refcnt, 1); + + blkif->hash_next = blkif_hash[BLKIF_HASH(domid)]; + blkif_hash[BLKIF_HASH(domid)] = blkif; return blkif; +} + +#ifndef CONFIG_XEN_BLKDEV_GRANT +static int map_frontend_page(blkif_t *blkif, unsigned long localaddr, + unsigned long shared_page) +{ + return direct_remap_area_pages(&init_mm, localaddr, + shared_page<<PAGE_SHIFT, PAGE_SIZE, + __pgprot(_KERNPG_TABLE), blkif->domid); +} + +static void unmap_frontend_page(blkif_t *blkif) +{ +} +#else +static int map_frontend_page(blkif_t *blkif, unsigned long localaddr, + unsigned long shared_page) +{ + struct gnttab_map_grant_ref op; + op.host_addr = localaddr; + op.flags = GNTMAP_host_map; + op.ref = shared_page; + op.dom = blkif->domid; + + BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); + + if (op.handle < 0) { + DPRINTK(" Grant table operation failure !\n"); + return op.handle; + } + + blkif->shmem_ref = shared_page; + blkif->shmem_handle = op.handle; + blkif->shmem_vaddr = localaddr; + return 0; +} + +static void unmap_frontend_page(blkif_t *blkif) +{ + struct gnttab_unmap_grant_ref op; + + op.host_addr = blkif->shmem_vaddr; + op.handle = blkif->shmem_handle; + op.dev_bus_addr = 0; + BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); +} +#endif /* CONFIG_XEN_BLKDEV_GRANT */ + +int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) +{ + struct vm_struct *vma; + blkif_sring_t *sring; + evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain }; + int err; + + BUG_ON(blkif->remote_evtchn); + + if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL ) + return -ENOMEM; + + err = map_frontend_page(blkif, VMALLOC_VMADDR(vma->addr), shared_page); + if (err) { + vfree(vma->addr); + return err; + } + + op.u.bind_interdomain.dom1 = DOMID_SELF; + op.u.bind_interdomain.dom2 = blkif->domid; + op.u.bind_interdomain.port1 = 0; + op.u.bind_interdomain.port2 = evtchn; + err = HYPERVISOR_event_channel_op(&op); + if (err) { + unmap_frontend_page(blkif); + vfree(vma->addr); + return err; + } + + blkif->evtchn = op.u.bind_interdomain.port1; + blkif->remote_evtchn = evtchn; + + sring = (blkif_sring_t *)vma->addr; + SHARED_RING_INIT(sring); + BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); + + bind_evtchn_to_irqhandler(blkif->evtchn, blkif_be_int, 0, "blkif-backend", + blkif); + blkif->status = CONNECTED; + blkif->shmem_frame = shared_page; + + return 0; } static void __blkif_disconnect_complete(void *arg) @@ -32,21 +143,13 @@ blkif_t *blkif = (blkif_t *)arg; ctrl_msg_t cmsg; blkif_be_disconnect_t disc; -#ifdef CONFIG_XEN_BLKDEV_GRANT - struct gnttab_unmap_grant_ref op; -#endif /* * These can't be done in blkif_disconnect() because at that point there * may be outstanding requests at the disc whose asynchronous responses * must still be notified to the remote driver. */ -#ifdef CONFIG_XEN_BLKDEV_GRANT - op.host_addr = blkif->shmem_vaddr; - op.handle = blkif->shmem_handle; - op.dev_bus_addr = 0; - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); -#endif + unmap_frontend_page(blkif); vfree(blkif->blk_ring.sring); /* Construct the deferred response message. */ @@ -81,200 +184,35 @@ schedule_work(&blkif->work); } -void blkif_create(blkif_be_create_t *create) -{ - domid_t domid = create->domid; - unsigned int handle = create->blkif_handle; - blkif_t **pblkif, *blkif; - - if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL)) == NULL ) +void free_blkif(blkif_t *blkif) +{ + blkif_t **pblkif; + evtchn_op_t op = { .cmd = EVTCHNOP_close }; + + op.u.close.port = blkif->evtchn; + op.u.close.dom = DOMID_SELF; + HYPERVISOR_event_channel_op(&op); + op.u.close.port = blkif->remote_evtchn; + op.u.close.dom = blkif->domid; + HYPERVISOR_event_channel_op(&op); + + if (blkif->evtchn) + unbind_evtchn_from_irqhandler(blkif->evtchn, blkif); + + if (blkif->blk_ring.sring) { + unmap_frontend_page(blkif); + vfree(blkif->blk_ring.sring); + } + + pblkif = &blkif_hash[BLKIF_HASH(blkif->domid)]; + while ( *pblkif != blkif ) { - DPRINTK("Could not create blkif: out of memory\n"); - create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; - return; - } - - memset(blkif, 0, sizeof(*blkif)); - blkif->domid = domid; - blkif->handle = handle; - blkif->status = DISCONNECTED; - spin_lock_init(&blkif->vbd_lock); - spin_lock_init(&blkif->blk_ring_lock); - atomic_set(&blkif->refcnt, 0); - - pblkif = &blkif_hash[BLKIF_HASH(domid, handle)]; - while ( *pblkif != NULL ) - { - if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) ) - { - DPRINTK("Could not create blkif: already exists\n"); - create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS; - kmem_cache_free(blkif_cachep, blkif); - return; - } + BUG_ON(!*pblkif); pblkif = &(*pblkif)->hash_next; } - - blkif->hash_next = *pblkif; - *pblkif = blkif; - - DPRINTK("Successfully created blkif\n"); - create->status = BLKIF_BE_STATUS_OKAY; -} - -void blkif_destroy(blkif_be_destroy_t *destroy) -{ - domid_t domid = destroy->domid; - unsigned int handle = destroy->blkif_handle; - blkif_t **pblkif, *blkif; - - pblkif = &blkif_hash[BLKIF_HASH(domid, handle)]; - while ( (blkif = *pblkif) != NULL ) - { - if ( (blkif->domid == domid) && (blkif->handle == handle) ) - { - if ( blkif->status != DISCONNECTED ) - goto still_connected; - goto destroy; - } - pblkif = &blkif->hash_next; - } - - destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - - still_connected: - destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED; - return; - - destroy: *pblkif = blkif->hash_next; destroy_all_vbds(blkif); kmem_cache_free(blkif_cachep, blkif); - destroy->status = BLKIF_BE_STATUS_OKAY; -} - -void blkif_connect(blkif_be_connect_t *connect) -{ - domid_t domid = connect->domid; - unsigned int handle = connect->blkif_handle; - unsigned int evtchn = connect->evtchn; - unsigned long shmem_frame = connect->shmem_frame; - struct vm_struct *vma; -#ifdef CONFIG_XEN_BLKDEV_GRANT - int ref = connect->shmem_ref; -#else - pgprot_t prot; - int error; -#endif - blkif_t *blkif; - blkif_sring_t *sring; - - blkif = blkif_find_by_handle(domid, handle); - if ( unlikely(blkif == NULL) ) - { - DPRINTK("blkif_connect attempted for non-existent blkif (%u,%u)\n", - connect->domid, connect->blkif_handle); - connect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - } - - if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL ) - { - connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; - return; - } - -#ifndef CONFIG_XEN_BLKDEV_GRANT - prot = __pgprot(_KERNPG_TABLE); - error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr), - shmem_frame<<PAGE_SHIFT, PAGE_SIZE, - prot, domid); - if ( error != 0 ) - { - if ( error == -ENOMEM ) - connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; - else if ( error == -EFAULT ) - connect->status = BLKIF_BE_STATUS_MAPPING_ERROR; - else - connect->status = BLKIF_BE_STATUS_ERROR; - vfree(vma->addr); - return; - } -#else - { /* Map: Use the Grant table reference */ - struct gnttab_map_grant_ref op; - op.host_addr = VMALLOC_VMADDR(vma->addr); - op.flags = GNTMAP_host_map; - op.ref = ref; - op.dom = domid; - - BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); - - handle = op.handle; - - if (op.handle < 0) { - DPRINTK(" Grant table operation failure !\n"); - connect->status = BLKIF_BE_STATUS_MAPPING_ERROR; - vfree(vma->addr); - return; - } - - blkif->shmem_ref = ref; - blkif->shmem_handle = handle; - blkif->shmem_vaddr = VMALLOC_VMADDR(vma->addr); - } -#endif - - if ( blkif->status != DISCONNECTED ) - { - connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED; - vfree(vma->addr); - return; - } - sring = (blkif_sring_t *)vma->addr; - SHARED_RING_INIT(sring); - BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); - - blkif->evtchn = evtchn; - blkif->shmem_frame = shmem_frame; - blkif->status = CONNECTED; - blkif_get(blkif); - - bind_evtchn_to_irqhandler( - blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); - - connect->status = BLKIF_BE_STATUS_OKAY; -} - -int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id) -{ - domid_t domid = disconnect->domid; - unsigned int handle = disconnect->blkif_handle; - blkif_t *blkif; - - blkif = blkif_find_by_handle(domid, handle); - if ( unlikely(blkif == NULL) ) - { - DPRINTK("blkif_disconnect attempted for non-existent blkif" - " (%u,%u)\n", disconnect->domid, disconnect->blkif_handle); - disconnect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return 1; /* Caller will send response error message. */ - } - - if ( blkif->status == CONNECTED ) - { - blkif->status = DISCONNECTING; - blkif->disconnect_rspid = rsp_id; - wmb(); /* Let other CPUs see the status change. */ - unbind_evtchn_from_irqhandler(blkif->evtchn, blkif); - blkif_deschedule(blkif); - blkif_put(blkif); - return 0; /* Caller should not send response message. */ - } - - disconnect->status = BLKIF_BE_STATUS_OKAY; - return 1; } void __init blkif_interface_init(void) diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Fri Aug 19 18:19:28 2005 @@ -11,13 +11,16 @@ */ #include "common.h" +#include <asm-xen/xenbus.h> struct vbd { - blkif_vdev_t vdevice; /* what the domain refers to this vbd as */ + blkif_vdev_t handle; /* what the domain refers to this vbd as */ unsigned char readonly; /* Non-zero -> read-only */ unsigned char type; /* VDISK_xxx */ blkif_pdev_t pdevice; /* phys device that this vbd maps to */ struct block_device *bdev; + + int active; rb_node_t rb; /* for linking into R-B tree lookup struct */ }; @@ -33,140 +36,128 @@ #define bdev_hardsect_size(_b) 512 #endif -void vbd_create(blkif_be_vbd_create_t *create) +unsigned long vbd_size(struct vbd *vbd) +{ + return vbd_sz(vbd); +} + +unsigned int vbd_info(struct vbd *vbd) +{ + return vbd->type | (vbd->readonly?VDISK_READONLY:0); +} + +unsigned long vbd_secsize(struct vbd *vbd) +{ + return bdev_hardsect_size(vbd->bdev); +} + +int vbd_is_active(struct vbd *vbd) +{ + return vbd->active; +} + +struct vbd *vbd_create(blkif_t *blkif, blkif_vdev_t handle, + blkif_pdev_t pdevice, int readonly) { struct vbd *vbd; + + if ( unlikely((vbd = kmalloc(sizeof(struct vbd), GFP_KERNEL)) == NULL) ) + { + DPRINTK("vbd_create: out of memory\n"); + return ERR_PTR(-ENOMEM); + } + + vbd->handle = handle; + vbd->readonly = readonly; + vbd->type = 0; + vbd->active = 0; + + vbd->pdevice = pdevice; + + /* FIXME: Who frees vbd on failure? --RR */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + vbd->bdev = open_by_devnum( + vbd_map_devnum(vbd->pdevice), + vbd->readonly ? FMODE_READ : FMODE_WRITE); + if ( IS_ERR(vbd->bdev) ) + { + DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); + return ERR_PTR(-ENOENT); + } + + if ( (vbd->bdev->bd_disk == NULL) ) + { + DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); + bdev_put(vbd->bdev); + return ERR_PTR(-ENOENT); + } + + if ( vbd->bdev->bd_disk->flags & GENHD_FL_CD ) + vbd->type |= VDISK_CDROM; + if ( vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE ) + vbd->type |= VDISK_REMOVABLE; + +#else + if ( (blk_size[MAJOR(vbd->pdevice)] == NULL) || (vbd_sz(vbd) == 0) ) + { + DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); + return ERR_PTR(-ENOENT); + } +#endif + + DPRINTK("Successful creation of handle=%04x (dom=%u)\n", + handle, blkif->domid); + return vbd; +} + +void vbd_activate(blkif_t *blkif, struct vbd *vbd) +{ rb_node_t **rb_p, *rb_parent = NULL; - blkif_t *blkif; - blkif_vdev_t vdevice = create->vdevice; - - blkif = blkif_find_by_handle(create->domid, create->blkif_handle); - if ( unlikely(blkif == NULL) ) - { - DPRINTK("vbd_create attempted for non-existent blkif (%u,%u)\n", - create->domid, create->blkif_handle); - create->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - } - + struct vbd *i; + BUG_ON(vbd_is_active(vbd)); + + /* Find where to put it. */ rb_p = &blkif->vbd_rb.rb_node; while ( *rb_p != NULL ) { rb_parent = *rb_p; - vbd = rb_entry(rb_parent, struct vbd, rb); - if ( vdevice < vbd->vdevice ) + i = rb_entry(rb_parent, struct vbd, rb); + if ( vbd->handle < i->handle ) { rb_p = &rb_parent->rb_left; } - else if ( vdevice > vbd->vdevice ) + else if ( vbd->handle > i->handle ) { rb_p = &rb_parent->rb_right; } else { - DPRINTK("vbd_create attempted for already existing vbd\n"); - create->status = BLKIF_BE_STATUS_VBD_EXISTS; - return; + /* We never create two of same vbd, so not possible. */ + BUG(); } } - if ( unlikely((vbd = kmalloc(sizeof(struct vbd), GFP_KERNEL)) == NULL) ) - { - DPRINTK("vbd_create: out of memory\n"); - create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; - return; - } - - vbd->vdevice = vdevice; - vbd->readonly = create->readonly; - vbd->type = 0; - - /* Mask to 16-bit for compatibility with old tools */ - vbd->pdevice = create->pdevice & 0xffff; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - vbd->bdev = open_by_devnum( - vbd_map_devnum(vbd->pdevice), - vbd->readonly ? FMODE_READ : FMODE_WRITE); - if ( IS_ERR(vbd->bdev) ) - { - DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); - create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND; - return; - } - - if ( (vbd->bdev->bd_disk == NULL) ) - { - DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); - create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND; - bdev_put(vbd->bdev); - return; - } - - if ( vbd->bdev->bd_disk->flags & GENHD_FL_CD ) - vbd->type |= VDISK_CDROM; - if ( vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE ) - vbd->type |= VDISK_REMOVABLE; - -#else - if ( (blk_size[MAJOR(vbd->pdevice)] == NULL) || (vbd_sz(vbd) == 0) ) - { - DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice); - create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND; - return; - } -#endif + /* Now we're active. */ + vbd->active = 1; + blkif_get(blkif); spin_lock(&blkif->vbd_lock); rb_link_node(&vbd->rb, rb_parent, rb_p); rb_insert_color(&vbd->rb, &blkif->vbd_rb); spin_unlock(&blkif->vbd_lock); - - DPRINTK("Successful creation of vdev=%04x (dom=%u)\n", - vdevice, create->domid); - create->status = BLKIF_BE_STATUS_OKAY; -} - - -void vbd_destroy(blkif_be_vbd_destroy_t *destroy) -{ - blkif_t *blkif; - struct vbd *vbd; - rb_node_t *rb; - blkif_vdev_t vdevice = destroy->vdevice; - - blkif = blkif_find_by_handle(destroy->domid, destroy->blkif_handle); - if ( unlikely(blkif == NULL) ) - { - DPRINTK("vbd_destroy attempted for non-existent blkif (%u,%u)\n", - destroy->domid, destroy->blkif_handle); - destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - } - - rb = blkif->vbd_rb.rb_node; - while ( rb != NULL ) - { - vbd = rb_entry(rb, struct vbd, rb); - if ( vdevice < vbd->vdevice ) - rb = rb->rb_left; - else if ( vdevice > vbd->vdevice ) - rb = rb->rb_right; - else - goto found; - } - - destroy->status = BLKIF_BE_STATUS_VBD_NOT_FOUND; - return; - - found: - spin_lock(&blkif->vbd_lock); - rb_erase(rb, &blkif->vbd_rb); - spin_unlock(&blkif->vbd_lock); +} + +void vbd_free(blkif_t *blkif, struct vbd *vbd) +{ + if (vbd_is_active(vbd)) { + spin_lock(&blkif->vbd_lock); + rb_erase(&vbd->rb, &blkif->vbd_rb); + spin_unlock(&blkif->vbd_lock); + blkif_put(blkif); + } bdev_put(vbd->bdev); kfree(vbd); } - void destroy_all_vbds(blkif_t *blkif) { @@ -183,73 +174,11 @@ bdev_put(vbd->bdev); kfree(vbd); spin_lock(&blkif->vbd_lock); + blkif_put(blkif); } spin_unlock(&blkif->vbd_lock); } - - -static void vbd_probe_single( - blkif_t *blkif, vdisk_t *vbd_info, struct vbd *vbd) -{ - vbd_info->device = vbd->vdevice; - vbd_info->info = vbd->type | (vbd->readonly ? VDISK_READONLY : 0); - vbd_info->capacity = vbd_sz(vbd); - vbd_info->sector_size = bdev_hardsect_size(vbd->bdev); -} - - -int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds) -{ - int rc = 0, nr_vbds = 0; - rb_node_t *rb; - - spin_lock(&blkif->vbd_lock); - - if ( (rb = blkif->vbd_rb.rb_node) == NULL ) - goto out; - - new_subtree: - /* STEP 1. Find least node (it'll be left-most). */ - while ( rb->rb_left != NULL ) - rb = rb->rb_left; - - for ( ; ; ) - { - /* STEP 2. Dealt with left subtree. Now process current node. */ - vbd_probe_single(blkif, &vbd_info[nr_vbds], - rb_entry(rb, struct vbd, rb)); - if ( ++nr_vbds == max_vbds ) - goto out; - - /* STEP 3. Process right subtree, if any. */ - if ( rb->rb_right != NULL ) - { - rb = rb->rb_right; - goto new_subtree; - } - - /* STEP 4. Done both subtrees. Head back through ancesstors. */ - for ( ; ; ) - { - /* We're done when we get back to the root node. */ - if ( rb->rb_parent == NULL ) - goto out; - /* If we are left of parent, then parent is next to process. */ - if ( rb->rb_parent->rb_left == rb ) - break; - /* If we are right of parent, then we climb to grandparent. */ - rb = rb->rb_parent; - } - - rb = rb->rb_parent; - } - - out: - spin_unlock(&blkif->vbd_lock); - return (rc == 0) ? nr_vbds : rc; -} - int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation) { @@ -264,9 +193,9 @@ while ( rb != NULL ) { vbd = rb_entry(rb, struct vbd, rb); - if ( req->dev < vbd->vdevice ) + if ( req->dev < vbd->handle ) rb = rb->rb_left; - else if ( req->dev > vbd->vdevice ) + else if ( req->dev > vbd->handle ) rb = rb->rb_right; else goto found; diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Fri Aug 19 18:19:28 2005 @@ -53,8 +53,8 @@ #include <linux/sched.h> #include <linux/interrupt.h> #include <scsi/scsi.h> -#include <asm-xen/ctrl_if.h> #include <asm-xen/evtchn.h> +#include <asm-xen/xenbus.h> #ifdef CONFIG_XEN_BLKDEV_GRANT #include <asm-xen/xen-public/grant_table.h> #include <asm-xen/gnttab.h> @@ -65,22 +65,14 @@ /* Control whether runtime update of vbds is enabled. */ #define ENABLE_VBD_UPDATE 1 -#if ENABLE_VBD_UPDATE -static void vbd_update(void); -#else -static void vbd_update(void){}; -#endif - #define BLKIF_STATE_CLOSED 0 #define BLKIF_STATE_DISCONNECTED 1 #define BLKIF_STATE_CONNECTED 2 -static int blkif_handle = 0; static unsigned int blkif_state = BLKIF_STATE_CLOSED; static unsigned int blkif_evtchn = 0; - -static int blkif_control_rsp_valid; -static blkif_response_t blkif_control_rsp; +static unsigned int blkif_vbds = 0; +static unsigned int blkif_vbds_connected = 0; static blkif_front_ring_t blk_ring; @@ -92,6 +84,7 @@ #define MAXIMUM_OUTSTANDING_BLOCK_REQS \ (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE) #define GRANTREF_INVALID (1<<15) +static int shmem_ref; #endif static struct blk_shadow { @@ -105,7 +98,7 @@ static void kick_pending_request_queues(void); -int __init xlblk_init(void); +static int __init xlblk_init(void); static void blkif_completion(struct blk_shadow *s); @@ -179,19 +172,6 @@ module_init(xlblk_init); -#if ENABLE_VBD_UPDATE -static void update_vbds_task(void *unused) -{ - xlvbd_update_vbds(); -} - -static void vbd_update(void) -{ - static DECLARE_WORK(update_tq, update_vbds_task, NULL); - schedule_work(&update_tq); -} -#endif /* ENABLE_VBD_UPDATE */ - static struct xlbd_disk_info *head_waiting = NULL; static void kick_pending_request_queues(void) { @@ -221,16 +201,7 @@ int blkif_release(struct inode *inode, struct file *filep) { - struct gendisk *gd = inode->i_bdev->bd_disk; - struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data; - - /* - * When usage drops to zero it may allow more VBD updates to occur. - * Update of usage count is protected by a per-device semaphore. - */ - if ( --di->mi->usage == 0 ) - vbd_update(); - + /* FIXME: This is where we can actually free up majors, etc. --RR */ return 0; } @@ -301,7 +272,7 @@ ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ; ring_req->sector_number = (blkif_sector_t)req->sector; - ring_req->device = di->xd_device; + ring_req->handle = di->handle; ring_req->nr_segments = 0; rq_for_each_bio(bio, req) @@ -446,10 +417,6 @@ end_that_request_last(req); break; - case BLKIF_OP_PROBE: - memcpy(&blkif_control_rsp, bret, sizeof(*bret)); - blkif_control_rsp_valid = 1; - break; default: BUG(); } @@ -483,28 +450,6 @@ #define blkif_io_lock io_request_lock /*============================================================================*/ -#if ENABLE_VBD_UPDATE - -/* - * blkif_update_int/update-vbds_task - handle VBD update events. - * Schedule a task for keventd to run, which will update the VBDs and perform - * the corresponding updates to our view of VBD state. - */ -static void update_vbds_task(void *unused) -{ - xlvbd_update_vbds(); -} - -static void vbd_update(void) -{ - static struct tq_struct update_tq; - update_tq.routine = update_vbds_task; - schedule_task(&update_tq); -} - -#endif /* ENABLE_VBD_UPDATE */ -/*============================================================================*/ - static void kick_pending_request_queues(void) { /* We kick pending request queues if the ring is reasonably empty. */ @@ -757,7 +702,8 @@ char * buffer, unsigned long sector_number, unsigned short nr_sectors, - kdev_t device) + kdev_t device, + blkif_vdev_t handle) { unsigned long buffer_ma = virt_to_bus(buffer); unsigned long xid; @@ -871,7 +817,7 @@ req->id = xid; req->operation = operation; req->sector_number = (blkif_sector_t)sector_number; - req->device = device; + req->handle = handle; req->nr_segments = 1; #ifdef CONFIG_XEN_BLKDEV_GRANT /* install a grant reference. */ @@ -1047,108 +993,10 @@ /***************************** COMMON CODE *******************************/ -#ifdef CONFIG_XEN_BLKDEV_GRANT -void blkif_control_probe_send(blkif_request_t *req, blkif_response_t *rsp, - unsigned long address) -{ - int ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); - ASSERT( ref != -ENOSPC ); - - gnttab_grant_foreign_access_ref( ref, rdomid, address >> PAGE_SHIFT, 0 ); - - req->frame_and_sects[0] = blkif_fas_from_gref(ref, 0, (PAGE_SIZE/512)-1); - - blkif_control_send(req, rsp); -} -#endif - -void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp) -{ - unsigned long flags, id; - blkif_request_t *req_d; - - retry: - while ( RING_FULL(&blk_ring) ) - { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - spin_lock_irqsave(&blkif_io_lock, flags); - if ( RING_FULL(&blk_ring) ) - { - spin_unlock_irqrestore(&blkif_io_lock, flags); - goto retry; - } - - DISABLE_SCATTERGATHER(); - req_d = RING_GET_REQUEST(&blk_ring, blk_ring.req_prod_pvt); - *req_d = *req; - - id = GET_ID_FROM_FREELIST(); - req_d->id = id; - blk_shadow[id].request = (unsigned long)req; - - pickle_request(&blk_shadow[id], req); - - blk_ring.req_prod_pvt++; - flush_requests(); - - spin_unlock_irqrestore(&blkif_io_lock, flags); - - while ( !blkif_control_rsp_valid ) - { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - memcpy(rsp, &blkif_control_rsp, sizeof(*rsp)); - blkif_control_rsp_valid = 0; -} - - -/* Send a driver status notification to the domain controller. */ -static void send_driver_status(int ok) -{ - ctrl_msg_t cmsg = { - .type = CMSG_BLKIF_FE, - .subtype = CMSG_BLKIF_FE_DRIVER_STATUS, - .length = sizeof(blkif_fe_driver_status_t), - }; - blkif_fe_driver_status_t *msg = (void*)cmsg.msg; - - msg->status = (ok ? BLKIF_DRIVER_STATUS_UP : BLKIF_DRIVER_STATUS_DOWN); - - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); -} - -/* Tell the controller to bring up the interface. */ -static void blkif_send_interface_connect(void) -{ - ctrl_msg_t cmsg = { - .type = CMSG_BLKIF_FE, - .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT, - .length = sizeof(blkif_fe_interface_connect_t), - }; - blkif_fe_interface_connect_t *msg = (void*)cmsg.msg; - - msg->handle = 0; - msg->shmem_frame = (virt_to_machine(blk_ring.sring) >> PAGE_SHIFT); - -#ifdef CONFIG_XEN_BLKDEV_GRANT - msg->shmem_ref = gnttab_claim_grant_reference( &gref_head, gref_terminal ); - ASSERT( msg->shmem_ref != -ENOSPC ); - gnttab_grant_foreign_access_ref ( msg->shmem_ref , rdomid, msg->shmem_frame, 0 ); -#endif - - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); -} - static void blkif_free(void) { /* Prevent new requests being issued until we fix things up. */ spin_lock_irq(&blkif_io_lock); - recovery = 1; blkif_state = BLKIF_STATE_DISCONNECTED; spin_unlock_irq(&blkif_io_lock); @@ -1160,31 +1008,6 @@ } unbind_evtchn_from_irqhandler(blkif_evtchn, NULL); blkif_evtchn = 0; -} - -static void blkif_close(void) -{ -} - -/* Move from CLOSED to DISCONNECTED state. */ -static void blkif_disconnect(void) -{ - blkif_sring_t *sring; - - if ( blk_ring.sring != NULL ) - free_page((unsigned long)blk_ring.sring); - - sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL); - SHARED_RING_INIT(sring); - FRONT_RING_INIT(&blk_ring, sring, PAGE_SIZE); - blkif_state = BLKIF_STATE_DISCONNECTED; - blkif_send_interface_connect(); -} - -static void blkif_reset(void) -{ - blkif_free(); - blkif_disconnect(); } static void blkif_recover(void) @@ -1257,11 +1080,14 @@ blkif_state = BLKIF_STATE_CONNECTED; } -static void blkif_connect(blkif_fe_interface_status_t *status) +static void blkif_connect(u16 evtchn, domid_t domid) { int err = 0; - blkif_evtchn = status->evtchn; + blkif_evtchn = evtchn; +#ifdef CONFIG_XEN_BLKDEV_GRANT + rdomid = domid; +#endif err = bind_evtchn_to_irqhandler( blkif_evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL); @@ -1270,142 +1096,318 @@ WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); return; } - - if ( recovery ) - { - blkif_recover(); - } - else - { - /* Transition to connected in case we need to do - * a partition probe on a whole disk. */ - blkif_state = BLKIF_STATE_CONNECTED; - - /* Probe for discs attached to the interface. */ - xlvbd_init(); - } - - /* Kick pending requests. */ - spin_lock_irq(&blkif_io_lock); - kick_pending_request_queues(); - spin_unlock_irq(&blkif_io_lock); -} - -static void unexpected(blkif_fe_interface_status_t *status) -{ - DPRINTK(" Unexpected blkif status %u in state %u\n", - status->status, blkif_state); -} - -static void blkif_status(blkif_fe_interface_status_t *status) -{ +} + + +static struct xenbus_device_id blkfront_ids[] = { + { "vbd" }, + { "" } +}; + +struct blkfront_info +{ + /* We watch the backend */ + struct xenbus_watch watch; + int vdevice; + u16 handle; + int connected; + struct xenbus_device *dev; + char *backend; +}; + +static void watch_for_status(struct xenbus_watch *watch, const char *node) +{ + struct blkfront_info *info; + unsigned int binfo; + unsigned long sectors, sector_size; + int err; + + info = container_of(watch, struct blkfront_info, watch); + node += strlen(watch->node); + + /* FIXME: clean up when error on the other end. */ + if (info->connected) + return; + + err = xenbus_gather(watch->node, + "sectors", "%lu", §ors, + "info", "%u", &binfo, + "sector-size", "%lu", §or_size, + NULL); + + if (err) + xenbus_dev_error(info->dev, err, "reading backend fields"); + else { + xlvbd_add(sectors, info->vdevice, info->handle, binfo, + sector_size); + info->connected = 1; + + /* First to connect? blkif is now connected. */ + if (blkif_vbds_connected++ == 0) + blkif_state = BLKIF_STATE_CONNECTED; + + xenbus_dev_ok(info->dev); + + /* Kick pending requests. */ + spin_lock_irq(&blkif_io_lock); + kick_pending_request_queues(); + spin_unlock_irq(&blkif_io_lock); + } +} + +static int setup_blkring(struct xenbus_device *dev, unsigned int backend_id) +{ + blkif_sring_t *sring; + evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound }; + int err; + + sring = (void *)__get_free_page(GFP_KERNEL); + if (!sring) { + xenbus_dev_error(dev, -ENOMEM, "allocating shared ring"); + return -ENOMEM; + } + SHARED_RING_INIT(sring); + FRONT_RING_INIT(&blk_ring, sring, PAGE_SIZE); + #ifdef CONFIG_XEN_BLKDEV_GRANT - rdomid = status->domid; /* need to set rdomid early */ -#endif - - if ( status->handle != blkif_handle ) - { - WPRINTK(" Invalid blkif: handle=%u\n", status->handle); - unexpected(status); - return; - } - - switch ( status->status ) - { - case BLKIF_INTERFACE_STATUS_CLOSED: - switch ( blkif_state ) - { - case BLKIF_STATE_CLOSED: - unexpected(status); - break; - case BLKIF_STATE_DISCONNECTED: - case BLKIF_STATE_CONNECTED: - unexpected(status); - blkif_close(); - break; - } - break; - - case BLKIF_INTERFACE_STATUS_DISCONNECTED: - switch ( blkif_state ) - { - case BLKIF_STATE_CLOSED: - blkif_disconnect(); - break; - case BLKIF_STATE_DISCONNECTED: - case BLKIF_STATE_CONNECTED: - /* unexpected(status); */ /* occurs during suspend/resume */ - blkif_reset(); - break; - } - break; - - case BLKIF_INTERFACE_STATUS_CONNECTED: - switch ( blkif_state ) - { - case BLKIF_STATE_CLOSED: - unexpected(status); - blkif_disconnect(); - blkif_connect(status); - break; - case BLKIF_STATE_DISCONNECTED: - blkif_connect(status); - break; - case BLKIF_STATE_CONNECTED: - unexpected(status); - blkif_connect(status); - break; - } - break; - - case BLKIF_INTERFACE_STATUS_CHANGED: - switch ( blkif_state ) - { - case BLKIF_STATE_CLOSED: - case BLKIF_STATE_DISCONNECTED: - unexpected(status); - break; - case BLKIF_STATE_CONNECTED: - vbd_update(); - break; - } - break; - - default: - WPRINTK(" Invalid blkif status: %d\n", status->status); - break; - } -} - - -static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) -{ - switch ( msg->subtype ) - { - case CMSG_BLKIF_FE_INTERFACE_STATUS: - blkif_status((blkif_fe_interface_status_t *) - &msg->msg[0]); - break; - default: - msg->length = 0; - break; - } - - ctrl_if_send_response(msg); -} - -int wait_for_blkif(void) + shmem_ref = gnttab_claim_grant_reference(&gref_head, + gref_terminal); + ASSERT(shmem_ref != -ENOSPC); + gnttab_grant_foreign_access_ref(shmem_ref, + backend_id, + virt_to_mfn(blk_ring.sring), + 0); +#endif + + op.u.alloc_unbound.dom = backend_id; + err = HYPERVISOR_event_channel_op(&op); + if (err) { + free_page((unsigned long)blk_ring.sring); + blk_ring.sring = 0; + xenbus_dev_error(dev, err, "allocating event channel"); + return err; + } + blkif_connect(op.u.alloc_unbound.port, backend_id); + return 0; +} + +/* Common code used when first setting up, and when resuming. */ +static int talk_to_backend(struct xenbus_device *dev, + struct blkfront_info *info) +{ + char *backend; + const char *message; + int err, backend_id; + + backend = xenbus_read(dev->nodename, "backend", NULL); + if (IS_ERR(backend)) { + err = PTR_ERR(backend); + if (err == -ENOENT) + goto out; + xenbus_dev_error(dev, err, "reading %s/backend", + dev->nodename); + goto out; + } + if (strlen(backend) == 0) { + err = -ENOENT; + goto free_backend; + } + + /* FIXME: This driver can't handle backends on different + * domains. Check and fail gracefully. */ + err = xenbus_scanf(dev->nodename, "backend-id", "%i", &backend_id); + if (err == -ENOENT) + goto free_backend; + if (err < 0) { + xenbus_dev_error(dev, err, "reading %s/backend-id", + dev->nodename); + goto free_backend; + } + + /* First device? We create shared ring, alloc event channel. */ + if (blkif_vbds == 0) { + err = setup_blkring(dev, backend_id); + if (err) + goto free_backend; + } + + err = xenbus_transaction_start(dev->nodename); + if (err) { + xenbus_dev_error(dev, err, "starting transaction"); + goto destroy_blkring; + } + +#ifdef CONFIG_XEN_BLKDEV_GRANT + err = xenbus_printf(dev->nodename, "grant-id","%u", shmem_ref); + if (err) { + message = "writing grant-id"; + goto abort_transaction; + } +#else + err = xenbus_printf(dev->nodename, "shared-frame", "%lu", + virt_to_mfn(blk_ring.sring)); + if (err) { + message = "writing shared-frame"; + goto abort_transaction; + } +#endif + err = xenbus_printf(dev->nodename, + "event-channel", "%u", blkif_evtchn); + if (err) { + message = "writing event-channel"; + goto abort_transaction; + } + + info->watch.node = info->backend = backend; + info->watch.callback = watch_for_status; + + err = register_xenbus_watch(&info->watch); + if (err) { + message = "registering watch on backend"; + goto abort_transaction; + } + + err = xenbus_transaction_end(0); + if (err) { + xenbus_dev_error(dev, err, "completing transaction"); + goto destroy_blkring; + } + return 0; + +abort_transaction: + xenbus_transaction_end(1); + /* Have to do this *outside* transaction. */ + xenbus_dev_error(dev, err, "%s", message); +destroy_blkring: + if (blkif_vbds == 0) + blkif_free(); +free_backend: + kfree(backend); +out: + printk("%s:%u = %i\n", __FILE__, __LINE__, err); + return err; +} + +/* Setup supplies the backend dir, virtual device. + + We place an event channel and shared frame entries. + We watch backend to wait if it's ok. */ +static int blkfront_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) +{ + int err; + struct blkfront_info *info; + int vdevice; + + /* FIXME: Use dynamic device id if this is not set. */ + err = xenbus_scanf(dev->nodename, "virtual-device", "%i", &vdevice); + if (err == -ENOENT) + return err; + if (err < 0) { + xenbus_dev_error(dev, err, "reading virtual-device"); + return err; + } + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + xenbus_dev_error(dev, err, "allocating info structure"); + return err; + } + info->dev = dev; + info->vdevice = vdevice; + info->connected = 0; + /* Front end dir is a number, which is used as the id. */ + info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0); + dev->data = info; + + err = talk_to_backend(dev, info); + if (err) { + kfree(info); + return err; + } + + /* Call once in case entries already there. */ + watch_for_status(&info->watch, info->watch.node); + blkif_vbds++; + return 0; +} + +static int blkfront_remove(struct xenbus_device *dev) +{ + struct blkfront_info *info = dev->data; + + if (info->backend) + unregister_xenbus_watch(&info->watch); + + if (info->connected) { + xlvbd_del(info->handle); + blkif_vbds_connected--; + } + kfree(info->backend); + kfree(info); + + if (--blkif_vbds == 0) + blkif_free(); + + return 0; +} + +static int blkfront_suspend(struct xenbus_device *dev) +{ + struct blkfront_info *info = dev->data; + + unregister_xenbus_watch(&info->watch); + kfree(info->backend); + info->backend = NULL; + + if (--blkif_vbds == 0) { + recovery = 1; + blkif_free(); + } + + return 0; +} + +static int blkfront_resume(struct xenbus_device *dev) +{ + struct blkfront_info *info = dev->data; + int err; + + /* FIXME: Check geometry hasn't changed here... */ + err = talk_to_backend(dev, info); + if (!err) { + if (blkif_vbds++ == 0) + blkif_recover(); + } + return err; +} + +static struct xenbus_driver blkfront = { + .name = "vbd", + .owner = THIS_MODULE, + .ids = blkfront_ids, + .probe = blkfront_probe, + .remove = blkfront_remove, + .resume = blkfront_resume, + .suspend = blkfront_suspend, +}; + +static void __init init_blk_xenbus(void) +{ + xenbus_register_device(&blkfront); +} + +static int wait_for_blkif(void) { int err = 0; int i; - send_driver_status(1); /* * We should read 'nr_interfaces' from response message and wait * for notifications before proceeding. For now we assume that we * will be notified of exactly one interface. */ - for ( i=0; (blkif_state != BLKIF_STATE_CONNECTED) && (i < 10*HZ); i++ ) + for ( i=0; blkif_state != BLKIF_STATE_CONNECTED && (i < 10*HZ); i++ ) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); @@ -1419,7 +1421,7 @@ return err; } -int __init xlblk_init(void) +static int __init xlblk_init(void) { int i; @@ -1443,27 +1445,11 @@ blk_shadow[i].req.id = i+1; blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; - (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); + init_blk_xenbus(); wait_for_blkif(); return 0; -} - -void blkdev_suspend(void) -{ -} - -void blkdev_resume(void) -{ -#ifdef CONFIG_XEN_BLKDEV_GRANT - int i, j; - for ( i = 0; i < BLK_RING_SIZE; i++ ) - for ( j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++ ) - blk_shadow[i].req.frame_and_sects[j] |= GRANTREF_INVALID; -#endif - send_driver_status(1); } static void blkif_completion(struct blk_shadow *s) diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkfront/block.h --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Fri Aug 19 18:19:28 2005 @@ -100,6 +100,7 @@ struct xlbd_disk_info { int xd_device; + blkif_vdev_t handle; struct xlbd_major_info *mi; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) struct xlbd_disk_info *next_waiting; @@ -119,17 +120,10 @@ unsigned command, unsigned long argument); extern int blkif_check(dev_t dev); extern int blkif_revalidate(dev_t dev); -extern void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp); -#ifdef CONFIG_XEN_BLKDEV_GRANT -extern void blkif_control_probe_send( - blkif_request_t *req, blkif_response_t *rsp, unsigned long address); -#endif extern void do_blkif_request (request_queue_t *rq); -extern void xlvbd_update_vbds(void); - /* Virtual block-device subsystem. */ -extern int xlvbd_init(void); -extern void xlvbd_cleanup(void); - +int xlvbd_add(blkif_sector_t capacity, int device, blkif_vdev_t handle, + u16 info, u16 sector_size); +void xlvbd_del(blkif_vdev_t handle); #endif /* __XEN_DRIVERS_BLOCK_H__ */ diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Fri Aug 19 18:19:28 2005 @@ -46,8 +46,9 @@ struct lvdisk { blkif_sector_t capacity; /* 0: Size in terms of 512-byte sectors. */ - blkif_vdev_t device; /* 8: Device number (opaque 16 bit value). */ - u16 info; + blkif_vdev_t handle; /* 8: Device number (opaque 16 bit value). */ + u16 info; + dev_t dev; struct list_head list; }; @@ -85,7 +86,7 @@ /* Information about our VBDs. */ #define MAX_VBDS 64 -struct list_head vbds_list; +static LIST_HEAD(vbds_list); #define MAJOR_XEN(dev) ((dev)>>8) #define MINOR_XEN(dev) ((dev) & 0xff) @@ -116,49 +117,6 @@ { list_del(&disk->list); kfree(disk); -} - -static vdisk_t *xlvbd_probe(int *ret) -{ - blkif_response_t rsp; - blkif_request_t req; - vdisk_t *disk_info = NULL; - unsigned long buf; - int nr; - - buf = __get_free_page(GFP_KERNEL); - if ((void *)buf == NULL) - goto out; - - memset(&req, 0, sizeof(req)); - req.operation = BLKIF_OP_PROBE; - req.nr_segments = 1; -#ifdef CONFIG_XEN_BLKDEV_GRANT - blkif_control_probe_send(&req, &rsp, - (unsigned long)(virt_to_machine(buf))); -#else - req.frame_and_sects[0] = blkif_fas(virt_to_machine(buf), 0, (PAGE_SIZE/512)-1); - - blkif_control_send(&req, &rsp); -#endif - if ( rsp.status <= 0 ) { - WPRINTK("Could not probe disks (%d)\n", rsp.status); - goto out; - } - nr = rsp.status; - if ( nr > MAX_VBDS ) - nr = MAX_VBDS; - - disk_info = kmalloc(nr * sizeof(vdisk_t), GFP_KERNEL); - if (disk_info != NULL) - memcpy(disk_info, (void *) buf, nr * sizeof(vdisk_t)); - - if (ret != NULL) - *ret = nr; - -out: - free_page(buf); - return disk_info; } static struct xlbd_major_info *xlbd_alloc_major_info( @@ -189,6 +147,7 @@ break; } + printk("Registering block device major %i\n", ptr->major); if (register_blkdev(ptr->major, ptr->type->devname)) { WPRINTK("can't get major %d with name %s\n", ptr->major, ptr->type->devname); @@ -231,7 +190,7 @@ xlbd_alloc_major_info(major, minor, index)); } -static int xlvbd_init_blk_queue(struct gendisk *gd, vdisk_t *disk) +static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) { request_queue_t *rq; @@ -242,7 +201,7 @@ elevator_init(rq, "noop"); /* Hard sector size and max sectors impersonate the equiv. hardware. */ - blk_queue_hardsect_size(rq, disk->sector_size); + blk_queue_hardsect_size(rq, sector_size); blk_queue_max_sectors(rq, 512); /* Each segment in a request is up to an aligned page in size. */ @@ -261,8 +220,9 @@ return 0; } -struct gendisk *xlvbd_alloc_gendisk( - struct xlbd_major_info *mi, int minor, vdisk_t *disk) +static struct gendisk *xlvbd_alloc_gendisk( + struct xlbd_major_info *mi, int minor, blkif_sector_t capacity, + int device, blkif_vdev_t handle, u16 info, u16 sector_size) { struct gendisk *gd; struct xlbd_disk_info *di; @@ -273,7 +233,8 @@ return NULL; memset(di, 0, sizeof(*di)); di->mi = mi; - di->xd_device = disk->device; + di->xd_device = device; + di->handle = handle; if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0) nr_minors = 1 << mi->type->partn_shift; @@ -296,22 +257,22 @@ gd->first_minor = minor; gd->fops = &xlvbd_block_fops; gd->private_data = di; - set_capacity(gd, disk->capacity); - - if (xlvbd_init_blk_queue(gd, disk)) { + set_capacity(gd, capacity); + + if (xlvbd_init_blk_queue(gd, sector_size)) { del_gendisk(gd); goto out; } di->rq = gd->queue; - if (disk->info & VDISK_READONLY) + if (info & VDISK_READONLY) set_disk_ro(gd, 1); - if (disk->info & VDISK_REMOVABLE) + if (info & VDISK_REMOVABLE) gd->flags |= GENHD_FL_REMOVABLE; - if (disk->info & VDISK_CDROM) + if (info & VDISK_CDROM) gd->flags |= GENHD_FL_CD; add_disk(gd); @@ -323,38 +284,36 @@ return NULL; } -static int xlvbd_device_add(struct list_head *list, vdisk_t *disk) +int xlvbd_add(blkif_sector_t capacity, int device, blkif_vdev_t handle, + u16 info, u16 sector_size) { struct lvdisk *new; - int minor; - dev_t device; struct block_device *bd; struct gendisk *gd; struct xlbd_major_info *mi; - mi = xlbd_get_major_info(disk->device); + mi = xlbd_get_major_info(device); if (mi == NULL) return -EPERM; new = xlvbd_device_alloc(); if (new == NULL) - return -1; - new->capacity = disk->capacity; - new->device = disk->device; - new->info = disk->info; - - minor = MINOR_XEN(disk->device); - device = MKDEV(mi->major, minor); - - bd = bdget(device); + return -ENOMEM; + new->capacity = capacity; + new->info = info; + new->handle = handle; + new->dev = MKDEV(MAJOR_XEN(device), MINOR_XEN(device)); + + bd = bdget(new->dev); if (bd == NULL) goto out; - gd = xlvbd_alloc_gendisk(mi, minor, disk); + gd = xlvbd_alloc_gendisk(mi, MINOR_XEN(device), capacity, device, handle, + info, sector_size); if (gd == NULL) goto out_bd; - list_add(&new->list, list); + list_add(&new->list, &vbds_list); out_bd: bdput(bd); out: @@ -363,27 +322,26 @@ static int xlvbd_device_del(struct lvdisk *disk) { - dev_t device; struct block_device *bd; struct gendisk *gd; struct xlbd_disk_info *di; int ret = 0, unused; request_queue_t *rq; - device = MKDEV(MAJOR_XEN(disk->device), MINOR_XEN(disk->device)); - - bd = bdget(device); + bd = bdget(disk->dev); if (bd == NULL) return -1; - gd = get_gendisk(device, &unused); + gd = get_gendisk(disk->dev, &unused); di = gd->private_data; +#if 0 /* This is wrong: hda and hdb share same major, for example. */ if (di->mi->usage != 0) { - WPRINTK("disk removal failed: used [dev=%x]\n", device); + WPRINTK("disk removal failed: used [dev=%x]\n", disk->dev); ret = -1; goto out; } +#endif rq = gd->queue; del_gendisk(gd); @@ -391,110 +349,19 @@ blk_cleanup_queue(rq); xlvbd_device_free(disk); -out: bdput(bd); return ret; } -static int xlvbd_device_update(struct lvdisk *ldisk, vdisk_t *disk) -{ - dev_t device; - struct block_device *bd; - struct gendisk *gd; - int unused; - - if ((ldisk->capacity == disk->capacity) && (ldisk->info == disk->info)) - return 0; - - device = MKDEV(MAJOR_XEN(ldisk->device), MINOR_XEN(ldisk->device)); - - bd = bdget(device); - if (bd == NULL) - return -1; - - gd = get_gendisk(device, &unused); - set_capacity(gd, disk->capacity); - ldisk->capacity = disk->capacity; - - bdput(bd); - - return 0; -} - -void xlvbd_refresh(void) -{ - vdisk_t *newdisks; - struct list_head *tmp, *tmp2; - struct lvdisk *disk; - int i, nr; - - newdisks = xlvbd_probe(&nr); - if (newdisks == NULL) { - WPRINTK("failed to probe\n"); - return; - } - - i = 0; - list_for_each_safe(tmp, tmp2, &vbds_list) { - disk = list_entry(tmp, struct lvdisk, list); - - for (i = 0; i < nr; i++) { - if ( !newdisks[i].device ) - continue; - if ( disk->device == newdisks[i].device ) { - xlvbd_device_update(disk, &newdisks[i]); - newdisks[i].device = 0; - break; - } - } - if (i == nr) { - xlvbd_device_del(disk); - newdisks[i].device = 0; - } - } - for (i = 0; i < nr; i++) - if ( newdisks[i].device ) - xlvbd_device_add(&vbds_list, &newdisks[i]); - kfree(newdisks); -} - -/* - * xlvbd_update_vbds - reprobes the VBD status and performs updates driver - * state. The VBDs need to be updated in this way when the domain is - * initialised and also each time we receive an XLBLK_UPDATE event. - */ -void xlvbd_update_vbds(void) -{ - xlvbd_refresh(); -} - -/* - * Set up all the linux device goop for the virtual block devices - * (vbd's) that we know about. Note that although from the backend - * driver's p.o.v. VBDs are addressed simply an opaque 16-bit device - * number, the domain creation tools conventionally allocate these - * numbers to correspond to those used by 'real' linux -- this is just - * for convenience as it means e.g. that the same /etc/fstab can be - * used when booting with or without Xen. - */ -int xlvbd_init(void) -{ - int i, nr; - vdisk_t *disks; - - INIT_LIST_HEAD(&vbds_list); - - memset(major_info, 0, sizeof(major_info)); - - disks = xlvbd_probe(&nr); - if (disks == NULL) { - WPRINTK("failed to probe\n"); - return -1; - } - - for (i = 0; i < nr; i++) - xlvbd_device_add(&vbds_list, &disks[i]); - - kfree(disks); - return 0; -} +void xlvbd_del(blkif_vdev_t handle) +{ + struct lvdisk *i; + + list_for_each_entry(i, &vbds_list, list) { + if (i->handle == handle) { + xlvbd_device_del(i); + return; + } + } + BUG(); +} diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blktap/blktap.h --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.h Fri Aug 19 18:19:28 2005 @@ -87,7 +87,7 @@ struct work_struct work; #ifdef CONFIG_XEN_BLKDEV_GRANT u16 shmem_handle; - memory_t shmem_vaddr; + unsigned long shmem_vaddr; grant_ref_t shmem_ref; #endif } blkif_t; diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c Fri Aug 19 18:19:28 2005 @@ -320,7 +320,7 @@ }; blkif_fe_interface_connect_t *msg = (void*)cmsg.msg; msg->handle = 0; - msg->shmem_frame = virt_to_machine(blktap_be_ring.sring) >> PAGE_SHIFT; + msg->shmem_frame = virt_to_mfn(blktap_be_ring.sring); ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); } diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/netback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Aug 19 18:19:28 2005 @@ -49,13 +49,13 @@ unsigned long tx_shmem_frame; #ifdef CONFIG_XEN_NETDEV_GRANT_TX u16 tx_shmem_handle; - memory_t tx_shmem_vaddr; + unsigned long tx_shmem_vaddr; grant_ref_t tx_shmem_ref; #endif unsigned long rx_shmem_frame; #ifdef CONFIG_XEN_NETDEV_GRANT_RX u16 rx_shmem_handle; - memory_t rx_shmem_vaddr; + unsigned long rx_shmem_vaddr; grant_ref_t rx_shmem_ref; #endif unsigned int evtchn; diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Fri Aug 19 18:19:28 2005 @@ -43,7 +43,7 @@ static int make_rx_response(netif_t *netif, u16 id, s8 st, - memory_t addr, + unsigned long addr, u16 size, u16 csum_valid); @@ -251,7 +251,7 @@ #else struct mmuext_op *mmuext; #endif - unsigned long vdata, mdata, new_mfn; + unsigned long vdata, old_mfn, new_mfn; struct sk_buff_head rxq; struct sk_buff *skb; u16 notify_list[NETIF_RX_RING_SIZE]; @@ -271,7 +271,7 @@ { netif = netdev_priv(skb->dev); vdata = (unsigned long)skb->data; - mdata = virt_to_machine(vdata); + old_mfn = virt_to_mfn(vdata); /* Memory squeeze? Back off for an arbitrary while. */ if ( (new_mfn = alloc_mfn()) == 0 ) @@ -293,7 +293,7 @@ mcl++; #ifdef CONFIG_XEN_NETDEV_GRANT_RX - gop->mfn = mdata >> PAGE_SHIFT; + gop->mfn = old_mfn; gop->domid = netif->domid; gop->handle = netif->rx->ring[ MASK_NETIF_RX_IDX(netif->rx_resp_prod_copy)].req.gref; @@ -308,7 +308,7 @@ mcl++; mmuext->cmd = MMUEXT_REASSIGN_PAGE; - mmuext->mfn = mdata >> PAGE_SHIFT; + mmuext->mfn = old_mfn; mmuext++; #endif mmu->ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; @@ -318,7 +318,7 @@ __skb_queue_tail(&rxq, skb); #ifdef DEBUG_GRANT - dump_packet('a', mdata, vdata); + dump_packet('a', old_mfn, vdata); #endif /* Filled the batch queue? */ if ( (mcl - rx_mcl) == ARRAY_SIZE(rx_mcl) ) @@ -345,10 +345,8 @@ mcl = rx_mcl; #ifdef CONFIG_XEN_NETDEV_GRANT_RX - if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_donate, - grant_rx_op, gop - grant_rx_op))) { - BUG(); - } + BUG_ON(HYPERVISOR_grant_table_op( + GNTTABOP_donate, grant_rx_op, gop - grant_rx_op)); gop = grant_rx_op; #else mmuext = rx_mmuext; @@ -361,10 +359,9 @@ /* Rederive the machine addresses. */ new_mfn = mcl[0].args[1] >> PAGE_SHIFT; #ifdef CONFIG_XEN_NETDEV_GRANT_RX - mdata = (unsigned long)skb->data & ~PAGE_MASK; -#else - mdata = ((mmuext[0].mfn << PAGE_SHIFT) | - ((unsigned long)skb->data & ~PAGE_MASK)); + old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */ +#else + old_mfn = mmuext[0].mfn; #endif atomic_set(&(skb_shinfo(skb)->dataref), 1); skb_shinfo(skb)->nr_frags = 0; @@ -379,18 +376,20 @@ /* Check the reassignment error code. */ status = NETIF_RSP_OKAY; #ifdef CONFIG_XEN_NETDEV_GRANT_RX - BUG_ON(gop->status != 0); + BUG_ON(gop->status != 0); /* XXX */ #else if ( unlikely(mcl[1].result != 0) ) { DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid); - free_mfn(mdata >> PAGE_SHIFT); + free_mfn(old_mfn); status = NETIF_RSP_ERROR; } #endif evtchn = netif->evtchn; id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id; - if ( make_rx_response(netif, id, status, mdata, + if ( make_rx_response(netif, id, status, + (old_mfn << PAGE_SHIFT) | /* XXX */ + ((unsigned long)skb->data & ~PAGE_MASK), size, skb->proto_csum_valid) && (rx_notify[evtchn] == 0) ) { @@ -888,7 +887,7 @@ static int make_rx_response(netif_t *netif, u16 id, s8 st, - memory_t addr, + unsigned long addr, u16 size, u16 csum_valid) { diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Aug 19 18:19:28 2005 @@ -448,11 +448,10 @@ } grant_rx_ref[id] = ref; gnttab_grant_foreign_transfer_ref(ref, rdomid, - virt_to_machine( - skb->head) >> PAGE_SHIFT); + virt_to_mfn(skb->head)); np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref; #endif - rx_pfn_array[i] = virt_to_machine(skb->head) >> PAGE_SHIFT; + rx_pfn_array[i] = virt_to_mfn(skb->head); /* Remove this page from pseudo phys map before passing back to Xen. */ phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] @@ -543,13 +542,14 @@ printk(KERN_ALERT "#### netfront can't claim tx grant reference\n"); BUG(); } - mfn = virt_to_machine(skb->data) >> PAGE_SHIFT; + mfn = virt_to_mfn(skb->data); gnttab_grant_foreign_access_ref(ref, rdomid, mfn, GNTMAP_readonly); - tx->addr = (ref << PAGE_SHIFT) | ((unsigned long)skb->data & ~PAGE_MASK); + tx->addr = ref << PAGE_SHIFT; grant_tx_ref[id] = ref; #else - tx->addr = virt_to_machine(skb->data); -#endif + tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; +#endif + tx->addr |= (unsigned long)skb->data & ~PAGE_MASK; tx->size = skb->len; tx->csum_blank = (skb->ip_summed == CHECKSUM_HW); @@ -720,7 +720,7 @@ while ((skb = __skb_dequeue(&rxq)) != NULL) { #ifdef GRANT_DEBUG printk(KERN_ALERT "#### rx_poll dequeue vdata=%p mfn=%lu\n", - skb->data, virt_to_machine(skb->data)>>PAGE_SHIFT); + skb->data, virt_to_mfn(skb->data)); dump_packet('d', skb->data, (unsigned long)skb->data); #endif /* @@ -854,18 +854,23 @@ * interface has been down. */ for (requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++) { - if ((unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET) { - struct sk_buff *skb = np->tx_skbs[i]; - - tx = &np->tx->ring[requeue_idx++].req; - - tx->id = i; - tx->addr = virt_to_machine(skb->data); - tx->size = skb->len; - - np->stats.tx_bytes += skb->len; - np->stats.tx_packets++; - } + if ((unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET) { + struct sk_buff *skb = np->tx_skbs[i]; + + tx = &np->tx->ring[requeue_idx++].req; + + tx->id = i; +#ifdef CONFIG_XEN_NETDEV_GRANT_TX + tx->addr = 0; /*(ref << PAGE_SHIFT) |*/ +#else + tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; +#endif + tx->addr |= (unsigned long)skb->data & ~PAGE_MASK; + tx->size = skb->len; + + np->stats.tx_bytes += skb->len; + np->stats.tx_packets++; + } } wmb(); np->tx->req_prod = requeue_idx; @@ -922,7 +927,7 @@ netif_fe_interface_connect_t *msg = (void*)cmsg.msg; msg->handle = np->handle; - msg->tx_shmem_frame = (virt_to_machine(np->tx) >> PAGE_SHIFT); + msg->tx_shmem_frame = virt_to_mfn(np->tx); #ifdef CONFIG_XEN_NETDEV_GRANT_TX msg->tx_shmem_ref = (u32)gnttab_claim_grant_reference(&gref_tx_head, gref_tx_terminal); @@ -934,7 +939,7 @@ msg->tx_shmem_frame, 0); #endif - msg->rx_shmem_frame = (virt_to_machine(np->rx) >> PAGE_SHIFT); + msg->rx_shmem_frame = virt_to_mfn(np->rx); #ifdef CONFIG_XEN_NETDEV_GRANT_RX msg->rx_shmem_ref = (u32)gnttab_claim_grant_reference(&gref_rx_head, gref_rx_terminal); diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c --- a/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Fri Aug 19 18:19:28 2005 @@ -657,8 +657,8 @@ phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] = FOREIGN_FRAME((buffer_mach + offset) >> PAGE_SHIFT); - ASSERT(virt_to_machine(MMAP_VADDR(pending_idx, i)) - == buffer_mach + i << PAGE_SHIFT); + ASSERT(virt_to_mfn(MMAP_VADDR(pending_idx, i)) + == ((buffer_mach >> PAGE_SHIFT) + i)); } if ( req->pipe_type == 0 && req->num_iso > 0 ) /* Maybe schedule ISO... */ diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c --- a/linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c Fri Aug 19 18:19:28 2005 @@ -195,7 +195,7 @@ } urb_priv->schedule = schedule; - req->iso_schedule = virt_to_machine(schedule); + req->iso_schedule = virt_to_mfn(schedule) << PAGE_SHIFT; return 0; } @@ -212,7 +212,7 @@ #if DEBUG printk(KERN_DEBUG "usbif = %p, req_prod = %d (@ 0x%lx), resp_prod = %d, resp_cons = %d\n", - usbif, usbif->req_prod, virt_to_machine(&usbif->req_prod), + usbif, usbif->req_prod, virt_to_mfn(&usbif->req_prod), usbif->resp_prod, xhci->usb_resp_cons); #endif @@ -232,7 +232,7 @@ req->operation = USBIF_OP_IO; req->port = 0; /* We don't care what the port is. */ req->id = (unsigned long) urb->hcpriv; - req->transfer_buffer = virt_to_machine(urb->transfer_buffer); + req->transfer_buffer = virt_to_mfn(urb->transfer_buffer) << PAGE_SHIFT; req->devnum = usb_pipedevice(urb->pipe); req->direction = usb_pipein(urb->pipe); req->speed = usb_pipeslow(urb->pipe); @@ -280,7 +280,7 @@ printk(KERN_DEBUG "queuing probe: req_prod = %d (@ 0x%lx), resp_prod = %d, " "resp_cons = %d\n", usbif->req_prod, - virt_to_machine(&usbif->req_prod), + virt_to_mfn(&usbif->req_prod), usbif->resp_prod, xhci->usb_resp_cons); #endif @@ -1555,7 +1555,7 @@ cmsg.type = CMSG_USBIF_FE; cmsg.subtype = CMSG_USBIF_FE_INTERFACE_CONNECT; cmsg.length = sizeof(usbif_fe_interface_connect_t); - up.shmem_frame = virt_to_machine(sring) >> PAGE_SHIFT; + up.shmem_frame = virt_to_mfn(sring); memcpy(cmsg.msg, &up, sizeof(up)); /* Tell the controller to bring up the interface. */ @@ -1599,7 +1599,7 @@ DPRINTK(KERN_INFO __FILE__ ": USB XHCI: SHM at %p (0x%lx), EVTCHN %d\n", - xhci->usb_ring.sring, virt_to_machine(xhci->usbif), + xhci->usb_ring.sring, virt_to_mfn(xhci->usbif), xhci->evtchn); xhci->state = USBIF_STATE_CONNECTED; diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Fri Aug 19 18:19:28 2005 @@ -48,13 +48,12 @@ static inline struct ringbuf_head *outbuf(void) { - return machine_to_virt(xen_start_info.store_mfn << PAGE_SHIFT); + return mfn_to_virt(xen_start_info.store_mfn); } static inline struct ringbuf_head *inbuf(void) { - return machine_to_virt(xen_start_info.store_mfn << PAGE_SHIFT) - + PAGE_SIZE/2; + return mfn_to_virt(xen_start_info.store_mfn) + PAGE_SIZE/2; } static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs) @@ -219,8 +218,7 @@ } /* FIXME zero out page -- domain builder should probably do this*/ - memset(machine_to_virt(xen_start_info.store_mfn << PAGE_SHIFT), - 0, PAGE_SIZE); + memset(mfn_to_virt(xen_start_info.store_mfn), 0, PAGE_SIZE); return 0; } diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Aug 19 18:19:28 2005 @@ -48,15 +48,7 @@ match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev) { for (; !streq(arr->devicetype, ""); arr++) { - if (!streq(arr->devicetype, dev->devicetype)) - continue; - - /* If they don't care what subtype, it's a match. */ - if (streq(arr->subtype, "")) - return arr; - - /* If they care, device must have (same) subtype. */ - if (dev->subtype && streq(arr->subtype, dev->subtype)) + if (streq(arr->devicetype, dev->devicetype)) return arr; } return NULL; @@ -72,10 +64,102 @@ return match_device(drv->ids, to_xenbus_device(_dev)) != NULL; } +struct xen_bus_type +{ + char *root; + unsigned int levels; + int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename); + int (*probe)(const char *type, const char *dir); + struct bus_type bus; + struct device dev; +}; + +/* device/<type>/<id> => <type>-<id> */ +static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) +{ + nodename = strchr(nodename, '/'); + if (!nodename || strlen(nodename + 1) >= BUS_ID_SIZE) { + printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename); + return -EINVAL; + } + + strlcpy(bus_id, nodename + 1, BUS_ID_SIZE); + if (!strchr(bus_id, '/')) { + printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id); + return -EINVAL; + } + *strchr(bus_id, '/') = '-'; + return 0; +} + /* Bus type for frontend drivers. */ -static struct bus_type xenbus_type = { - .name = "xenbus", - .match = xenbus_match, +static int xenbus_probe_frontend(const char *type, const char *name); +static struct xen_bus_type xenbus_frontend = { + .root = "device", + .levels = 2, /* device/type/<id> */ + .get_bus_id = frontend_bus_id, + .probe = xenbus_probe_frontend, + .bus = { + .name = "xen", + .match = xenbus_match, + }, + .dev = { + .bus_id = "xen", + }, +}; + +/* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */ +static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) +{ + int domid, err; + const char *devid, *type, *frontend; + unsigned int typelen; + + type = strchr(nodename, '/'); + if (!type) + return -EINVAL; + type++; + typelen = strcspn(type, "/"); + if (!typelen || type[typelen] != '/') + return -EINVAL; + + devid = strrchr(nodename, '/') + 1; + + err = xenbus_gather(nodename, "frontend-id", "%i", &domid, + "frontend", NULL, &frontend, + NULL); + if (err) + return err; + if (strlen(frontend) == 0) + err = -ERANGE; + + if (!err && !xenbus_exists(frontend, "")) + err = -ENOENT; + + if (err) { + kfree(frontend); + return err; + } + + if (snprintf(bus_id, BUS_ID_SIZE, + "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE) + return -ENOSPC; + return 0; +} + +static int xenbus_probe_backend(const char *type, const char *uuid); +static struct xen_bus_type xenbus_backend = { + .root = "backend", + .levels = 3, /* backend/type/<frontend>/<id> */ + .get_bus_id = backend_bus_id, + .probe = xenbus_probe_backend, + .bus = { + .name = "xen-backend", + .match = xenbus_match, + }, + .dev = { + .bus_id = "xen-backend", + }, }; static int xenbus_dev_probe(struct device *_dev) @@ -104,12 +188,13 @@ return drv->remove(dev); } -int xenbus_register_driver(struct xenbus_driver *drv) +static int xenbus_register_driver(struct xenbus_driver *drv, + struct xen_bus_type *bus) { int err; drv->driver.name = drv->name; - drv->driver.bus = &xenbus_type; + drv->driver.bus = &bus->bus; drv->driver.owner = drv->owner; drv->driver.probe = xenbus_dev_probe; drv->driver.remove = xenbus_dev_remove; @@ -120,6 +205,16 @@ return err; } +int xenbus_register_device(struct xenbus_driver *drv) +{ + return xenbus_register_driver(drv, &xenbus_frontend); +} + +int xenbus_register_backend(struct xenbus_driver *drv) +{ + return xenbus_register_driver(drv, &xenbus_backend); +} + void xenbus_unregister_driver(struct xenbus_driver *drv) { down(&xenbus_lock); @@ -130,52 +225,98 @@ struct xb_find_info { struct xenbus_device *dev; - const char *busid; + const char *nodename; }; static int cmp_dev(struct device *dev, void *data) { + struct xenbus_device *xendev = to_xenbus_device(dev); struct xb_find_info *info = data; - if (streq(dev->bus_id, info->busid)) { - info->dev = container_of(get_device(dev), - struct xenbus_device, dev); + if (streq(xendev->nodename, info->nodename)) { + info->dev = xendev; + get_device(dev); return 1; } return 0; } -/* FIXME: device_find is fixed in 2.6.13-rc2 according to Greg KH --RR */ -struct xenbus_device *xenbus_device_find(const char *busid) -{ - struct xb_find_info info = { .dev = NULL, .busid = busid }; - - bus_for_each_dev(&xenbus_type, NULL, &info, cmp_dev); +struct xenbus_device *xenbus_device_find(const char *nodename, + struct bus_type *bus) +{ + struct xb_find_info info = { .dev = NULL, .nodename = nodename }; + + bus_for_each_dev(bus, NULL, &info, cmp_dev); return info.dev; } +static int cleanup_dev(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + struct xb_find_info *info = data; + int len = strlen(info->nodename); + + if (!strncmp(xendev->nodename, info->nodename, len)) { + info->dev = xendev; + get_device(dev); + return 1; + } + return 0; +} + +static void xenbus_cleanup_devices(const char *path, struct bus_type *bus) +{ + struct xb_find_info info = { .nodename = path }; + + do { + info.dev = NULL; + bus_for_each_dev(bus, NULL, &info, cleanup_dev); + if (info.dev) { + device_unregister(&info.dev->dev); + put_device(&info.dev->dev); + } + } while (info.dev); +} static void xenbus_release_device(struct device *dev) { if (dev) { struct xenbus_device *xendev = to_xenbus_device(dev); - kfree(xendev->subtype); kfree(xendev); } } -/* devices/<typename>/<name> */ -static int xenbus_probe_device(const char *dirpath, const char *devicetype, - const char *name) + +/* Simplified asprintf. */ +static char *kasprintf(const char *fmt, ...) +{ + va_list ap; + unsigned int len; + char *p, dummy[1]; + + va_start(ap, fmt); + /* FIXME: vsnprintf has a bug, NULL should work */ + len = vsnprintf(dummy, 0, fmt, ap); + va_end(ap); + + p = kmalloc(len + 1, GFP_KERNEL); + if (!p) + return NULL; + va_start(ap, fmt); + vsprintf(p, fmt, ap); + va_end(ap); + return p; +} + +static int xenbus_probe_node(struct xen_bus_type *bus, + const char *type, + const char *nodename) { int err; struct xenbus_device *xendev; unsigned int stringlen; - /* Nodename: /device/<typename>/<name>/ */ - stringlen = strlen(dirpath) + strlen(devicetype) + strlen(name) + 3; - /* Typename */ - stringlen += strlen(devicetype) + 1; + stringlen = strlen(nodename) + 1 + strlen(type) + 1; xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL); if (!xendev) return -ENOMEM; @@ -183,38 +324,103 @@ /* Copy the strings into the extra space. */ xendev->nodename = (char *)(xendev + 1); - sprintf(xendev->nodename, "%s/%s/%s", dirpath, devicetype, name); + strcpy(xendev->nodename, nodename); xendev->devicetype = xendev->nodename + strlen(xendev->nodename) + 1; - strcpy(xendev->devicetype, devicetype); - - /* FIXME: look for "subtype" field. */ - snprintf(xendev->dev.bus_id, BUS_ID_SIZE, "%s-%s", devicetype, name); - xendev->dev.bus = &xenbus_type; + strcpy(xendev->devicetype, type); + + xendev->dev.parent = &bus->dev; + xendev->dev.bus = &bus->bus; xendev->dev.release = xenbus_release_device; + + err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename); + if (err) { + kfree(xendev); + return err; + } /* Register with generic device framework. */ err = device_register(&xendev->dev); if (err) { - printk("XENBUS: Registering device %s: error %i\n", - xendev->dev.bus_id, err); + printk("XENBUS: Registering %s device %s: error %i\n", + bus->bus.name, xendev->dev.bus_id, err); kfree(xendev); } return err; } -static int xenbus_probe_device_type(const char *dirpath, const char *typename) +/* device/<typename>/<name> */ +static int xenbus_probe_frontend(const char *type, const char *name) +{ + char *nodename; + int err; + + nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name); + if (!nodename) + return -ENOMEM; + + err = xenbus_probe_node(&xenbus_frontend, type, nodename); + kfree(nodename); + return err; +} + +/* backend/<typename>/<frontend-uuid>/<name> */ +static int xenbus_probe_backend_unit(const char *dir, + const char *type, + const char *name) +{ + char *nodename; + int err; + + nodename = kasprintf("%s/%s", dir, name); + if (!nodename) + return -ENOMEM; + + err = xenbus_probe_node(&xenbus_backend, type, nodename); + kfree(nodename); + return err; +} + +/* backend/<typename>/<frontend-uuid> */ +static int xenbus_probe_backend(const char *type, const char *uuid) +{ + char *nodename; + int err = 0; + char **dir; + unsigned int i, dir_n = 0; + + nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, uuid); + if (!nodename) + return -ENOMEM; + + dir = xenbus_directory(nodename, "", &dir_n); + if (IS_ERR(dir)) { + kfree(nodename); + return PTR_ERR(dir); + } + + for (i = 0; i < dir_n; i++) { + err = xenbus_probe_backend_unit(nodename, type, dir[i]); + if (err) + break; + } + kfree(dir); + kfree(nodename); + return err; +} + +static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type) { int err = 0; char **dir; unsigned int dir_n = 0; int i; - dir = xenbus_directory(dirpath, typename, &dir_n); + dir = xenbus_directory(bus->root, type, &dir_n); if (IS_ERR(dir)) return PTR_ERR(dir); for (i = 0; i < dir_n; i++) { - err = xenbus_probe_device(dirpath, typename, dir[i]); + err = bus->probe(type, dir[i]); if (err) break; } @@ -222,18 +428,18 @@ return err; } -static int xenbus_probe_devices(const char *path) +static int xenbus_probe_devices(struct xen_bus_type *bus) { int err = 0; char **dir; unsigned int i, dir_n; - dir = xenbus_directory(path, "", &dir_n); + dir = xenbus_directory(bus->root, "", &dir_n); if (IS_ERR(dir)) return PTR_ERR(dir); for (i = 0; i < dir_n; i++) { - err = xenbus_probe_device_type(path, dir[i]); + err = xenbus_probe_device_type(bus, dir[i]); if (err) break; } @@ -251,58 +457,117 @@ return ret; } -static void dev_changed(struct xenbus_watch *watch, const char *node) -{ - char busid[BUS_ID_SIZE]; - int exists; +static int strsep_len(const char *str, char c, unsigned int len) +{ + unsigned int i; + + for (i = 0; str[i]; i++) + if (str[i] == c) { + if (len == 0) + return i; + len--; + } + return (len == 0) ? i : -ERANGE; +} + +static void dev_changed(const char *node, struct xen_bus_type *bus) +{ + int exists, rootlen; struct xenbus_device *dev; - char *p; - - /* Node is of form device/<type>/<identifier>[/...] */ - if (char_count(node, '/') != 2) + char type[BUS_ID_SIZE]; + const char *p, *root; + + if (char_count(node, '/') < 2) + return; + + exists = xenbus_exists(node, ""); + if (!exists) { + xenbus_cleanup_devices(node, &bus->bus); return; - - /* Created or deleted? */ - exists = xenbus_exists(node, ""); - + } + + /* backend/<type>/... or device/<type>/... */ p = strchr(node, '/') + 1; - if (strlen(p) + 1 > BUS_ID_SIZE) { - printk("Device for node %s is too big!\n", node); + snprintf(type, BUS_ID_SIZE, "%.*s", strcspn(p, "/"), p); + type[BUS_ID_SIZE-1] = '\0'; + + rootlen = strsep_len(node, '/', bus->levels); + if (rootlen < 0) return; - } - /* Bus ID is name with / changed to - */ - strcpy(busid, p); - *strchr(busid, '/') = '-'; - - dev = xenbus_device_find(busid); - printk("xenbus: device %s %s\n", busid, dev ? "exists" : "new"); - if (dev && !exists) { - printk("xenbus: Unregistering device %s\n", busid); - /* FIXME: free? */ - device_unregister(&dev->dev); - } else if (!dev && exists) { - printk("xenbus: Adding device %s\n", busid); - /* Hack bus id back into two strings. */ - *strrchr(busid, '-') = '\0'; - xenbus_probe_device("device", busid, busid+strlen(busid)+1); - } else - printk("xenbus: strange, %s already %s\n", busid, - exists ? "exists" : "gone"); - if (dev) + root = kasprintf("%.*s", rootlen, node); + if (!root) + return; + + dev = xenbus_device_find(root, &bus->bus); + if (!dev) + xenbus_probe_node(bus, type, root); + else put_device(&dev->dev); + + kfree(root); +} + +static void frontend_changed(struct xenbus_watch *watch, const char *node) +{ + dev_changed(node, &xenbus_frontend); +} + +static void backend_changed(struct xenbus_watch *watch, const char *node) +{ + dev_changed(node, &xenbus_backend); } /* We watch for devices appearing and vanishing. */ -static struct xenbus_watch dev_watch = { - /* FIXME: Ideally we'd only watch for changes 2 levels deep... */ +static struct xenbus_watch fe_watch = { .node = "device", - .callback = dev_changed, + .callback = frontend_changed, }; + +static struct xenbus_watch be_watch = { + .node = "backend", + .callback = backend_changed, +}; + +static int suspend_dev(struct device *dev, void *data) +{ + int err = 0; + struct xenbus_driver *drv; + struct xenbus_device *xdev; + + if (dev->driver == NULL) + return 0; + drv = to_xenbus_driver(dev->driver); + xdev = container_of(dev, struct xenbus_device, dev); + if (drv->suspend) + err = drv->suspend(xdev); + if (err) + printk("xenbus: suspend %s failed: %i\n", dev->bus_id, err); + return 0; +} + +static int resume_dev(struct device *dev, void *data) +{ + int err = 0; + struct xenbus_driver *drv; + struct xenbus_device *xdev; + + if (dev->driver == NULL) + return 0; + drv = to_xenbus_driver(dev->driver); + xdev = container_of(dev, struct xenbus_device, dev); + if (drv->resume) + err = drv->resume(xdev); + if (err) + printk("xenbus: resume %s failed: %i\n", dev->bus_id, err); + return 0; +} void xenbus_suspend(void) { /* We keep lock, so no comms can happen as page moves. */ down(&xenbus_lock); + bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); + bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev); xb_suspend_comms(); } @@ -310,6 +575,8 @@ { xb_init_comms(); reregister_xenbus_watches(); + bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); + bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev); up(&xenbus_lock); } @@ -354,30 +621,23 @@ } down(&xenbus_lock); - err = notifier_call_chain(&xenstore_chain, 0, 0); + /* Enumerate devices in xenstore. */ + xenbus_probe_devices(&xenbus_frontend); + xenbus_probe_devices(&xenbus_backend); + /* Watch for changes. */ + register_xenbus_watch(&fe_watch); + register_xenbus_watch(&be_watch); up(&xenbus_lock); - - if (err == NOTIFY_BAD) { - printk("%s: calling xenstore notify chain failed\n", - __FUNCTION__); - return -EINVAL; - } - - err = 0; - - down(&xenbus_lock); - /* Enumerate devices in xenstore. */ - xenbus_probe_devices("device"); - /* Watch for changes. */ - register_xenbus_watch(&dev_watch); - up(&xenbus_lock); return 0; } static int __init xenbus_probe_init(void) { - bus_register(&xenbus_type); - + bus_register(&xenbus_frontend.bus); + bus_register(&xenbus_backend.bus); + device_register(&xenbus_frontend.dev); + device_register(&xenbus_backend.dev); + if (!xen_start_info.store_evtchn) return 0; diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Fri Aug 19 18:19:28 2005 @@ -187,6 +187,7 @@ static char buffer[4096]; BUG_ON(down_trylock(&xenbus_lock) == 0); + /* XXX FIXME: might not be correct if name == "" */ BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer)); strcpy(buffer, dir); @@ -399,9 +400,12 @@ ret = PTR_ERR(p); break; } - if (sscanf(p, fmt, result) == 0) - ret = -EINVAL; - kfree(p); + if (fmt) { + if (sscanf(p, fmt, result) == 0) + ret = -EINVAL; + kfree(p); + } else + *(char **)result = p; } va_end(ap); return ret; diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/include/asm-xen/asm-i386/desc.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/desc.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/desc.h Fri Aug 19 18:19:28 2005 @@ -93,7 +93,7 @@ static inline void load_TLS(struct thread_struct *t, unsigned int cpu) { -#define C(i) HYPERVISOR_update_descriptor(virt_to_machine(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]), ((u32 *)&t->tls_array[i])[0], ((u32 *)&t->tls_array[i])[1]) +#define C(i) HYPERVISOR_update_descriptor(virt_to_machine(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]), *(u64 *)&t->tls_array[i]) C(0); C(1); C(2); #undef C } diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/include/asm-xen/asm-i386/fixmap.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/fixmap.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/fixmap.h Fri Aug 19 18:19:28 2005 @@ -102,8 +102,8 @@ __end_of_fixed_addresses }; -extern void __set_fixmap (enum fixed_addresses idx, - unsigned long phys, pgprot_t flags); +extern void __set_fixmap( + enum fixed_addresses idx, maddr_t phys, pgprot_t flags); #define set_fixmap(idx, phys) \ __set_fixmap(idx, phys, PAGE_KERNEL) diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Fri Aug 19 18:19:28 2005 @@ -163,7 +163,7 @@ TRAP_INSTR : "=a" (ret), "=b" (ign) : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield) - : "memory" ); + : "memory", "ecx" ); return ret; } @@ -178,7 +178,7 @@ TRAP_INSTR : "=a" (ret), "=b" (ign1) : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block) - : "memory" ); + : "memory", "ecx" ); return ret; } @@ -194,7 +194,7 @@ : "=a" (ret), "=b" (ign1) : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift)) - : "memory" ); + : "memory", "ecx" ); return ret; } @@ -210,7 +210,7 @@ : "=a" (ret), "=b" (ign1) : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift)) - : "memory" ); + : "memory", "ecx" ); return ret; } @@ -228,7 +228,7 @@ : "=a" (ret), "=b" (ign1), "=S" (ign2) : "0" (__HYPERVISOR_sched_op), "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)), - "S" (srec) : "memory"); + "S" (srec) : "memory", "ecx"); return ret; } @@ -244,7 +244,7 @@ : "=a" (ret), "=b" (ign1) : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift)) - : "memory" ); + : "memory", "ecx" ); return ret; } @@ -316,16 +316,17 @@ static inline int HYPERVISOR_update_descriptor( - unsigned long ma, unsigned long word1, unsigned long word2) -{ - int ret; - unsigned long ign1, ign2, ign3; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) - : "0" (__HYPERVISOR_update_descriptor), "1" (ma), "2" (word1), - "3" (word2) + u64 ma, u64 desc) +{ + int ret; + unsigned long ign1, ign2, ign3, ign4; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) + : "0" (__HYPERVISOR_update_descriptor), + "1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)), + "3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32)) : "memory" ); return ret; @@ -529,12 +530,15 @@ { int ret; unsigned long ign1; + /* Yes, I really do want to clobber edx here: when we resume a + vcpu after unpickling a multi-processor domain, it returns + here, but clobbers all of the call clobbered registers. */ __asm__ __volatile__ ( TRAP_INSTR : "=a" (ret), "=b" (ign1) : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift)) - : "memory" ); + : "memory", "ecx", "edx" ); return ret; } @@ -550,8 +554,26 @@ : "=a" (ret), "=b" (ign1) : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift)) + : "memory", "ecx" ); + + return ret; +} + +static inline int +HYPERVISOR_vcpu_pickle( + int vcpu, vcpu_guest_context_t *ctxt) +{ + int ret; + unsigned long ign1, ign2; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)), + "2" (ctxt) : "memory" ); return ret; } + #endif /* __HYPERCALL_H__ */ diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h Fri Aug 19 18:19:28 2005 @@ -63,20 +63,25 @@ extern unsigned int *phys_to_machine_mapping; #define pfn_to_mfn(_pfn) ((unsigned long)(phys_to_machine_mapping[(_pfn)])) #define mfn_to_pfn(_mfn) ((unsigned long)(machine_to_phys_mapping[(_mfn)])) + +/* Definitions for machine and pseudophysical addresses. */ #ifdef CONFIG_X86_PAE -typedef unsigned long long physaddr_t; -#else -typedef unsigned long physaddr_t; -#endif -static inline physaddr_t phys_to_machine(physaddr_t phys) -{ - physaddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT); +typedef unsigned long long paddr_t; +typedef unsigned long long maddr_t; +#else +typedef unsigned long paddr_t; +typedef unsigned long maddr_t; +#endif + +static inline maddr_t phys_to_machine(paddr_t phys) +{ + maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT); machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK); return machine; } -static inline physaddr_t machine_to_phys(physaddr_t machine) -{ - physaddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT); +static inline paddr_t machine_to_phys(maddr_t machine) +{ + paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT); phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK); return phys; } @@ -233,8 +238,10 @@ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) /* VIRT <-> MACHINE conversion */ -#define virt_to_machine(_a) (phys_to_machine(__pa(_a))) -#define machine_to_virt(_m) (__va(machine_to_phys(_m))) +#define virt_to_machine(v) (phys_to_machine(__pa(v))) +#define machine_to_virt(m) (__va(machine_to_phys(m))) +#define virt_to_mfn(v) (pfn_to_mfn(__pa(v) >> PAGE_SHIFT)) +#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) #endif /* __KERNEL__ */ diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h Fri Aug 19 18:19:28 2005 @@ -32,7 +32,7 @@ */ #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) extern unsigned long empty_zero_page[1024]; -extern pgd_t swapper_pg_dir[1024]; +extern pgd_t *swapper_pg_dir; extern kmem_cache_t *pgd_cache; extern kmem_cache_t *pmd_cache; extern spinlock_t pgd_lock; @@ -450,7 +450,7 @@ #define arbitrary_virt_to_machine(__va) \ ({ \ pte_t *__pte = virt_to_ptep(__va); \ - unsigned long __pa = (*(unsigned long *)__pte) & PAGE_MASK; \ + maddr_t __pa = (maddr_t)pte_mfn(*__pte) << PAGE_SHIFT; \ __pa | ((unsigned long)(__va) & (PAGE_SIZE-1)); \ }) diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Fri Aug 19 18:19:28 2005 @@ -502,4 +502,21 @@ return ret; } +static inline int +HYPERVISOR_vcpu_pickle( + int vcpu, vcpu_guest_context_t *ctxt) +{ + int ret; + unsigned long ign1, ign2; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)), + "2" (ctxt) + : __syscall_clobber ); + + return ret; +} + #endif /* __HYPERCALL_H__ */ diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h Fri Aug 19 18:19:28 2005 @@ -65,16 +65,21 @@ extern u32 *phys_to_machine_mapping; #define pfn_to_mfn(_pfn) ((unsigned long) phys_to_machine_mapping[(unsigned int)(_pfn)]) #define mfn_to_pfn(_mfn) ((unsigned long) machine_to_phys_mapping[(unsigned int)(_mfn)]) -static inline unsigned long phys_to_machine(unsigned long phys) -{ - unsigned long machine = pfn_to_mfn(phys >> PAGE_SHIFT); + +/* Definitions for machine and pseudophysical addresses. */ +typedef unsigned long paddr_t; +typedef unsigned long maddr_t; + +static inline maddr_t phys_to_machine(paddr_t phys) +{ + maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT); machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK); return machine; } -static inline unsigned long machine_to_phys(unsigned long machine) -{ - unsigned long phys = mfn_to_pfn(machine >> PAGE_SHIFT); +static inline paddr_t machine_to_phys(maddr_t machine) +{ + paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT); phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK); return phys; } @@ -211,8 +216,10 @@ #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) /* VIRT <-> MACHINE conversion */ -#define virt_to_machine(_a) (phys_to_machine(__pa(_a))) -#define machine_to_virt(_m) (__va(machine_to_phys(_m))) +#define virt_to_machine(v) (phys_to_machine(__pa(v))) +#define machine_to_virt(m) (__va(machine_to_phys(m))) +#define virt_to_mfn(v) (pfn_to_mfn(__pa(v) >> PAGE_SHIFT)) +#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) #define VM_DATA_DEFAULT_FLAGS \ (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \ diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/include/asm-xen/xenbus.h --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Fri Aug 19 18:19:28 2005 @@ -37,7 +37,6 @@ /* A xenbus device. */ struct xenbus_device { char *devicetype; - char *subtype; char *nodename; struct device dev; int has_error; @@ -53,7 +52,6 @@ { /* .../device/<device_type>/<identifier> */ char devicetype[32]; /* General class of device. */ - char subtype[32]; /* Contents of "subtype" for this device */ }; /* A xenbus driver. */ @@ -61,9 +59,11 @@ char *name; struct module *owner; const struct xenbus_device_id *ids; - int (*probe) (struct xenbus_device * dev, - const struct xenbus_device_id * id); - int (*remove) (struct xenbus_device * dev); + int (*probe)(struct xenbus_device *dev, + const struct xenbus_device_id *id); + int (*remove)(struct xenbus_device *dev); + int (*suspend)(struct xenbus_device *dev); + int (*resume)(struct xenbus_device *dev); struct device_driver driver; }; @@ -72,7 +72,8 @@ return container_of(drv, struct xenbus_driver, driver); } -int xenbus_register_driver(struct xenbus_driver *drv); +int xenbus_register_device(struct xenbus_driver *drv); +int xenbus_register_backend(struct xenbus_driver *drv); void xenbus_unregister_driver(struct xenbus_driver *drv); /* Caller must hold this lock to call these functions: it's also held diff -r 99914b54f7bf -r 81576d3d1ca8 tools/debugger/libxendebug/xendebug.c --- a/tools/debugger/libxendebug/xendebug.c Thu Aug 18 18:40:02 2005 +++ b/tools/debugger/libxendebug/xendebug.c Fri Aug 19 18:19:28 2005 @@ -40,7 +40,7 @@ typedef struct bwcpoint /* break/watch/catch point */ { struct list_head list; - memory_t address; + unsigned long address; u32 domain; u8 old_value; /* old value for software bkpt */ } bwcpoint_t, *bwcpoint_p; @@ -311,7 +311,7 @@ /* access to one page */ static int xendebug_memory_page (domain_context_p ctxt, int xc_handle, u32 vcpu, - int protection, memory_t address, int length, u8 *buffer) + int protection, unsigned long address, int length, u8 *buffer) { vcpu_guest_context_t *vcpu_ctxt = &ctxt->context[vcpu]; unsigned long pde, page; @@ -407,7 +407,7 @@ /* divide a memory operation into accesses to individual pages */ static int xendebug_memory_op (domain_context_p ctxt, int xc_handle, u32 vcpu, - int protection, memory_t address, int length, u8 *buffer) + int protection, unsigned long address, int length, u8 *buffer) { int remain; /* number of bytes to touch past this page */ int bytes = 0; @@ -431,7 +431,7 @@ xendebug_read_memory(int xc_handle, u32 domid, u32 vcpu, - memory_t address, + unsigned long address, u32 length, u8 *data) { @@ -451,7 +451,7 @@ xendebug_write_memory(int xc_handle, u32 domid, u32 vcpu, - memory_t address, + unsigned long address, u32 length, u8 *data) { @@ -471,7 +471,7 @@ xendebug_insert_memory_breakpoint(int xc_handle, u32 domid, u32 vcpu, - memory_t address, + unsigned long address, u32 length) { bwcpoint_p bkpt; @@ -517,7 +517,7 @@ xendebug_remove_memory_breakpoint(int xc_handle, u32 domid, u32 vcpu, - memory_t address, + unsigned long address, u32 length) { bwcpoint_p bkpt = NULL; diff -r 99914b54f7bf -r 81576d3d1ca8 tools/debugger/libxendebug/xendebug.h --- a/tools/debugger/libxendebug/xendebug.h Thu Aug 18 18:40:02 2005 +++ b/tools/debugger/libxendebug/xendebug.h Fri Aug 19 18:19:28 2005 @@ -45,7 +45,7 @@ int xendebug_read_memory(int xc_handle, u32 domid, u32 vcpu, - memory_t address, + unsigned long address, u32 length, u8 *data); @@ -53,7 +53,7 @@ int xendebug_write_memory(int xc_handle, u32 domid, u32 vcpu, - memory_t address, + unsigned long address, u32 length, u8 *data); @@ -61,13 +61,13 @@ int xendebug_insert_memory_breakpoint(int xc_handle, u32 domid, u32 vcpu, - memory_t address, + unsigned long address, u32 length); int xendebug_remove_memory_breakpoint(int xc_handle, u32 domid, u32 vcpu, - memory_t address, + unsigned long address, u32 length); int xendebug_query_domain_stop(int xc_handle, diff -r 99914b54f7bf -r 81576d3d1ca8 tools/debugger/pdb/linux-2.6-module/debug.c --- a/tools/debugger/pdb/linux-2.6-module/debug.c Thu Aug 18 18:40:02 2005 +++ b/tools/debugger/pdb/linux-2.6-module/debug.c Fri Aug 19 18:19:28 2005 @@ -26,7 +26,7 @@ typedef struct bwcpoint /* break/watch/catch point */ { struct list_head list; - memory_t address; + unsigned long address; int length; u8 type; /* BWC_??? */ @@ -109,7 +109,7 @@ } bwcpoint_p -pdb_search_watchpoint (u32 process, memory_t address) +pdb_search_watchpoint (u32 process, unsigned long address) { bwcpoint_p bwc_watch = (bwcpoint_p) 0; bwcpoint_p bwc_entry = (bwcpoint_p) 0; @@ -364,7 +364,7 @@ int pdb_insert_memory_breakpoint (struct task_struct *target, - memory_t address, u32 length) + unsigned long address, u32 length) { int rc = 0; bwcpoint_p bkpt; @@ -399,7 +399,7 @@ int pdb_remove_memory_breakpoint (struct task_struct *target, - memory_t address, u32 length) + unsigned long address, u32 length) { int rc = 0; bwcpoint_p bkpt = NULL; @@ -760,7 +760,7 @@ { pdb_response_t resp; bwcpoint_p bkpt = NULL; - memory_t address = regs->eip - 1; + unsigned long address = regs->eip - 1; struct list_head *entry; list_for_each(entry, &bwcpoint_list) diff -r 99914b54f7bf -r 81576d3d1ca8 tools/debugger/pdb/linux-2.6-module/module.c --- a/tools/debugger/pdb/linux-2.6-module/module.c Thu Aug 18 18:40:02 2005 +++ b/tools/debugger/pdb/linux-2.6-module/module.c Fri Aug 19 18:19:28 2005 @@ -199,7 +199,7 @@ } static void -pdb_send_connection_status(int status, memory_t ring) +pdb_send_connection_status(int status, unsigned long ring) { ctrl_msg_t cmsg = { diff -r 99914b54f7bf -r 81576d3d1ca8 tools/debugger/pdb/linux-2.6-module/pdb_debug.h --- a/tools/debugger/pdb/linux-2.6-module/pdb_debug.h Thu Aug 18 18:40:02 2005 +++ b/tools/debugger/pdb/linux-2.6-module/pdb_debug.h Fri Aug 19 18:19:28 2005 @@ -18,9 +18,9 @@ int pdb_step (struct task_struct *target); int pdb_insert_memory_breakpoint (struct task_struct *target, - memory_t address, u32 length); + unsigned long address, u32 length); int pdb_remove_memory_breakpoint (struct task_struct *target, - memory_t address, u32 length); + unsigned long address, u32 length); int pdb_insert_watchpoint (struct task_struct *target, pdb_op_watchpt_p watchpt); int pdb_remove_watchpoint (struct task_struct *target, diff -r 99914b54f7bf -r 81576d3d1ca8 tools/debugger/pdb/pdb_caml_domain.c --- a/tools/debugger/pdb/pdb_caml_domain.c Thu Aug 18 18:40:02 2005 +++ b/tools/debugger/pdb/pdb_caml_domain.c Fri Aug 19 18:19:28 2005 @@ -203,7 +203,7 @@ context_t ctx; int loop; char *buffer; - memory_t my_address = Int32_val(address); + unsigned long my_address = Int32_val(address); u32 my_length = Int_val(length); printf ("(pdb) read memory\n"); @@ -259,7 +259,7 @@ context_t ctx; char buffer[4096]; /* a big buffer */ - memory_t my_address; + unsigned long my_address; u32 length = 0; printf ("(pdb) write memory\n"); @@ -279,7 +279,7 @@ } buffer[length++] = Int_val(Field(node, 0)); - my_address = (memory_t) Int32_val(address); + my_address = (unsigned long) Int32_val(address); if ( xendebug_write_memory(xc_handle, ctx.domain, ctx.vcpu, my_address, length, buffer) ) @@ -344,7 +344,7 @@ CAMLparam3(context, address, length); context_t ctx; - memory_t my_address = (memory_t) Int32_val(address); + unsigned long my_address = (unsigned long) Int32_val(address); int my_length = Int_val(length); decode_context(&ctx, context); @@ -373,7 +373,7 @@ context_t ctx; - memory_t my_address = (memory_t) Int32_val(address); + unsigned long my_address = (unsigned long) Int32_val(address); int my_length = Int_val(length); printf ("(pdb) remove memory breakpoint 0x%lx %d\n", diff -r 99914b54f7bf -r 81576d3d1ca8 tools/debugger/pdb/pdb_caml_process.c --- a/tools/debugger/pdb/pdb_caml_process.c Thu Aug 18 18:40:02 2005 +++ b/tools/debugger/pdb/pdb_caml_process.c Fri Aug 19 18:19:28 2005 @@ -495,7 +495,7 @@ req.operation = PDB_OPCODE_SET_BKPT; req.process = ctx.process; - req.u.bkpt.address = (memory_t) Int32_val(address); + req.u.bkpt.address = (unsigned long) Int32_val(address); req.u.bkpt.length = Int_val(length); send_request(ctx.ring, ctx.evtchn, &req); @@ -518,7 +518,7 @@ req.operation = PDB_OPCODE_CLR_BKPT; req.process = ctx.process; - req.u.bkpt.address = (memory_t) Int32_val(address); + req.u.bkpt.address = (unsigned long) Int32_val(address); req.u.bkpt.length = Int_val(length); send_request(ctx.ring, ctx.evtchn, &req); @@ -542,7 +542,7 @@ req.operation = PDB_OPCODE_SET_WATCHPT; req.process = ctx.process; req.u.watchpt.type = Int_val(kind); - req.u.watchpt.address = (memory_t) Int32_val(address); + req.u.watchpt.address = (unsigned long) Int32_val(address); req.u.watchpt.length = Int_val(length); send_request(ctx.ring, ctx.evtchn, &req); @@ -566,7 +566,7 @@ req.operation = PDB_OPCODE_CLR_WATCHPT; req.process = ctx.process; req.u.watchpt.type = Int_val(kind); - req.u.watchpt.address = (memory_t) Int32_val(address); + req.u.watchpt.address = (unsigned long) Int32_val(address); req.u.watchpt.length = Int_val(length); send_request(ctx.ring, ctx.evtchn, &req); diff -r 99914b54f7bf -r 81576d3d1ca8 tools/debugger/pdb/pdb_caml_xcs.c --- a/tools/debugger/pdb/pdb_caml_xcs.c Thu Aug 18 18:40:02 2005 +++ b/tools/debugger/pdb/pdb_caml_xcs.c Fri Aug 19 18:19:28 2005 @@ -50,7 +50,7 @@ { CAMLparam2(domain, ring); int my_domain = Int_val(domain); - memory_t my_ring = Int32_val(ring); + unsigned long my_ring = Int32_val(ring); pdb_front_ring_t *front_ring; pdb_sring_t *sring; diff -r 99914b54f7bf -r 81576d3d1ca8 tools/libxc/xc.h --- a/tools/libxc/xc.h Thu Aug 18 18:40:02 2005 +++ b/tools/libxc/xc.h Fri Aug 19 18:19:28 2005 @@ -515,25 +515,25 @@ */ int xc_grant_interface_close(int xc_handle); -int xc_gnttab_map_grant_ref(int xc_handle, - memory_t host_virt_addr, - u32 dom, - u16 ref, - u16 flags, - s16 *handle, - memory_t *dev_bus_addr); - -int xc_gnttab_unmap_grant_ref(int xc_handle, - memory_t host_virt_addr, - memory_t dev_bus_addr, - u16 handle, - s16 *status); +int xc_gnttab_map_grant_ref(int xc_handle, + u64 host_virt_addr, + u32 dom, + u16 ref, + u16 flags, + s16 *handle, + u64 *dev_bus_addr); + +int xc_gnttab_unmap_grant_ref(int xc_handle, + u64 host_virt_addr, + u64 dev_bus_addr, + u16 handle, + s16 *status); int xc_gnttab_setup_table(int xc_handle, u32 dom, u16 nr_frames, s16 *status, - memory_t **frame_list); + unsigned long **frame_list); /* Grant debug builds only: */ int xc_gnttab_dump_table(int xc_handle, diff -r 99914b54f7bf -r 81576d3d1ca8 tools/libxc/xc_gnttab.c --- a/tools/libxc/xc_gnttab.c Thu Aug 18 18:40:02 2005 +++ b/tools/libxc/xc_gnttab.c Fri Aug 19 18:19:28 2005 @@ -40,12 +40,12 @@ int xc_gnttab_map_grant_ref(int xc_handle, - memory_t host_virt_addr, + u64 host_virt_addr, u32 dom, u16 ref, u16 flags, s16 *handle, - memory_t *dev_bus_addr) + u64 *dev_bus_addr) { struct gnttab_map_grant_ref op; int rc; @@ -67,8 +67,8 @@ int xc_gnttab_unmap_grant_ref(int xc_handle, - memory_t host_virt_addr, - memory_t dev_bus_addr, + u64 host_virt_addr, + u64 dev_bus_addr, u16 handle, s16 *status) { @@ -92,7 +92,7 @@ u32 dom, u16 nr_frames, s16 *status, - memory_t **frame_list) + unsigned long **frame_list) { struct gnttab_setup_table op; int rc, i; diff -r 99914b54f7bf -r 81576d3d1ca8 tools/python/xen/lowlevel/xu/xu.c --- a/tools/python/xen/lowlevel/xu/xu.c Thu Aug 18 18:40:02 2005 +++ b/tools/python/xen/lowlevel/xu/xu.c Fri Aug 19 18:19:28 2005 @@ -844,7 +844,7 @@ case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT): P2C(blkif_be_connect_t, domid, u32); P2C(blkif_be_connect_t, blkif_handle, u32); - P2C(blkif_be_connect_t, shmem_frame, memory_t); + P2C(blkif_be_connect_t, shmem_frame, unsigned long); P2C(blkif_be_connect_t, shmem_ref, u32); P2C(blkif_be_connect_t, evtchn, u16); break; @@ -906,9 +906,9 @@ case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT): P2C(netif_be_connect_t, domid, u32); P2C(netif_be_connect_t, netif_handle, u32); - P2C(netif_be_connect_t, tx_shmem_frame, memory_t); + P2C(netif_be_connect_t, tx_shmem_frame, unsigned long); P2C(netif_be_connect_t, tx_shmem_ref, u32); - P2C(netif_be_connect_t, rx_shmem_frame, memory_t); + P2C(netif_be_connect_t, rx_shmem_frame, unsigned long); P2C(netif_be_connect_t, rx_shmem_ref, u32); P2C(netif_be_connect_t, evtchn, u16); break; @@ -942,7 +942,7 @@ P2C(usbif_fe_driver_status_changed_t, status, u32); break; case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT): - P2C(usbif_fe_interface_connect_t, shmem_frame, memory_t); + P2C(usbif_fe_interface_connect_t, shmem_frame, unsigned long); break; case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT): break; @@ -956,7 +956,7 @@ break; case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT): P2C(usbif_be_connect_t, domid, domid_t); - P2C(usbif_be_connect_t, shmem_frame, memory_t); + P2C(usbif_be_connect_t, shmem_frame, unsigned long); P2C(usbif_be_connect_t, evtchn, u32); P2C(usbif_be_connect_t, bandwidth, u32); P2C(usbif_be_connect_t, status, u32); diff -r 99914b54f7bf -r 81576d3d1ca8 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Thu Aug 18 18:40:02 2005 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Aug 19 18:19:28 2005 @@ -36,8 +36,10 @@ from xen.xend.server import SrvDaemon; xend = SrvDaemon.instance() from xen.xend.server import messages from xen.xend.server.channel import EventChannel, channelFactory +from xen.util.blkif import blkdev_name_to_number, expand_dev_name from xen.xend import sxp +from xen.xend import Blkctl from xen.xend.PrettyPrint import prettyprintstring from xen.xend.XendBootloader import bootloader from xen.xend.XendLogging import log @@ -380,6 +382,39 @@ return ctrl def createDevice(self, type, devconfig, change=False): + if type == 'vbd': + + backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0')) + + devnum = blkdev_name_to_number(sxp.child_value(devconfig, 'dev')) + + # create backend db + backdb = backdom.db.addChild("/backend/%s/%s/%d" % + (type, self.uuid, devnum)) + + # create frontend db + db = self.db.addChild("/device/%s/%d" % (type, devnum)) + + db['virtual-device'] = "%i" % devnum + #db['backend'] = sxp.child_value(devconfig, 'backend', '0') + db['backend'] = backdb.getPath() + db['backend-id'] = "%i" % int(sxp.child_value(devconfig, + 'backend', '0')) + + backdb['frontend'] = db.getPath() + (type, params) = string.split(sxp.child_value(devconfig, 'uname'), ':', 1) + node = Blkctl.block('bind', type, params) + backdb['frontend-id'] = "%i" % self.id + backdb['physical-device'] = "%li" % blkdev_name_to_number(node) + backdb.saveDB(save=True) + + # Ok, super gross, this really doesn't belong in the frontend db... + db['type'] = type + db['node'] = node + db['params'] = params + db.saveDB(save=True) + + return ctrl = self.findDeviceController(type) return ctrl.createDevice(devconfig, recreate=self.recreate, change=change) @@ -671,6 +706,16 @@ for ctrl in self.getDeviceControllers(): if ctrl.isDestroyed(): continue ctrl.destroyController(reboot=reboot) + ddb = self.db.addChild("/device") + for type in ddb.keys(): + if type == 'vbd': + typedb = ddb.addChild(type) + for dev in typedb.keys(): + devdb = typedb.addChild(str(dev)) + Blkctl.block('unbind', devdb['type'].getData(), + devdb['node'].getData()) + typedb[dev].delete() + typedb.saveDB(save=True) def show(self): """Print virtual machine info. @@ -926,6 +971,7 @@ at creation time, for example when it uses NFS root. """ + return blkif = self.getDeviceController("vbd", error=False) if not blkif: blkif = self.createDeviceController("vbd") diff -r 99914b54f7bf -r 81576d3d1ca8 tools/python/xen/xend/server/event.py --- a/tools/python/xen/xend/server/event.py Thu Aug 18 18:40:02 2005 +++ b/tools/python/xen/xend/server/event.py Fri Aug 19 18:19:28 2005 @@ -50,7 +50,7 @@ def dataReceived(self, data): try: self.parser.input(data) - if self.parser.ready(): + while(self.parser.ready()): val = self.parser.get_val() res = self.dispatch(val) self.send_result(res) diff -r 99914b54f7bf -r 81576d3d1ca8 tools/python/xen/xend/server/relocate.py --- a/tools/python/xen/xend/server/relocate.py Thu Aug 18 18:40:02 2005 +++ b/tools/python/xen/xend/server/relocate.py Fri Aug 19 18:19:28 2005 @@ -42,7 +42,7 @@ def dataReceived(self, data): try: self.parser.input(data) - if self.parser.ready(): + while(self.parser.ready()): val = self.parser.get_val() res = self.dispatch(val) self.send_result(res) diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/Makefile --- a/tools/security/Makefile Thu Aug 18 18:40:02 2005 +++ b/tools/security/Makefile Fri Aug 19 18:19:28 2005 @@ -2,27 +2,71 @@ include $(XEN_ROOT)/tools/Rules.mk SRCS = secpol_tool.c -CFLAGS += -static CFLAGS += -Wall CFLAGS += -Werror CFLAGS += -O3 CFLAGS += -fno-strict-aliasing -CFLAGS += -I. +CFLAGS += -I. -I/usr/include/libxml2 +CFLAGS_XML2BIN += $(shell xml2-config --cflags --libs ) +#if above does not work, try -L/usr/lib -lxml2 -lz -lpthread -lm +XML2VERSION = $(shell xml2-config --version ) +VALIDATE_SCHEMA=$(shell if [[ $(XML2VERSION) < 2.6.20 ]]; then echo ""; else echo "-DVALIDATE_SCHEMA"; fi; ) +ifeq ($(ACM_USE_SECURITY_POLICY),ACM_NULL_POLICY) +POLICY=null +endif +ifeq ($(ACM_USE_SECURITY_POLICY),ACM_CHINESE_WALL_POLICY) +POLICY=chwall +endif +ifeq ($(ACM_USE_SECURITY_POLICY),ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) +POLICY=ste +endif +ifeq ($(ACM_USE_SECURITY_POLICY),ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) +POLICY=chwall_ste +endif +POLICYFILE=./policies/$(POLICY)/$(POLICY).bin + +ifneq ($(ACM_USE_SECURITY_POLICY), ACM_NULL_POLICY) all: build + +install:all + +default:all +else +all: + +install: + +default: +endif + build: mk-symlinks $(MAKE) secpol_tool + $(MAKE) secpol_xml2bin + chmod 700 ./setlabel.sh + chmod 700 ./updategrub.sh -default: all - -install: all - -secpol_tool : secpol_tool.c +secpol_tool : secpol_tool.c secpol_compat.h $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< +secpol_xml2bin : secpol_xml2bin.c secpol_xml2bin.h secpol_compat.h + $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_XML2BIN) $(VALIDATE_SCHEMA) -o $@ $< + clean: - rm -rf secpol_tool xen + rm -rf secpol_tool secpol_xml2bin xen +policy_clean: + rm -rf policies/*/*.bin policies/*/*.map + +mrproper: clean policy_clean + + +$(POLICYFILE) : build + @./secpol_xml2bin $(POLICY) > /dev/null + +boot_install: $(POLICYFILE) + @cp $(POLICYFILE) /boot + @./updategrub.sh $(POLICY) $(PWD)/$(XEN_ROOT) LINUX_ROOT := $(XEN_ROOT)/linux-2.6-xen-sparse mk-symlinks: diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/secpol_tool.c --- a/tools/security/secpol_tool.c Thu Aug 18 18:40:02 2005 +++ b/tools/security/secpol_tool.c Fri Aug 19 18:19:28 2005 @@ -31,18 +31,8 @@ #include <stdlib.h> #include <sys/ioctl.h> #include <string.h> -#include <stdint.h> #include <netinet/in.h> - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - +#include "secpol_compat.h" #include <xen/acm.h> #include <xen/acm_ops.h> #include <xen/linux/privcmd.h> @@ -270,171 +260,6 @@ } } -/*************************** set policy ****************************/ - -int acm_domain_set_chwallpolicy(void *bufstart, int buflen) -{ -#define CWALL_MAX_SSIDREFS 6 -#define CWALL_MAX_TYPES 10 -#define CWALL_MAX_CONFLICTSETS 2 - - struct acm_chwall_policy_buffer *chwall_bin_pol = - (struct acm_chwall_policy_buffer *) bufstart; - domaintype_t *ssidrefs, *conflicts; - int ret = 0; - int j; - - chwall_bin_pol->chwall_max_types = htonl(CWALL_MAX_TYPES); - chwall_bin_pol->chwall_max_ssidrefs = htonl(CWALL_MAX_SSIDREFS); - chwall_bin_pol->policy_code = htonl(ACM_CHINESE_WALL_POLICY); - chwall_bin_pol->policy_version = htonl(ACM_CHWALL_VERSION); - chwall_bin_pol->chwall_ssid_offset = - htonl(sizeof(struct acm_chwall_policy_buffer)); - chwall_bin_pol->chwall_max_conflictsets = - htonl(CWALL_MAX_CONFLICTSETS); - chwall_bin_pol->chwall_conflict_sets_offset = - htonl(ntohl(chwall_bin_pol->chwall_ssid_offset) + - sizeof(domaintype_t) * CWALL_MAX_SSIDREFS * CWALL_MAX_TYPES); - chwall_bin_pol->chwall_running_types_offset = 0; /* not set */ - chwall_bin_pol->chwall_conflict_aggregate_offset = 0; /* not set */ - ret += sizeof(struct acm_chwall_policy_buffer); - /* now push example ssids into the buffer (max_ssidrefs x max_types entries) */ - /* check buffer size */ - if ((buflen - ret) < - (CWALL_MAX_TYPES * CWALL_MAX_SSIDREFS * sizeof(domaintype_t))) - return -1; /* not enough space */ - - ssidrefs = (domaintype_t *) (bufstart + - ntohl(chwall_bin_pol->chwall_ssid_offset)); - memset(ssidrefs, 0, - CWALL_MAX_TYPES * CWALL_MAX_SSIDREFS * sizeof(domaintype_t)); - - /* now set type j-1 for ssidref i+1 */ - for (j = 0; j <= CWALL_MAX_SSIDREFS; j++) - if ((0 < j) && (j <= CWALL_MAX_TYPES)) - ssidrefs[j * CWALL_MAX_TYPES + j - 1] = htons(1); - - ret += CWALL_MAX_TYPES * CWALL_MAX_SSIDREFS * sizeof(domaintype_t); - if ((buflen - ret) < - (CWALL_MAX_CONFLICTSETS * CWALL_MAX_TYPES * sizeof(domaintype_t))) - return -1; /* not enough space */ - - /* now the chinese wall policy conflict sets */ - conflicts = (domaintype_t *) (bufstart + - ntohl(chwall_bin_pol-> - chwall_conflict_sets_offset)); - memset((void *) conflicts, 0, - CWALL_MAX_CONFLICTSETS * CWALL_MAX_TYPES * - sizeof(domaintype_t)); - /* just 1 conflict set [0]={2,3}, [1]={1,5,6} */ - if (CWALL_MAX_TYPES > 3) - { - conflicts[2] = htons(1); - conflicts[3] = htons(1); /* {2,3} */ - conflicts[CWALL_MAX_TYPES + 1] = htons(1); - conflicts[CWALL_MAX_TYPES + 5] = htons(1); - conflicts[CWALL_MAX_TYPES + 6] = htons(1); /* {0,5,6} */ - } - ret += sizeof(domaintype_t) * CWALL_MAX_CONFLICTSETS * CWALL_MAX_TYPES; - return ret; -} - -int acm_domain_set_stepolicy(void *bufstart, int buflen) -{ -#define STE_MAX_SSIDREFS 6 -#define STE_MAX_TYPES 5 - - struct acm_ste_policy_buffer *ste_bin_pol = - (struct acm_ste_policy_buffer *) bufstart; - domaintype_t *ssidrefs; - int j, ret = 0; - - ste_bin_pol->ste_max_types = htonl(STE_MAX_TYPES); - ste_bin_pol->ste_max_ssidrefs = htonl(STE_MAX_SSIDREFS); - ste_bin_pol->policy_code = htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); - ste_bin_pol->policy_version = htonl(ACM_STE_VERSION); - ste_bin_pol->ste_ssid_offset = - htonl(sizeof(struct acm_ste_policy_buffer)); - ret += sizeof(struct acm_ste_policy_buffer); - /* check buffer size */ - if ((buflen - ret) < - (STE_MAX_TYPES * STE_MAX_SSIDREFS * sizeof(domaintype_t))) - return -1; /* not enough space */ - - ssidrefs = - (domaintype_t *) (bufstart + ntohl(ste_bin_pol->ste_ssid_offset)); - memset(ssidrefs, 0, - STE_MAX_TYPES * STE_MAX_SSIDREFS * sizeof(domaintype_t)); - /* all types 1 for ssidref 1 */ - for (j = 0; j < STE_MAX_TYPES; j++) - ssidrefs[1 * STE_MAX_TYPES + j] = htons(1); - /* now set type j-1 for ssidref j */ - for (j = 0; j < STE_MAX_SSIDREFS; j++) - if ((0 < j) && (j <= STE_MAX_TYPES)) - ssidrefs[j * STE_MAX_TYPES + j - 1] = htons(1); - ret += STE_MAX_TYPES * STE_MAX_SSIDREFS * sizeof(domaintype_t); - return ret; -} - -#define MAX_PUSH_BUFFER 16384 -u8 push_buffer[MAX_PUSH_BUFFER]; - -int acm_domain_setpolicy(int xc_handle) -{ - int ret; - struct acm_policy_buffer *bin_pol; - acm_op_t op; - - /* future: read policy from file and set it */ - bin_pol = (struct acm_policy_buffer *) push_buffer; - bin_pol->policy_version = htonl(ACM_POLICY_VERSION); - bin_pol->magic = htonl(ACM_MAGIC); - bin_pol->primary_policy_code = htonl(ACM_CHINESE_WALL_POLICY); - bin_pol->secondary_policy_code = - htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); - - bin_pol->len = htonl(sizeof(struct acm_policy_buffer)); - bin_pol->primary_buffer_offset = htonl(ntohl(bin_pol->len)); - ret = - acm_domain_set_chwallpolicy(push_buffer + - ntohl(bin_pol->primary_buffer_offset), - MAX_PUSH_BUFFER - - ntohl(bin_pol->primary_buffer_offset)); - if (ret < 0) - { - printf("ERROR creating chwallpolicy buffer.\n"); - return -1; - } - bin_pol->len = htonl(ntohl(bin_pol->len) + ret); - bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len)); - ret = acm_domain_set_stepolicy(push_buffer + - ntohl(bin_pol->secondary_buffer_offset), - MAX_PUSH_BUFFER - - ntohl(bin_pol->secondary_buffer_offset)); - if (ret < 0) - { - printf("ERROR creating chwallpolicy buffer.\n"); - return -1; - } - bin_pol->len = htonl(ntohl(bin_pol->len) + ret); - - /* dump it and then push it down into xen/acm */ - acm_dump_policy_buffer(push_buffer, ntohl(bin_pol->len)); - - op.cmd = ACM_SETPOLICY; - op.interface_version = ACM_INTERFACE_VERSION; - op.u.setpolicy.pushcache = (void *) push_buffer; - op.u.setpolicy.pushcache_size = ntohl(bin_pol->len); - ret = do_acm_op(xc_handle, &op); - - if (ret) - printf("ERROR setting policy. Use 'xm dmesg' to see details.\n"); - else - printf("Successfully changed policy.\n"); - - return ret; -} - /******************************* get policy ******************************/ #define PULL_CACHE_SIZE 8192 @@ -602,7 +427,6 @@ void usage(char *progname) { printf("Use: %s \n" - "\t setpolicy\n" "\t getpolicy\n" "\t dumpstats\n" "\t loadpolicy <binary policy file>\n", progname); @@ -623,12 +447,7 @@ exit(-1); } - if (!strcmp(argv[1], "setpolicy")) - { - if (argc != 2) - usage(argv[0]); - ret = acm_domain_setpolicy(acm_cmd_fd); - } else if (!strcmp(argv[1], "getpolicy")) { + if (!strcmp(argv[1], "getpolicy")) { if (argc != 2) usage(argv[0]); ret = acm_domain_getpolicy(acm_cmd_fd); diff -r 99914b54f7bf -r 81576d3d1ca8 tools/xentrace/xentrace.c --- a/tools/xentrace/xentrace.c Thu Aug 18 18:40:02 2005 +++ b/tools/xentrace/xentrace.c Fri Aug 19 18:19:28 2005 @@ -95,13 +95,13 @@ /** * get_tbufs - get pointer to and size of the trace buffers - * @mach_addr: location to store machine address if the trace buffers to - * @size: location to store the size of a trace buffer to + * @mfn: location to store mfn of the trace buffers to + * @size: location to store the size of a trace buffer to * * Gets the machine address of the trace pointer area and the size of the * per CPU buffers. */ -void get_tbufs(unsigned long *mach_addr, unsigned long *size) +void get_tbufs(unsigned long *mfn, unsigned long *size) { int ret; dom0_op_t op; /* dom0 op we'll build */ @@ -121,19 +121,19 @@ exit(EXIT_FAILURE); } - *mach_addr = op.u.tbufcontrol.mach_addr; - *size = op.u.tbufcontrol.size; + *mfn = op.u.tbufcontrol.buffer_mfn; + *size = op.u.tbufcontrol.size; } /** * map_tbufs - memory map Xen trace buffers into user space - * @tbufs: machine address of the trace buffers + * @tbufs_mfn: mfn of the trace buffers * @num: number of trace buffers to map * @size: size of each trace buffer * * Maps the Xen trace buffers them into process address space. */ -struct t_buf *map_tbufs(unsigned long tbufs_mach, unsigned int num, +struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num, unsigned long size) { int xc_handle; /* file descriptor for /proc/xen/privcmd */ @@ -149,7 +149,7 @@ tbufs_mapped = xc_map_foreign_range(xc_handle, 0 /* Dom 0 ID */, size * num, PROT_READ, - tbufs_mach >> PAGE_SHIFT); + tbufs_mfn); xc_interface_close(xc_handle); @@ -231,7 +231,7 @@ /** * init_rec_ptrs - initialises data area pointers to locations in user space - * @tbufs_mach: machine base address of the trace buffer area + * @tbufs_mfn: base mfn of the trace buffer area * @tbufs_mapped: user virtual address of base of trace buffer area * @meta: array of user-space pointers to struct t_buf's of metadata * @num: number of trace buffers @@ -240,7 +240,7 @@ * mapped in user space. Note that the trace buffer metadata contains machine * pointers - the array returned allows more convenient access to them. */ -struct t_rec **init_rec_ptrs(unsigned long tbufs_mach, +struct t_rec **init_rec_ptrs(unsigned long tbufs_mfn, struct t_buf *tbufs_mapped, struct t_buf **meta, unsigned int num) @@ -256,7 +256,7 @@ } for ( i = 0; i < num; i++ ) - data[i] = (struct t_rec *)(meta[i]->rec_addr - tbufs_mach + data[i] = (struct t_rec *)(meta[i]->rec_addr - (tbufs_mfn<<XC_PAGE_SHIFT) /* XXX */ + (unsigned long)tbufs_mapped); return data; @@ -330,7 +330,7 @@ struct t_rec **data; /* pointers to the trace buffer data areas * where they are mapped into user space. */ unsigned long *cons; /* store tail indexes for the trace buffers */ - unsigned long tbufs_mach; /* machine address of the tbufs */ + unsigned long tbufs_mfn; /* mfn of the tbufs */ unsigned int num; /* number of trace buffers / logical CPUS */ unsigned long size; /* size of a single trace buffer */ @@ -340,14 +340,14 @@ num = get_num_cpus(); /* setup access to trace buffers */ - get_tbufs(&tbufs_mach, &size); - tbufs_mapped = map_tbufs(tbufs_mach, num, size); + get_tbufs(&tbufs_mfn, &size); + tbufs_mapped = map_tbufs(tbufs_mfn, num, size); size_in_recs = (size - sizeof(struct t_buf)) / sizeof(struct t_rec); /* build arrays of convenience ptrs */ meta = init_bufs_ptrs (tbufs_mapped, num, size); - data = init_rec_ptrs (tbufs_mach, tbufs_mapped, meta, num); + data = init_rec_ptrs (tbufs_mfn, tbufs_mapped, meta, num); cons = init_tail_idxs (meta, num); /* now, scan buffers for events */ diff -r 99914b54f7bf -r 81576d3d1ca8 xen/Rules.mk --- a/xen/Rules.mk Thu Aug 18 18:40:02 2005 +++ b/xen/Rules.mk Fri Aug 19 18:19:28 2005 @@ -10,14 +10,6 @@ optimize ?= y domu_debug ?= n crash_debug ?= n - -# ACM_USE_SECURITY_POLICY is set to security policy of Xen -# Supported models are: -# ACM_NULL_POLICY (ACM will not be built with this policy) -# ACM_CHINESE_WALL_POLICY -# ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY -# ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY -ACM_USE_SECURITY_POLICY ?= ACM_NULL_POLICY include $(BASEDIR)/../Config.mk diff -r 99914b54f7bf -r 81576d3d1ca8 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Thu Aug 18 18:40:02 2005 +++ b/xen/arch/x86/domain.c Fri Aug 19 18:19:28 2005 @@ -217,8 +217,16 @@ return xmalloc(struct vcpu); } +/* We assume that vcpu 0 is always the last one to be freed in a + domain i.e. if v->vcpu_id == 0, the domain should be + single-processor. */ void arch_free_vcpu_struct(struct vcpu *v) { + struct vcpu *p; + for_each_vcpu(v->domain, p) { + if (p->next_in_list == v) + p->next_in_list = v->next_in_list; + } xfree(v); } @@ -403,7 +411,7 @@ { if ( ((c->user_regs.cs & 3) == 0) || ((c->user_regs.ss & 3) == 0) ) - return -EINVAL; + return -EINVAL; } clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); @@ -457,7 +465,7 @@ if ( !(c->flags & VGCF_VMX_GUEST) ) #endif if ( !get_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT], d, - PGT_base_page_table) ) + PGT_base_page_table) ) return -EINVAL; } diff -r 99914b54f7bf -r 81576d3d1ca8 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Thu Aug 18 18:40:02 2005 +++ b/xen/arch/x86/domain_build.c Fri Aug 19 18:19:28 2005 @@ -22,16 +22,28 @@ #include <asm/i387.h> #include <asm/shadow.h> -/* opt_dom0_mem: memory allocated to domain 0. */ -static unsigned int opt_dom0_mem; +static long dom0_nrpages; + +/* + * dom0_mem: + * If +ve: + * * The specified amount of memory is allocated to domain 0. + * If -ve: + * * All of memory is allocated to domain 0, minus the specified amount. + * If not specified: + * * All of memory is allocated to domain 0, minus 1/16th which is reserved + * for uses such as DMA buffers (the reservation is clamped to 128MB). + */ static void parse_dom0_mem(char *s) { - unsigned long long bytes = parse_size_and_unit(s); - /* If no unit is specified we default to kB units, not bytes. */ - if ( isdigit(s[strlen(s)-1]) ) - opt_dom0_mem = (unsigned int)bytes; - else - opt_dom0_mem = (unsigned int)(bytes >> 10); + unsigned long long bytes; + char *t = s; + if ( *s == '-' ) + t++; + bytes = parse_size_and_unit(t); + dom0_nrpages = bytes >> PAGE_SHIFT; + if ( *s == '-' ) + dom0_nrpages = -dom0_nrpages; } custom_param("dom0_mem", parse_dom0_mem); @@ -137,12 +149,30 @@ printk("*** LOADING DOMAIN 0 ***\n"); - /* By default DOM0 is allocated all available memory. */ d->max_pages = ~0U; - if ( (nr_pages = opt_dom0_mem >> (PAGE_SHIFT - 10)) == 0 ) + + /* + * If domain 0 allocation isn't specified, reserve 1/16th of available + * memory for things like DMA buffers. This reservation is clamped to + * a maximum of 128MB. + */ + if ( dom0_nrpages == 0 ) + { + dom0_nrpages = avail_domheap_pages() + + ((initrd_len + PAGE_SIZE - 1) >> PAGE_SHIFT) + + ((image_len + PAGE_SIZE - 1) >> PAGE_SHIFT); + dom0_nrpages = min(dom0_nrpages / 16, 128L << (20 - PAGE_SHIFT)); + dom0_nrpages = -dom0_nrpages; + } + + /* Negative memory specification means "all memory - specified amount". */ + if ( dom0_nrpages < 0 ) nr_pages = avail_domheap_pages() + ((initrd_len + PAGE_SIZE - 1) >> PAGE_SHIFT) + - ((image_len + PAGE_SIZE - 1) >> PAGE_SHIFT); + ((image_len + PAGE_SIZE - 1) >> PAGE_SHIFT) + + dom0_nrpages; + else + nr_pages = dom0_nrpages; if ( (rc = parseelfimage(&dsi)) != 0 ) return rc; diff -r 99914b54f7bf -r 81576d3d1ca8 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Thu Aug 18 18:40:02 2005 +++ b/xen/arch/x86/mm.c Fri Aug 19 18:19:28 2005 @@ -2633,14 +2633,16 @@ if ( entries > FIRST_RESERVED_GDT_ENTRY ) return -EINVAL; - + shadow_sync_all(d); /* Check the pages in the new GDT. */ - for ( i = 0; i < nr_pages; i++ ) - if ( ((pfn = frames[i]) >= max_page) || - !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) + for ( i = 0; i < nr_pages; i++ ) { + pfn = frames[i]; + if ((pfn >= max_page) || + !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) goto fail; + } /* Tear down the old GDT. */ destroy_gdt(v); @@ -2687,22 +2689,24 @@ } -long do_update_descriptor(unsigned long pa, u64 desc) +long do_update_descriptor(u64 pa, u64 desc) { struct domain *dom = current->domain; unsigned long gpfn = pa >> PAGE_SHIFT; unsigned long mfn; - unsigned int offset = (pa & ~PAGE_MASK) / sizeof(struct desc_struct); + unsigned int offset; struct desc_struct *gdt_pent, d; struct pfn_info *page; long ret = -EINVAL; + offset = ((unsigned int)pa & ~PAGE_MASK) / sizeof(struct desc_struct); + *(u64 *)&d = desc; LOCK_BIGLOCK(dom); if ( !VALID_MFN(mfn = __gpfn_to_mfn(dom, gpfn)) || - ((pa % sizeof(struct desc_struct)) != 0) || + (((unsigned int)pa % sizeof(struct desc_struct)) != 0) || (mfn >= max_page) || !check_descriptor(&d) ) { diff -r 99914b54f7bf -r 81576d3d1ca8 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Thu Aug 18 18:40:02 2005 +++ b/xen/arch/x86/physdev.c Fri Aug 19 18:19:28 2005 @@ -106,7 +106,7 @@ (op.u.set_iobitmap.nr_ports > 65536) ) break; ret = 0; - current->arch.iobmp = (u8 *)op.u.set_iobitmap.bitmap; + current->arch.iobmp = op.u.set_iobitmap.bitmap; current->arch.iobmp_limit = op.u.set_iobitmap.nr_ports; break; default: diff -r 99914b54f7bf -r 81576d3d1ca8 xen/common/event_channel.c --- a/xen/common/event_channel.c Thu Aug 18 18:40:02 2005 +++ b/xen/common/event_channel.c Fri Aug 19 18:19:28 2005 @@ -588,7 +588,6 @@ long rc = 0; if ( (vcpu >= MAX_VIRT_CPUS) || (d->vcpu[vcpu] == NULL) ) { - printf("vcpu %d bad.\n", vcpu); return -EINVAL; } @@ -596,7 +595,6 @@ if ( !port_is_valid(d, port) ) { - printf("port %d bad.\n", port); rc = -EINVAL; goto out; } @@ -610,7 +608,6 @@ chn->notify_vcpu_id = vcpu; break; default: - printf("evtchn type %d can't be rebound.\n", chn->state); rc = -EINVAL; break; } diff -r 99914b54f7bf -r 81576d3d1ca8 xen/common/lib.c --- a/xen/common/lib.c Thu Aug 18 18:40:02 2005 +++ b/xen/common/lib.c Fri Aug 19 18:19:28 2005 @@ -450,8 +450,10 @@ ret <<= 10; case 'M': case 'm': ret <<= 10; - case 'K': case 'k': + case 'K': case 'k': default: ret <<= 10; + case 'B': case 'b': + break; } return ret; diff -r 99914b54f7bf -r 81576d3d1ca8 xen/common/schedule.c --- a/xen/common/schedule.c Thu Aug 18 18:40:02 2005 +++ b/xen/common/schedule.c Fri Aug 19 18:19:28 2005 @@ -38,6 +38,8 @@ #include <xen/mm.h> #include <public/sched_ctl.h> +extern void arch_getdomaininfo_ctxt(struct vcpu *, + struct vcpu_guest_context *); /* opt_sched: scheduler - default to SEDF */ static char opt_sched[10] = "sedf"; string_param("sched", opt_sched); @@ -82,7 +84,8 @@ int i; SCHED_OP(free_task, d); - for (i = 0; i < MAX_VIRT_CPUS; i++) + /* vcpu 0 has to be the last one destructed. */ + for (i = MAX_VIRT_CPUS-1; i >= 0; i--) if ( d->vcpu[i] ) arch_free_vcpu_struct(d->vcpu[i]); @@ -295,10 +298,36 @@ return 0; } +static long do_vcpu_pickle(int vcpu, unsigned long arg) +{ + struct vcpu *v; + vcpu_guest_context_t *c; + int ret = 0; + + if (vcpu >= MAX_VIRT_CPUS) + return -EINVAL; + v = current->domain->vcpu[vcpu]; + if (!v) + return -ESRCH; + /* Don't pickle vcpus which are currently running */ + if (!test_bit(_VCPUF_down, &v->vcpu_flags)) { + return -EBUSY; + } + c = xmalloc(vcpu_guest_context_t); + if (!c) + return -ENOMEM; + arch_getdomaininfo_ctxt(v, c); + if (copy_to_user((vcpu_guest_context_t *)arg, + (const vcpu_guest_context_t *)c, sizeof(*c))) + ret = -EFAULT; + xfree(c); + return ret; +} + /* * Demultiplex scheduler-related hypercalls. */ -long do_sched_op(unsigned long op) +long do_sched_op(unsigned long op, unsigned long arg) { long ret = 0; @@ -332,6 +361,11 @@ case SCHEDOP_vcpu_up: { ret = do_vcpu_up((int)(op >> SCHEDOP_vcpushift)); + break; + } + case SCHEDOP_vcpu_pickle: + { + ret = do_vcpu_pickle((int)(op >> SCHEDOP_vcpushift), arg); break; } diff -r 99914b54f7bf -r 81576d3d1ca8 xen/common/trace.c --- a/xen/common/trace.c Thu Aug 18 18:40:02 2005 +++ b/xen/common/trace.c Fri Aug 19 18:19:28 2005 @@ -113,10 +113,10 @@ switch ( tbc->op) { case DOM0_TBUF_GET_INFO: - tbc->cpu_mask = tb_cpu_mask; - tbc->evt_mask = tb_event_mask; - tbc->mach_addr = __pa(t_bufs[0]); - tbc->size = opt_tbuf_size * PAGE_SIZE; + tbc->cpu_mask = tb_cpu_mask; + tbc->evt_mask = tb_event_mask; + tbc->buffer_mfn = __pa(t_bufs[0]) >> PAGE_SHIFT; + tbc->size = opt_tbuf_size * PAGE_SIZE; break; case DOM0_TBUF_SET_CPU_MASK: tb_cpu_mask = tbc->cpu_mask; diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/arch-ia64.h --- a/xen/include/public/arch-ia64.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/arch-ia64.h Fri Aug 19 18:19:28 2005 @@ -12,9 +12,6 @@ #define MAX_VIRT_CPUS 1 #ifndef __ASSEMBLY__ - -/* NB. Both the following are 64 bits each. */ -typedef unsigned long memory_t; /* Full-sized pointer/address/memory-size. */ #define MAX_NR_SECTION 32 // at most 32 memory holes typedef struct { diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/arch-x86_32.h --- a/xen/include/public/arch-x86_32.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/arch-x86_32.h Fri Aug 19 18:19:28 2005 @@ -63,9 +63,6 @@ #ifndef __ASSEMBLY__ -/* NB. Both the following are 32 bits each. */ -typedef unsigned long memory_t; /* Full-sized pointer/address/memory-size. */ - /* * Send an array of these to HYPERVISOR_set_trap_table() */ @@ -74,10 +71,10 @@ #define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl)) #define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2)) typedef struct trap_info { - u8 vector; /* exception vector */ - u8 flags; /* 0-3: privilege level; 4: clear event enable? */ - u16 cs; /* code selector */ - memory_t address; /* code address */ + u8 vector; /* exception vector */ + u8 flags; /* 0-3: privilege level; 4: clear event enable? */ + u16 cs; /* code selector */ + unsigned long address; /* code offset */ } trap_info_t; typedef struct cpu_user_regs { diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/arch-x86_64.h --- a/xen/include/public/arch-x86_64.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/arch-x86_64.h Fri Aug 19 18:19:28 2005 @@ -103,9 +103,6 @@ /* Bottom of switch_to_user stack frame. */ }; -/* NB. Both the following are 64 bits each. */ -typedef unsigned long memory_t; /* Full-sized pointer/address/memory-size. */ - /* * Send an array of these to HYPERVISOR_set_trap_table(). * N.B. As in x86/32 mode, the privilege level specifies which modes may enter @@ -121,10 +118,10 @@ #define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl)) #define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2)) typedef struct trap_info { - u8 vector; /* exception vector */ - u8 flags; /* 0-3: privilege level; 4: clear event enable? */ - u16 cs; /* code selector */ - memory_t address; /* code address */ + u8 vector; /* exception vector */ + u8 flags; /* 0-3: privilege level; 4: clear event enable? */ + u16 cs; /* code selector */ + unsigned long address; /* code offset */ } trap_info_t; typedef struct cpu_user_regs { diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/dom0_ops.h --- a/xen/include/public/dom0_ops.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/dom0_ops.h Fri Aug 19 18:19:28 2005 @@ -19,7 +19,7 @@ * This makes sure that old versions of dom0 tools will stop working in a * well-defined way (rather than crashing the machine, for instance). */ -#define DOM0_INTERFACE_VERSION 0xAAAA100E +#define DOM0_INTERFACE_VERSION 0xAAAA100F /************************************************************************/ @@ -27,10 +27,10 @@ typedef struct { /* IN variables. */ domid_t domain; - memory_t max_pfns; + unsigned long max_pfns; void *buffer; /* OUT variables. */ - memory_t num_pfns; + unsigned long num_pfns; } dom0_getmemlist_t; #define DOM0_SCHEDCTL 6 @@ -83,9 +83,9 @@ #define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code. */ #define DOMFLAGS_SHUTDOWNSHIFT 16 u32 flags; - memory_t tot_pages; - memory_t max_pages; - memory_t shared_info_frame; /* MFN of shared_info struct */ + unsigned long tot_pages; + unsigned long max_pages; + unsigned long shared_info_frame; /* MFN of shared_info struct */ u64 cpu_time; u32 n_vcpu; s32 vcpu_to_cpu[MAX_VIRT_CPUS]; /* current mapping */ @@ -155,7 +155,7 @@ typedef struct { /* IN variables. */ - memory_t pfn; /* Machine page frame number to query. */ + unsigned long pfn; /* Machine page frame number to query. */ domid_t domain; /* To which domain does the frame belong? */ /* OUT variables. */ /* Is the page PINNED to a type? */ @@ -197,7 +197,7 @@ unsigned long cpu_mask; u32 evt_mask; /* OUT variables */ - memory_t mach_addr; + unsigned long buffer_mfn; u32 size; } dom0_tbufcontrol_t; @@ -211,8 +211,8 @@ u32 sockets_per_node; u32 nr_nodes; u32 cpu_khz; - memory_t total_pages; - memory_t free_pages; + unsigned long total_pages; + unsigned long free_pages; } dom0_physinfo_t; /* @@ -252,7 +252,7 @@ u32 op; unsigned long *dirty_bitmap; /* pointer to locked buffer */ /* IN/OUT variables. */ - memory_t pages; /* size of buffer, updated with actual size */ + unsigned long pages; /* size of buffer, updated with actual size */ /* OUT variables. */ dom0_shadow_control_stats_t stats; } dom0_shadow_control_t; @@ -260,15 +260,15 @@ #define DOM0_SETDOMAINMAXMEM 28 typedef struct { /* IN variables. */ - domid_t domain; - memory_t max_memkb; + domid_t domain; + unsigned long max_memkb; } dom0_setdomainmaxmem_t; #define DOM0_GETPAGEFRAMEINFO2 29 /* batched interface */ typedef struct { /* IN variables. */ - domid_t domain; - memory_t num; + domid_t domain; + unsigned long num; /* IN/OUT variables. */ unsigned long *array; } dom0_getpageframeinfo2_t; @@ -283,12 +283,12 @@ #define DOM0_ADD_MEMTYPE 31 typedef struct { /* IN variables. */ - memory_t pfn; - memory_t nr_pfns; - u32 type; - /* OUT variables. */ - u32 handle; - u32 reg; + unsigned long pfn; + unsigned long nr_pfns; + u32 type; + /* OUT variables. */ + u32 handle; + u32 reg; } dom0_add_memtype_t; /* @@ -311,8 +311,8 @@ /* IN variables. */ u32 reg; /* OUT variables. */ - memory_t pfn; - memory_t nr_pfns; + unsigned long pfn; + unsigned long nr_pfns; u32 type; } dom0_read_memtype_t; @@ -361,10 +361,10 @@ typedef struct { /* IN variables. */ domid_t first_domain; - memory_t max_domains; + unsigned int max_domains; dom0_getdomaininfo_t *buffer; /* OUT variables. */ - memory_t num_domains; + unsigned int num_domains; } dom0_getdomaininfolist_t; #define DOM0_PLATFORM_QUIRK 39 diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/grant_table.h --- a/xen/include/public/grant_table.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/grant_table.h Fri Aug 19 18:19:28 2005 @@ -153,13 +153,13 @@ #define GNTTABOP_map_grant_ref 0 typedef struct gnttab_map_grant_ref { /* IN parameters. */ - memory_t host_addr; + u64 host_addr; domid_t dom; grant_ref_t ref; u16 flags; /* GNTMAP_* */ /* OUT parameters. */ s16 handle; /* +ve: handle; -ve: GNTST_* */ - memory_t dev_bus_addr; + u64 dev_bus_addr; } gnttab_map_grant_ref_t; /* @@ -176,8 +176,8 @@ #define GNTTABOP_unmap_grant_ref 1 typedef struct gnttab_unmap_grant_ref { /* IN parameters. */ - memory_t host_addr; - memory_t dev_bus_addr; + u64 host_addr; + u64 dev_bus_addr; u16 handle; /* OUT parameters. */ s16 status; /* GNTST_* */ @@ -223,7 +223,7 @@ */ #define GNTTABOP_donate 4 typedef struct { - memory_t mfn; /* 0 */ + unsigned long mfn; /* 0 */ domid_t domid; /* 4 */ u16 handle; /* 8 */ s16 status; /* 10: GNTST_* */ diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/io/blkif.h --- a/xen/include/public/io/blkif.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/io/blkif.h Fri Aug 19 18:19:28 2005 @@ -18,7 +18,6 @@ #define BLKIF_OP_READ 0 #define BLKIF_OP_WRITE 1 -#define BLKIF_OP_PROBE 2 /* NB. Ring size must be small enough for sizeof(blkif_ring_t) <= PAGE_SIZE. */ #define BLKIF_RING_SIZE 64 @@ -33,7 +32,7 @@ typedef struct blkif_request { u8 operation; /* BLKIF_OP_??? */ u8 nr_segments; /* number of segments */ - blkif_vdev_t device; /* only for read/write requests */ + blkif_vdev_t handle; /* only for read/write requests */ unsigned long id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ /* @f_a_s[4:0]=last_sect ; @f_a_s[9:5]=first_sect */ @@ -71,31 +70,8 @@ DEFINE_RING_TYPES(blkif, blkif_request_t, blkif_response_t); -/* - * BLKIF_OP_PROBE: - * The request format for a probe request is constrained as follows: - * @operation == BLKIF_OP_PROBE - * @nr_segments == size of probe buffer in pages - * @device == unused (zero) - * @id == any value (echoed in response message) - * @sector_num == unused (zero) - * @frame_and_sects == list of page-sized buffers. - * (i.e., @first_sect == 0, @last_sect == 7). - * - * The response is a list of vdisk_t elements copied into the out-of-band - * probe buffer. On success the response status field contains the number - * of vdisk_t elements. - */ - #define VDISK_CDROM 0x1 #define VDISK_REMOVABLE 0x2 #define VDISK_READONLY 0x4 -typedef struct vdisk { - blkif_sector_t capacity; /* Size in terms of 512-byte sectors. */ - blkif_vdev_t device; /* Device number (opaque 16 bit value). */ - u16 info; /* Device type and flags (VDISK_*). */ - u16 sector_size; /* Minimum alignment for requests. */ -} vdisk_t; /* 16 bytes */ - #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */ diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/io/domain_controller.h --- a/xen/include/public/io/domain_controller.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/io/domain_controller.h Fri Aug 19 18:19:28 2005 @@ -139,7 +139,7 @@ */ typedef struct blkif_fe_interface_connect { u32 handle; - memory_t shmem_frame; + unsigned long shmem_frame; int shmem_ref; } blkif_fe_interface_connect_t; @@ -249,7 +249,7 @@ /* IN */ domid_t domid; /* Domain attached to new interface. */ u32 blkif_handle; /* Domain-specific interface handle. */ - memory_t shmem_frame; /* Page cont. shared comms window. */ + unsigned long shmem_frame;/* Page cont. shared comms window. */ int shmem_ref; /* Grant table reference. */ u32 evtchn; /* Event channel for notifications. */ /* OUT */ @@ -364,11 +364,11 @@ * STATUS_CONNECTED message. */ typedef struct netif_fe_interface_connect { - u32 handle; - memory_t tx_shmem_frame; - int tx_shmem_ref; - memory_t rx_shmem_frame; - int rx_shmem_ref; + u32 handle; + unsigned long tx_shmem_frame; + int tx_shmem_ref; + unsigned long rx_shmem_frame; + int rx_shmem_ref; } netif_fe_interface_connect_t; /* @@ -486,13 +486,13 @@ */ typedef struct netif_be_connect { /* IN */ - domid_t domid; /* Domain attached to new interface. */ - u32 netif_handle; /* Domain-specific interface handle. */ - memory_t tx_shmem_frame; /* Page cont. tx shared comms window. */ - int tx_shmem_ref; /* Grant reference for above */ - memory_t rx_shmem_frame; /* Page cont. rx shared comms window. */ - int rx_shmem_ref; /* Grant reference for above */ - u16 evtchn; /* Event channel for notifications. */ + domid_t domid; /* Domain attached to new interface. */ + u32 netif_handle; /* Domain-specific interface handle. */ + unsigned long tx_shmem_frame;/* Page cont. tx shared comms window. */ + int tx_shmem_ref; /* Grant reference for above */ + unsigned long rx_shmem_frame;/* Page cont. rx shared comms window. */ + int rx_shmem_ref; /* Grant reference for above */ + u16 evtchn; /* Event channel for notifications. */ /* OUT */ u32 status; } netif_be_connect_t; @@ -577,7 +577,7 @@ * STATUS_CONNECTED message. */ typedef struct usbif_fe_interface_connect { - memory_t shmem_frame; + unsigned long shmem_frame; } usbif_fe_interface_connect_t; /* @@ -660,7 +660,7 @@ typedef struct usbif_be_connect { /* IN */ domid_t domid; /* Domain attached to new interface. */ - memory_t shmem_frame; /* Page cont. shared comms window. */ + unsigned long shmem_frame;/* Page cont. shared comms window. */ u32 evtchn; /* Event channel for notifications. */ u32 bandwidth; /* Bandwidth allocated for isoch / int - us * per 1ms frame (ie between 0 and 900 or 800 @@ -780,7 +780,7 @@ #define PDB_CONNECTION_STATUS_UP 1 #define PDB_CONNECTION_STATUS_DOWN 2 u32 status; - memory_t ring; /* status: UP */ + unsigned long ring; /* status: UP */ u32 evtchn; /* status: UP */ } pdb_connection_t, *pdb_connection_p; diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/io/netif.h --- a/xen/include/public/io/netif.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/io/netif.h Fri Aug 19 18:19:28 2005 @@ -10,7 +10,7 @@ #define __XEN_PUBLIC_IO_NETIF_H__ typedef struct netif_tx_request { - memory_t addr; /* Machine address of packet. */ + unsigned long addr; /* Machine address of packet. */ u16 csum_blank:1; /* Proto csum field blank? */ u16 id:15; /* Echoed in response message. */ u16 size; /* Packet size in bytes. */ @@ -32,7 +32,7 @@ #ifdef CONFIG_XEN_NETDEV_GRANT_TX u32 addr; /* 0: Offset in page of start of received packet */ #else - memory_t addr; /* Machine address of packet. */ + unsigned long addr; /* Machine address of packet. */ #endif u16 csum_valid:1; /* Protocol checksum is validated? */ u16 id:15; diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/physdev.h --- a/xen/include/public/physdev.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/physdev.h Fri Aug 19 18:19:28 2005 @@ -27,8 +27,8 @@ typedef struct physdevop_set_iobitmap { /* IN */ - memory_t bitmap; - u32 nr_ports; + char *bitmap; + u32 nr_ports; } physdevop_set_iobitmap_t; typedef struct physdevop_apic { diff -r 99914b54f7bf -r 81576d3d1ca8 xen/include/public/xen.h --- a/xen/include/public/xen.h Thu Aug 18 18:40:02 2005 +++ b/xen/include/public/xen.h Fri Aug 19 18:19:28 2005 @@ -171,9 +171,9 @@ unsigned int cmd; union { /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR, REASSIGN_PAGE */ - memory_t mfn; + unsigned long mfn; /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */ - memory_t linear_addr; + unsigned long linear_addr; }; union { /* SET_LDT */ @@ -203,6 +203,7 @@ #define SCHEDOP_shutdown 2 /* Stop executing this domain. */ #define SCHEDOP_vcpu_down 3 /* make target VCPU not-runnable. */ #define SCHEDOP_vcpu_up 4 /* make target VCPU runnable. */ +#define SCHEDOP_vcpu_pickle 5 /* save a vcpu's context to memory. */ #define SCHEDOP_cmdmask 255 /* 8-bit command. */ #define SCHEDOP_reasonshift 8 /* 8-bit reason code. (SCHEDOP_shutdown) */ #define SCHEDOP_vcpushift 8 /* 8-bit VCPU target. (SCHEDOP_up|down) */ @@ -437,18 +438,18 @@ #define MAX_GUEST_CMDLINE 1024 typedef struct start_info { /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */ - memory_t nr_pages; /* Total pages allocated to this domain. */ - memory_t shared_info; /* MACHINE address of shared info struct. */ + unsigned long nr_pages; /* Total pages allocated to this domain. */ + unsigned long shared_info;/* MACHINE address of shared info struct. */ u32 flags; /* SIF_xxx flags. */ u16 domain_controller_evtchn; /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */ - memory_t pt_base; /* VIRTUAL address of page directory. */ - memory_t nr_pt_frames; /* Number of bootstrap p.t. frames. */ - memory_t mfn_list; /* VIRTUAL address of page-frame list. */ - memory_t mod_start; /* VIRTUAL address of pre-loaded module. */ - memory_t mod_len; /* Size (bytes) of pre-loaded module. */ + unsigned long pt_base; /* VIRTUAL address of page directory. */ + unsigned long nr_pt_frames;/* Number of bootstrap p.t. frames. */ + unsigned long mfn_list; /* VIRTUAL address of page-frame list. */ + unsigned long mod_start; /* VIRTUAL address of pre-loaded module. */ + unsigned long mod_len; /* Size (bytes) of pre-loaded module. */ s8 cmd_line[MAX_GUEST_CMDLINE]; - memory_t store_mfn; /* MACHINE page number of shared page. */ + unsigned long store_mfn; /* MACHINE page number of shared page. */ u16 store_evtchn; /* Event channel for store communication. */ } start_info_t; diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/arch/xen/i386/kernel/init_task.c --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/init_task.c Fri Aug 19 18:19:28 2005 @@ -0,0 +1,49 @@ +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/init_task.h> +#include <linux/fs.h> +#include <linux/mqueue.h> + +#include <asm/uaccess.h> +#include <asm/pgtable.h> +#include <asm/desc.h> + +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); + +#define swapper_pg_dir ((pgd_t *)NULL) +struct mm_struct init_mm = INIT_MM(init_mm); +#undef swapper_pg_dir + +EXPORT_SYMBOL(init_mm); + +/* + * Initial thread structure. + * + * We need to make sure that this is THREAD_SIZE aligned due to the + * way process stacks are handled. This is done by having a special + * "init_task" linker map entry.. + */ +union thread_union init_thread_union + __attribute__((__section__(".data.init_task"))) = + { INIT_THREAD_INFO(init_task) }; + +/* + * Initial task structure. + * + * All other task structs will be allocated on slabs in fork.c + */ +struct task_struct init_task = INIT_TASK(init_task); + +EXPORT_SYMBOL(init_task); + +/* + * per-CPU TSS segments. Threads are completely 'soft' on Linux, + * no more per-task TSS's. + */ +DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS; + diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Aug 19 18:19:28 2005 @@ -0,0 +1,308 @@ +/* Xenbus code for blkif backend + Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include <stdarg.h> +#include <linux/module.h> +#include <asm-xen/xenbus.h> +#include "common.h" + +struct backend_info +{ + struct xenbus_device *dev; + + /* our communications channel */ + blkif_t *blkif; + struct vbd *vbd; + + long int frontend_id; + long int pdev; + long int readonly; + + /* watch back end for changes */ + struct xenbus_watch backend_watch; + + /* watch front end for changes */ + struct xenbus_watch watch; + char *frontpath; +}; + +static int blkback_remove(struct xenbus_device *dev) +{ + struct backend_info *be = dev->data; + + if (be->watch.node) + unregister_xenbus_watch(&be->watch); + unregister_xenbus_watch(&be->backend_watch); + if (be->vbd) + vbd_free(be->blkif, be->vbd); + if (be->blkif) + blkif_put(be->blkif); + if (be->frontpath) + kfree(be->frontpath); + kfree(be); + return 0; +} + +/* Front end tells us frame. */ +static void frontend_changed(struct xenbus_watch *watch, const char *node) +{ + unsigned long sharedmfn; + unsigned int evtchn; + int err; + struct backend_info *be + = container_of(watch, struct backend_info, watch); + + /* If other end is gone, delete ourself. */ + if (!xenbus_exists(be->frontpath, "")) { + xenbus_rm(be->dev->nodename, ""); + device_unregister(&be->dev->dev); + return; + } + if (vbd_is_active(be->vbd)) + return; + +#ifndef CONFIG_XEN_BLKDEV_GRANT + err = xenbus_gather(be->frontpath, "shared-frame", "%lu", &sharedmfn, + "event-channel", "%u", &evtchn, NULL); + if (err) { + xenbus_dev_error(be->dev, err, + "reading %s/shared-frame and event-channel", + be->frontpath); + return; + } +#else + err = xenbus_gather(be->frontpath, "grant-id", "%lu", &sharedmfn, + "event-channel", "%u", &evtchn, NULL); + if (err) { + xenbus_dev_error(be->dev, err, + "reading %s/grant-id and event-channel", + be->frontpath); + return; + } +#endif + + /* Domains must use same shared frame for all vbds. */ + if (be->blkif->status == CONNECTED && + (evtchn != be->blkif->remote_evtchn || + sharedmfn != be->blkif->shmem_frame)) { + xenbus_dev_error(be->dev, err, + "Shared frame/evtchn %li/%u not same as" + " old %li/%u", + sharedmfn, evtchn, + be->blkif->shmem_frame, + be->blkif->remote_evtchn); + return; + } + + /* Supply the information about the device the frontend needs */ + err = xenbus_transaction_start(be->dev->nodename); + if (err) { + xenbus_dev_error(be->dev, err, "starting transaction"); + return; + } + + err = xenbus_printf(be->dev->nodename, "sectors", "%lu", + vbd_size(be->vbd)); + if (err) { + xenbus_dev_error(be->dev, err, "writing %s/sectors", + be->dev->nodename); + goto abort; + } + + /* FIXME: use a typename instead */ + err = xenbus_printf(be->dev->nodename, "info", "%u", + vbd_info(be->vbd)); + if (err) { + xenbus_dev_error(be->dev, err, "writing %s/info", + be->dev->nodename); + goto abort; + } + err = xenbus_printf(be->dev->nodename, "sector-size", "%lu", + vbd_secsize(be->vbd)); + if (err) { + xenbus_dev_error(be->dev, err, "writing %s/sector-size", + be->dev->nodename); + goto abort; + } + + /* First vbd? We need to map the shared frame, irq etc. */ + if (be->blkif->status != CONNECTED) { + err = blkif_map(be->blkif, sharedmfn, evtchn); + if (err) { + xenbus_dev_error(be->dev, err, + "mapping shared-frame %lu port %u", + sharedmfn, evtchn); + goto abort; + } + } + + /* We're ready, activate. */ + vbd_activate(be->blkif, be->vbd); + + xenbus_transaction_end(0); + xenbus_dev_ok(be->dev); + + return; + +abort: + xenbus_transaction_end(1); +} + +/* + Setup supplies physical device. + We provide event channel and device details to front end. + Frontend supplies shared frame and event channel. + */ +static void backend_changed(struct xenbus_watch *watch, const char *node) +{ + int err; + char *p; + char *frontend; + long int handle, pdev; + struct backend_info *be + = container_of(watch, struct backend_info, backend_watch); + struct xenbus_device *dev = be->dev; + + frontend = NULL; + err = xenbus_gather(dev->nodename, + "frontend-id", "%li", &be->frontend_id, + "frontend", NULL, &frontend, + NULL); + if (err == -ENOENT || err == -ERANGE || + strlen(frontend) == 0 || !xenbus_exists(frontend, "")) { + if (frontend) + kfree(frontend); + /* If we can't get a frontend path and a frontend-id, + * then our bus-id is no longer valid and we need to + * destroy the backend device. + */ + goto device_fail; + } + + if (!be->frontpath || strcmp(frontend, be->frontpath)) { + if (be->watch.node) + unregister_xenbus_watch(&be->watch); + if (be->frontpath) + kfree(be->frontpath); + be->frontpath = frontend; + be->watch.node = be->frontpath; + be->watch.callback = frontend_changed; + err = register_xenbus_watch(&be->watch); + if (err) { + be->watch.node = NULL; + goto device_fail; + } + } else + kfree(frontend); + + err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev); + if (err == -ENOENT || err == -ERANGE) + goto out; + if (err < 0) { + xenbus_dev_error(dev, err, "Reading physical-device"); + goto device_fail; + } + if (be->pdev && be->pdev != pdev) { + printk(KERN_WARNING + "changing physical-device not supported\n"); + goto device_fail; + } + be->pdev = pdev; + + /* If there's a read-only node, we're read only. */ + p = xenbus_read(dev->nodename, "read-only", NULL); + if (!IS_ERR(p)) { + be->readonly = 1; + kfree(p); + } + + if (be->blkif == NULL) { + /* Front end dir is a number, which is used as the handle. */ + p = strrchr(be->frontpath, '/') + 1; + handle = simple_strtoul(p, NULL, 0); + + be->blkif = blkif_find(be->frontend_id); + if (IS_ERR(be->blkif)) { + err = PTR_ERR(be->blkif); + be->blkif = NULL; + goto device_fail; + } + + be->vbd = vbd_create(be->blkif, handle, be->pdev, + be->readonly); + if (IS_ERR(be->vbd)) { + err = PTR_ERR(be->vbd); + be->vbd = NULL; + goto device_fail; + } + + frontend_changed(&be->watch, be->frontpath); + } + + return; + + device_fail: + device_unregister(&be->dev->dev); + out: + return; +} + +static int blkback_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) +{ + struct backend_info *be; + int err; + + be = kmalloc(sizeof(*be), GFP_KERNEL); + if (!be) + return -ENOMEM; + + memset(be, 0, sizeof(*be)); + + be->dev = dev; + be->backend_watch.node = dev->nodename; + be->backend_watch.callback = backend_changed; + err = register_xenbus_watch(&be->backend_watch); + if (err) + goto free_be; + + dev->data = be; + + backend_changed(&be->backend_watch, dev->nodename); + return err; + free_be: + kfree(be); + return err; +} + +static struct xenbus_device_id blkback_ids[] = { + { "vbd" }, + { "" } +}; + +static struct xenbus_driver blkback = { + .name = "vbd", + .owner = THIS_MODULE, + .ids = blkback_ids, + .probe = blkback_probe, + .remove = blkback_remove, +}; + +void blkif_xenbus_init(void) +{ + xenbus_register_backend(&blkback); +} diff -r 99914b54f7bf -r 81576d3d1ca8 patches/linux-2.6.12/workaround_double_br_del_if.patch --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/patches/linux-2.6.12/workaround_double_br_del_if.patch Fri Aug 19 18:19:28 2005 @@ -0,0 +1,11 @@ +--- linux-2.6.12/net/bridge/br_if.c 2005-06-17 14:48:29.000000000 -0500 ++++ linux-2.6.12-xen0-smp/net/bridge/br_if.c 2005-08-18 15:17:27.302615846 -0500 +@@ -382,7 +382,7 @@ + { + struct net_bridge_port *p = dev->br_port; + +- if (!p || p->br != br) ++ if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + + br_sysfs_removeif(p); diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/example.txt --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/example.txt Fri Aug 19 18:19:28 2005 @@ -0,0 +1,269 @@ +## +# example.txt <description to the xen access control architecture> +# +# Author: +# Reiner Sailer 08/15/2005 <sailer@xxxxxxxxxxxxxx> +# +# +# This file introduces into the tools to manage policies +# and to label domains and resources. +## + +We will show how to install and use the chwall_ste policy. +Other policies work similarly. Feedback welcome! + + + +1. Using secpol_xml2bin to translate the chwall_ste policy: +=========================================================== + +#tools/security/secpol_xml2bin chwall_ste + +Successful execution should print: + + [root@laptopxn security]# ./secpol_xml2bin chwall_ste + Validating label file policies/chwall_ste/chwall_ste-security_label_template.xml... + XML Schema policies/security_policy.xsd valid. + Validating policy file policies/chwall_ste/chwall_ste-security_policy.xml... + XML Schema policies/security_policy.xsd valid. + Creating ssid mappings ... + Creating label mappings ... + Max chwall labels: 7 + Max chwall-types: 4 + Max chwall-ssids: 5 + Max ste labels: 14 + Max ste-types: 6 + Max ste-ssids: 10 + +The tool looks in directory policies/chwall_ste for +the label and policy files. + +The default policy directory structure under tools/security looks like: + +policies +|-- security_policy.xsd +|-- chwall +| |-- chwall-security_label_template.xml +| `-- chwall-security_policy.xml +|-- chwall_ste +| |-- chwall_ste-security_label_template.xml +| `-- chwall_ste-security_policy.xml +|-- null +| |-- null-security_label_template.xml +| `-- null-security_policy.xml +`-- ste + |-- ste-security_label_template.xml + `-- ste-security_policy.xml + +policies/security_policy.xsd contains the schema against which both the +label-template and the policy files must validate during translation. + +policies/chwall_ste/chwall_ste-security_policy.xml defines the +policies and the types known to the policies. + +policies/chwall_ste/chwall_ste-security_label_template.xml contains +label definitions that group chwall and ste types together and make +them easier to use for users + +After executing the above secpol_xml2bin command, you will find 2 new +files in the policies/chwall_ste sub-directory: + +policies/chwall_ste/chwall_ste.map ... this file includes the mapping +of names from the xml files into their binary code representation. + +policies/chwall_ste/chwall_ste.bin ... this is the binary policy file, +the result of parsing the xml files and using the mapping to extract a +binary version that can be loaded into the hypervisor. + + + +2. Loading and activating the policy: +===================================== + +We assume that xen is already configured to use the chwall_ste policy; +please refer to install.txt for instructions. + +To activate the policy from the command line (assuming that the +currently established policy is the minimal boot-policy that is +hard-coded into the hypervisor: + +# ./secpol_tool loadpolicy policies/chwall_ste/chwall_ste.bin + +To activate the policy at next reboot: + +# cp policies/chwall_ste/chwall_ste.bin /boot + +Add a module line to your /boot/grub/grub.conf Xen entry. +My boot entry with chwall_ste enabled looks like this: + + title Xen (2.6.12) + root (hd0,5) + kernel /boot/xen.gz dom0_mem=1200000 console=vga + module /boot/vmlinuz-2.6.12-xen0 ro root=/dev/hda6 rhgb + module /boot/initrd-2.6.12-xen0.img + module /boot/chwall_ste.bin + +This tells the grub boot-loader to load the binary policy, which +the hypervisor will recognize. The hypervisor will then establish +this binary policy during boot instead of the minimal policy that +is hardcoded as default. + +If you have any trouble here, maks sure you have the access control +framework enabled (see: install.txt). + + + +3. Labeling domains: +==================== + +a) Labeling Domain0: + +The chwall_ste-security_label_template.xml file includes an attribute +"bootstrap", which is set to the label name that will be assigned to +Dom0 (this label will be mapped to ssidref 1/1, the default for Dom0). + +b) Labeling User Domains: + +Use the script tools/security/setlabel.sh to choose a label and to +assign labels to user domains. + +To show available labels for the chwall_ste policy: + +#tools/security/setlabel.sh -l + +lists all available labels. For the default chwall_ste it should print +the following: + + [root@laptopxn security]# ./setlabel.sh -l chwall_ste + The following labels are available: + dom_SystemManagement + dom_HomeBanking + dom_Fun + dom_BoincClient + dom_StorageDomain + dom_NetworkDomain + +You need to have compiled the policy beforehand so that a .map file +exists. Setlabel.sh uses the mapping file created throughout the +policy translation to translate a user-friendly label string into a +ssidref-number that is eventually used by the Xen hypervisor. + +We distinguish two kinds of labels: a) VM labels (for domains) and RES +Labels (for resources). We are currently working on support for +resource labeling but will focus here on VM labels. + +Setlabel.sh only prints VM labels (which we have prefixed with "dom_") +since only those are used at this time. + +If you would like to assign the dom_HomeBanking label to one of your +user domains (which you hopefully keep clean), look at an example +domain configuration homebanking.xm: + + #------HOMEBANKING--------- + kernel = "/boot/vmlinuz-2.6.12-xenU" + ramdisk="/boot/U1_ramdisk.img" + memory = 65 + name = "test34" + cpu = -1 # leave to Xen to pick + # Number of network interfaces. Default is 1. + nics=1 + dhcp="dhcp" + #------------------------- + +Now we label this domain + +[root@laptopxn security]# ./setlabel.sh homebanking.xm dom_HomeBanking chwall_ste +Mapped label 'dom_HomeBanking' to ssidref '0x00020002'. + +The domain configuration my look now like: + + [root@laptopxn security]# cat homebanking.xm + #------HOMEBANKING--------- + kernel = "/boot/vmlinuz-2.6.12-xenU" + ramdisk="/boot/U1_ramdisk.img" + memory = 65 + name = "test34" + cpu = -1 # leave to Xen to pick + # Number of network interfaces. Default is 1. + nics=1 + dhcp="dhcp" + #------------------------- + #ACM_POLICY=chwall_ste-security_policy.xml + #ACM_LABEL=dom_HomeBanking + ssidref = 0x00020002 + +You can see 3 new entries, two of which are comments. The only value +that the hypervisor cares about is the ssidref that will reference +those types assigned to this label. You can look them up in the +xml label-template file for the chwall_ste policy. + +This script will eventually move into the domain management and will +be called when the domain is instantiated. For now, the setlabel +script must be run on domains whenever the policy files change since +the mapping between label names and ssidrefs can change in this case. + + +4. Starting a labeled domain +============================ + +Now, start the domain: + #xm create -c homebanking.xm + + +If you label another domain configuration as dom_Fun and try to start +it afterwards, its start will fail. Why? + +Because the running homebanking domain has the chinese wall type +"cw_Sensitive". The new domain dom_Fun has the chinese wall label +"cw_Distrusted". This domain is not allowed to run simultaneously +because of the defined conflict set + + <conflictset name="Protection1"> + <type>cw_Sensitive</type> + <type>cw_Distrusted</type> + </conflictset> + +(in policies/chwall_ste/chwall_ste-security_policy.xml), which says +that only one of the types cw_sensitive and cw_Distrusted can run at a +time. + +If you save or shutdown the HomeBanking domain, you will be able to +start the "Fun" domain. You can look into the Xen log to see if a +domain was denied to start because of the access control framework +with the command 'xm dmesg'. + +It is important (and usually non-trivial) to define the labels in a +way that the semantics of the labels are enforced and supported by the +types and the conflict sets. + +Note: While the chinese wall policy enforcement is complete, the type +enforcement is currently enforced in the Xen hypervisor +only. Therefore, only point-to-point sharing with regard to the type +enforcement is currently controlled. We are working on enhancements to +Dom0 that enforce types also for network traffic that is routed +through Dom0 and on the enforcement of resource labeling when binding +resources to domains (e.g., enforcing types between domains and +hardware resources, such as disk partitions). + + +4. Adding your own policies +=========================== + +Writing your own policy (e.g. "mypolicy") requires the following: + +a) the policy definition (types etc.) file +b) the label template definition (labels etc.) file + +If your policy name is "mypolicy", you need to create a +subdirectory mypolicy in tools/security/policies. + +Then you create +tools/security/policies/mypolicy/mypolicy-security_policy.xml and +tools/security/policies/mypolicy/mypolicy-security_label_template.xml. + +You need to keep to the schema as defined in +tools/security/security_policy.xsd since the translation tool +secpol_xml2bin is written against this schema. + +If you keep to the security policy schema, then you can use all the +tools described above. Refer to install.txt to install it. diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/install.txt --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/install.txt Fri Aug 19 18:19:28 2005 @@ -0,0 +1,67 @@ +## +# install.txt <description to the xen access control architecture> +# +# Author: +# Reiner Sailer 08/15/2005 <sailer@xxxxxxxxxxxxxx> +# +# +# This file shows how to activate and install the access control +# framework. +## + + +INSTALLING A SECURITY POLICY IN XEN +=================================== + +By default, the access control architecture is disabled in Xen. To +enable the access control architecture in Xen follow the steps below. +This description assumes that you want to install the Chinese Wall and +Simple Type Enforcement policy. Some file names need to be replaced +below to activate the Chinese Wall OR the Type Enforcement policy +exclusively (chwall_ste --> {chwall, ste}). + +1. enable access control in Xen + # cd "xen_root" + # edit/xemacs/vi Config.mk + + change the line: + ACM_USE_SECURITY_POLICY ?= ACM_NULL_POLICY + + to: + ACM_USE_SECURITY_POLICY ?= ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY + + # make all + # ./install.sh + +2. compile the policy from xml to a binary format that can be loaded + into the hypervisor for enforcement + # cd tools/security + # make + + manual steps (alternative to make boot_install): + #./secpol_xml2bin chwall_ste + #cp policies/chwall_ste/chwall_ste.bin /boot + #edit /boot/grub/grub.conf + add the follwoing line to your xen boot entry: + "module chwall_ste.bin" + + alternatively, you can try our automatic translation and + installation of the policy: + # make boot_install + + [we try hard to do the right thing to the right boot entry but + please verify boot entry in /boot/grub/grub.conf afterwards; + your xen boot entry should have an additional module line + specifying a chwall_ste.bin file with the correct directory + (e.g. "/" or "/boot").] + + +3. reboot into the newly compiled hypervisor + + after boot + #xm dmesg should show an entry about the policy being loaded + during the boot process + + #tools/security/secpol_tool getpolicy + should print the new chwall_ste binary policy representation + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policies/chwall/chwall-security_label_template.xml --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policies/chwall/chwall-security_label_template.xml Fri Aug 19 18:19:28 2005 @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com --> +<!-- This file defines the security labels, which can --> +<!-- be attached to Domains and resources. Based on --> +<!-- these labels, the access control module decides --> +<!-- about sharing between Domains and about access --> +<!-- of Domains to real resources. --> + +<SecurityLabelTemplate + xmlns="http://www.ibm.com" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.ibm.com security_policy.xsd"> + <LabelHeader> + <Name>chwall-security_label_template</Name> + <Date>2005-08-10</Date> + <PolicyName> + <Url>chwall-security_policy.xml</Url> + <Reference>abcdef123456abcdef</Reference> + </PolicyName> + </LabelHeader> + + <SubjectLabels bootstrap="dom_SystemManagement"> + <!-- single ste typed domains --> + <!-- ACM enforces that only domains with --> + <!-- the same type can share information --> + <!-- --> + <!-- Bootstrap label is assigned to Dom0 --> + <VirtualMachineLabel> + <Name>dom_HomeBanking</Name> + <ChineseWallTypes> + <Type>cw_Sensitive</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <Name>dom_Fun</Name> + <ChineseWallTypes> + <Type>cw_Distrusted</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <!-- donating some cycles to seti@home --> + <Name>dom_BoincClient</Name> + <ChineseWallTypes> + <Type>cw_Isolated</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <!-- Domains with multiple ste types services; such domains --> + <!-- must keep the types inside their domain safely confined. --> + <VirtualMachineLabel> + <Name>dom_SystemManagement</Name> + <ChineseWallTypes> + <Type>cw_SystemManagement</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <!-- serves persistent storage to other domains --> + <Name>dom_StorageDomain</Name> + <ChineseWallTypes> + <Type>cw_SystemManagement</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <!-- serves network access to other domains --> + <Name>dom_NetworkDomain</Name> + <ChineseWallTypes> + <Type>cw_SystemManagement</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + </SubjectLabels> +</SecurityLabelTemplate> + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policies/chwall/chwall-security_policy.xml --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policies/chwall/chwall-security_policy.xml Fri Aug 19 18:19:28 2005 @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com --> +<!-- This file defines the security policies, which --> +<!-- can be enforced by the Xen Access Control Module. --> +<!-- Currently: Chinese Wall and Simple Type Enforcement--> +<SecurityPolicyDefinition xmlns="http://www.ibm.com" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.ibm.com security_policy.xsd"> +<PolicyHeader> + <Name>chwall-security_policy</Name> + <Date>2005-08-10</Date> +</PolicyHeader> +<!-- --> +<!-- example of a chinese wall type definition --> +<!-- along with its conflict sets --> +<!-- (typse in a confict set are exclusive, i.e. --> +<!-- once a Domain with one type of a set is --> +<!-- running, no other Domain with another type --> +<!-- of the same conflict set can start.) --> + <ChineseWall priority="PrimaryPolicyComponent"> + <ChineseWallTypes> + <Type>cw_SystemManagement</Type> + <Type>cw_Sensitive</Type> + <Type>cw_Isolated</Type> + <Type>cw_Distrusted</Type> + </ChineseWallTypes> + + <ConflictSets> + <Conflict name="Protection1"> + <Type>cw_Sensitive</Type> + <Type>cw_Distrusted</Type> + </Conflict> + </ConflictSets> + </ChineseWall> +</SecurityPolicyDefinition> + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policies/chwall_ste/chwall_ste-security_label_template.xml --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policies/chwall_ste/chwall_ste-security_label_template.xml Fri Aug 19 18:19:28 2005 @@ -0,0 +1,167 @@ +<?xml version="1.0"?> +<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com --> +<!-- This file defines the security labels, which can --> +<!-- be attached to Domains and resources. Based on --> +<!-- these labels, the access control module decides --> +<!-- about sharing between Domains and about access --> +<!-- of Domains to real resources. --> + +<SecurityLabelTemplate + xmlns="http://www.ibm.com" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.ibm.com security_policy.xsd"> + <LabelHeader> + <Name>chwall_ste-security_label_template</Name> + <Date>2005-08-10</Date> + <PolicyName> + <Url>chwall_ste-security_policy.xml</Url> + <Reference>abcdef123456abcdef</Reference> + </PolicyName> + </LabelHeader> + + <SubjectLabels bootstrap="dom_SystemManagement"> + <!-- single ste typed domains --> + <!-- ACM enforces that only domains with --> + <!-- the same type can share information --> + <!-- --> + <!-- Bootstrap label is assigned to Dom0 --> + <VirtualMachineLabel> + <Name>dom_HomeBanking</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_PersonalFinances</Type> + </SimpleTypeEnforcementTypes> + + <ChineseWallTypes> + <Type>cw_Sensitive</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <Name>dom_Fun</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_InternetInsecure</Type> + </SimpleTypeEnforcementTypes> + + <ChineseWallTypes> + <Type>cw_Distrusted</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <!-- donating some cycles to seti@home --> + <Name>dom_BoincClient</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_DonatedCycles</Type> + </SimpleTypeEnforcementTypes> + + <ChineseWallTypes> + <Type>cw_Isolated</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <!-- Domains with multiple ste types services; such domains --> + <!-- must keep the types inside their domain safely confined. --> + <VirtualMachineLabel> + <Name>dom_SystemManagement</Name> + <SimpleTypeEnforcementTypes> + <!-- since dom0 needs access to every domain and --> + <!-- resource right now ... --> + <Type>ste_SystemManagement</Type> + <Type>ste_PersonalFinances</Type> + <Type>ste_InternetInsecure</Type> + <Type>ste_DonatedCycles</Type> + <Type>ste_PersistentStorageA</Type> + <Type>ste_NetworkAdapter0</Type> + </SimpleTypeEnforcementTypes> + + <ChineseWallTypes> + <Type>cw_SystemManagement</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <!-- serves persistent storage to other domains --> + <Name>dom_StorageDomain</Name> + <SimpleTypeEnforcementTypes> + <!-- access right to the resource (hard drive a) --> + <Type>ste_PersistentStorageA</Type> + <!-- can serve following types --> + <Type>ste_PersonalFinances</Type> + <Type>ste_InternetInsecure</Type> + </SimpleTypeEnforcementTypes> + + <ChineseWallTypes> + <Type>cw_SystemManagement</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <!-- serves network access to other domains --> + <Name>dom_NetworkDomain</Name> + <SimpleTypeEnforcementTypes> + <!-- access right to the resource (ethernet card) --> + <Type>ste_NetworkAdapter0</Type> + <!-- can serve following types --> + <Type>ste_PersonalFinances</Type> + <Type>ste_InternetInsecure</Type> + <Type>ste_DonatedCycles</Type> + </SimpleTypeEnforcementTypes> + + <ChineseWallTypes> + <Type>cw_SystemManagement</Type> + </ChineseWallTypes> + </VirtualMachineLabel> + </SubjectLabels> + + <ObjectLabels> + <ResourceLabel> + <Name>res_ManagementResource</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_SystemManagement</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_HardDrive (hda)</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_PersistentStorageA</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_LogicalDiskPartition1 (hda1)</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_PersonalFinances</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_LogicalDiskPartition2 (hda2)</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_InternetInsecure</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_EthernetCard</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_NetworkAdapter0</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_SecurityToken</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_PersonalFinances</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_GraphicsAdapter</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_SystemManagement</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + </ObjectLabels> +</SecurityLabelTemplate> + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policies/chwall_ste/chwall_ste-security_policy.xml --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policies/chwall_ste/chwall_ste-security_policy.xml Fri Aug 19 18:19:28 2005 @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com --> +<!-- This file defines the security policies, which --> +<!-- can be enforced by the Xen Access Control Module. --> +<!-- Currently: Chinese Wall and Simple Type Enforcement--> +<SecurityPolicyDefinition xmlns="http://www.ibm.com" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.ibm.com security_policy.xsd"> +<PolicyHeader> + <Name>chwall_ste-security_policy</Name> + <Date>2005-08-10</Date> +</PolicyHeader> +<!-- --> +<!-- example of a simple type enforcement policy definition --> +<!-- --> + <SimpleTypeEnforcement> + <SimpleTypeEnforcementTypes> + <Type>ste_SystemManagement</Type> <!-- machine/security management --> + <Type>ste_PersonalFinances</Type> <!-- personal finances --> + <Type>ste_InternetInsecure</Type> <!-- games, active X, etc. --> + <Type>ste_DonatedCycles</Type> <!-- donation to BOINC/seti@home --> + <Type>ste_PersistentStorageA</Type> <!-- domain managing the harddrive A--> + <Type>ste_NetworkAdapter0</Type> <!-- type of the domain managing ethernet adapter 0--> + </SimpleTypeEnforcementTypes> + </SimpleTypeEnforcement> +<!-- --> +<!-- example of a chinese wall type definition --> +<!-- along with its conflict sets --> +<!-- (typse in a confict set are exclusive, i.e. --> +<!-- once a Domain with one type of a set is --> +<!-- running, no other Domain with another type --> +<!-- of the same conflict set can start.) --> + <ChineseWall priority="PrimaryPolicyComponent"> + <ChineseWallTypes> + <Type>cw_SystemManagement</Type> + <Type>cw_Sensitive</Type> + <Type>cw_Isolated</Type> + <Type>cw_Distrusted</Type> + </ChineseWallTypes> + + <ConflictSets> + <Conflict name="Protection1"> + <Type>cw_Sensitive</Type> + <Type>cw_Distrusted</Type> + </Conflict> + </ConflictSets> + </ChineseWall> +</SecurityPolicyDefinition> + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policies/null/null-security_label_template.xml --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policies/null/null-security_label_template.xml Fri Aug 19 18:19:28 2005 @@ -0,0 +1,24 @@ +<?xml version="1.0"?> +<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com --> +<!-- This file defines the security labels, which can --> +<!-- be attached to Domains and resources. Based on --> +<!-- these labels, the access control module decides --> +<!-- about sharing between Domains and about access --> +<!-- of Domains to real resources. --> + +<SecurityLabelTemplate + xmlns="http://www.ibm.com" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.ibm.com security_policy.xsd"> + <LabelHeader> + <Name>null-security_label_template</Name> + + <Date>2005-08-10</Date> + <PolicyName> + <Url>null-security_policy.xml</Url> + + <Reference>abcdef123456abcdef</Reference> + </PolicyName> + </LabelHeader> +</SecurityLabelTemplate> + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policies/null/null-security_policy.xml --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policies/null/null-security_policy.xml Fri Aug 19 18:19:28 2005 @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com --> +<!-- This file defines the security policies, which --> +<!-- can be enforced by the Xen Access Control Module. --> +<!-- Currently: Chinese Wall and Simple Type Enforcement--> +<SecurityPolicyDefinition xmlns="http://www.ibm.com" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.ibm.com security_policy.xsd"> +<PolicyHeader> + <Name>null-security_policy</Name> + <Date>2005-08-10</Date> +</PolicyHeader> +</SecurityPolicyDefinition> + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policies/security_policy.xsd --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policies/security_policy.xsd Fri Aug 19 18:19:28 2005 @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Author: Ray Valdez, Reiner Sailer {rvaldez,sailer}@us.ibm.com --> +<!-- This file defines the schema, which is used to define --> +<!-- the security policy and the security labels in Xe. --> + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ibm.com" xmlns="http://www.ibm.com" elementFormDefault="qualified"> + <xsd:element name="SecurityPolicyDefinition"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="PolicyHeader" minOccurs="0" maxOccurs="1"></xsd:element> + <xsd:element ref="SimpleTypeEnforcement" minOccurs="0" maxOccurs="1"></xsd:element> + <xsd:element ref="ChineseWall" minOccurs="0" maxOccurs="1"></xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="SecurityLabelTemplate"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="LabelHeader" minOccurs="1" maxOccurs="1"></xsd:element> + <xsd:element name="SubjectLabels" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="VirtualMachineLabel" minOccurs="1" maxOccurs="unbounded"></xsd:element> + </xsd:sequence> + <xsd:attribute name="bootstrap" type="xsd:string" use="required"></xsd:attribute> + </xsd:complexType> + </xsd:element> + <xsd:element name="ObjectLabels" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="ResourceLabel" minOccurs="1" maxOccurs="unbounded"></xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="PolicyHeader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="Name" minOccurs="1" maxOccurs="1" /> + <xsd:element ref="Date" minOccurs="1" maxOccurs="1" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="LabelHeader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="Name"></xsd:element> + <xsd:element ref="Date" minOccurs="1" maxOccurs="1"></xsd:element> + <xsd:element ref="PolicyName" minOccurs="1" maxOccurs="1"></xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="SimpleTypeEnforcement"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="SimpleTypeEnforcementTypes" /> + </xsd:sequence> + <xsd:attribute name="priority" type="PolicyOrder" use="optional"></xsd:attribute> + </xsd:complexType> + </xsd:element> + <xsd:element name="ChineseWall"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="ChineseWallTypes" /> + <xsd:element ref="ConflictSets" /> + </xsd:sequence> + <xsd:attribute name="priority" type="PolicyOrder" use="optional"></xsd:attribute> + </xsd:complexType> + </xsd:element> + <xsd:element name="ChineseWallTypes"> + <xsd:complexType> + <xsd:sequence> + <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="ConflictSets"> + <xsd:complexType> + <xsd:sequence> + <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Conflict" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="SimpleTypeEnforcementTypes"> + <xsd:complexType> + <xsd:sequence> + <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="Conflict"> + <xsd:complexType> + <xsd:sequence> + <xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="optional"></xsd:attribute> + </xsd:complexType> + </xsd:element> + <xsd:element name="VirtualMachineLabel"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="Name"></xsd:element> + <xsd:element ref="SimpleTypeEnforcementTypes" minOccurs="0" maxOccurs="unbounded" /> + <xsd:element ref="ChineseWallTypes" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="ResourceLabel"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="Name"></xsd:element> + <xsd:element ref="SimpleTypeEnforcementTypes" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="PolicyName"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="Url" /> + <xsd:element ref="Reference" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="Date" type="xsd:string" /> + <xsd:element name="Name" type="xsd:string" /> + <xsd:element name="Type" type="xsd:string" /> + <xsd:element name="Reference" type="xsd:string" /> + <xsd:element name="Url"></xsd:element> + + <xsd:simpleType name="PolicyOrder"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="PrimaryPolicyComponent"></xsd:enumeration> + </xsd:restriction> + </xsd:simpleType> + +</xsd:schema> diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policies/ste/ste-security_label_template.xml --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policies/ste/ste-security_label_template.xml Fri Aug 19 18:19:28 2005 @@ -0,0 +1,143 @@ +<?xml version="1.0"?> +<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com --> +<!-- This file defines the security labels, which can --> +<!-- be attached to Domains and resources. Based on --> +<!-- these labels, the access control module decides --> +<!-- about sharing between Domains and about access --> +<!-- of Domains to real resources. --> + +<SecurityLabelTemplate + xmlns="http://www.ibm.com" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.ibm.com security_policy.xsd"> + <LabelHeader> + <Name>ste-security_label_template</Name> + <Date>2005-08-10</Date> + <PolicyName> + <Url>ste-security_policy.xml</Url> + <Reference>abcdef123456abcdef</Reference> + </PolicyName> + </LabelHeader> + + <SubjectLabels bootstrap="dom_SystemManagement"> + <!-- single ste typed domains --> + <!-- ACM enforces that only domains with --> + <!-- the same type can share information --> + <!-- --> + <!-- Bootstrap label is assigned to Dom0 --> + <VirtualMachineLabel> + <Name>dom_HomeBanking</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_PersonalFinances</Type> + </SimpleTypeEnforcementTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <Name>dom_Fun</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_InternetInsecure</Type> + </SimpleTypeEnforcementTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <!-- donating some cycles to seti@home --> + <Name>dom_BoincClient</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_DonatedCycles</Type> + </SimpleTypeEnforcementTypes> + </VirtualMachineLabel> + + <!-- Domains with multiple ste types services; such domains --> + <!-- must keep the types inside their domain safely confined. --> + <VirtualMachineLabel> + <Name>dom_SystemManagement</Name> + <SimpleTypeEnforcementTypes> + <!-- since dom0 needs access to every domain and --> + <!-- resource right now ... --> + <Type>ste_SystemManagement</Type> + <Type>ste_PersonalFinances</Type> + <Type>ste_InternetInsecure</Type> + <Type>ste_DonatedCycles</Type> + <Type>ste_PersistentStorageA</Type> + <Type>ste_NetworkAdapter0</Type> + </SimpleTypeEnforcementTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <!-- serves persistent storage to other domains --> + <Name>dom_StorageDomain</Name> + <SimpleTypeEnforcementTypes> + <!-- access right to the resource (hard drive a) --> + <Type>ste_PersistentStorageA</Type> + <!-- can serve following types --> + <Type>ste_PersonalFinances</Type> + <Type>ste_InternetInsecure</Type> + </SimpleTypeEnforcementTypes> + </VirtualMachineLabel> + + <VirtualMachineLabel> + <!-- serves network access to other domains --> + <Name>dom_NetworkDomain</Name> + <SimpleTypeEnforcementTypes> + <!-- access right to the resource (ethernet card) --> + <Type>ste_NetworkAdapter0</Type> + <!-- can serve following types --> + <Type>ste_PersonalFinances</Type> + <Type>ste_InternetInsecure</Type> + <Type>ste_DonatedCycles</Type> + </SimpleTypeEnforcementTypes> + </VirtualMachineLabel> + </SubjectLabels> + + <ObjectLabels> + <ResourceLabel> + <Name>res_ManagementResource</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_SystemManagement</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_HardDrive (hda)</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_PersistentStorageA</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_LogicalDiskPartition1 (hda1)</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_PersonalFinances</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_LogicalDiskPartition2 (hda2)</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_InternetInsecure</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_EthernetCard</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_NetworkAdapter0</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_SecurityToken</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_PersonalFinances</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + + <ResourceLabel> + <Name>res_GraphicsAdapter</Name> + <SimpleTypeEnforcementTypes> + <Type>ste_SystemManagement</Type> + </SimpleTypeEnforcementTypes> + </ResourceLabel> + </ObjectLabels> +</SecurityLabelTemplate> + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policies/ste/ste-security_policy.xml --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policies/ste/ste-security_policy.xml Fri Aug 19 18:19:28 2005 @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com --> +<!-- This file defines the security policies, which --> +<!-- can be enforced by the Xen Access Control Module. --> +<!-- Currently: Chinese Wall and Simple Type Enforcement--> +<SecurityPolicyDefinition xmlns="http://www.ibm.com" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.ibm.com security_policy.xsd"> +<PolicyHeader> + <Name>ste-security_policy</Name> + <Date>2005-08-10</Date> +</PolicyHeader> +<!-- --> +<!-- example of a simple type enforcement policy definition --> +<!-- --> + <SimpleTypeEnforcement> + <SimpleTypeEnforcementTypes> + <Type>ste_SystemManagement</Type> <!-- machine/security management --> + <Type>ste_PersonalFinances</Type> <!-- personal finances --> + <Type>ste_InternetInsecure</Type> <!-- games, active X, etc. --> + <Type>ste_DonatedCycles</Type> <!-- donation to BOINC/seti@home --> + <Type>ste_PersistentStorageA</Type> <!-- domain managing the harddrive A--> + <Type>ste_NetworkAdapter0</Type> <!-- type of the domain managing ethernet adapter 0--> + </SimpleTypeEnforcementTypes> + </SimpleTypeEnforcement> +</SecurityPolicyDefinition> + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/policy.txt --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/policy.txt Fri Aug 19 18:19:28 2005 @@ -0,0 +1,405 @@ +## +# policy.txt <description to the Xen access control architecture> +# +# Author: +# Reiner Sailer 08/15/2005 <sailer@xxxxxxxxxxxxxx> +# +# +# This file gives an overview of the security policies currently +# provided and also gives some reasoning about how to assign +# labels to domains. +## + +Xen access control policies + + +General explanation of supported security policies: +===================================================== + +We have implemented the mandatory access control architecture of our +hypervisor security architecture (sHype) for the Xen hypervisor. It +controls communication (in Xen: event channels, grant tables) between +Virtual Machines (from here on called domains) and through this the +virtual block devices, networking, and shared memory are implemented +on top of these communication means. While we have implemented the +described policies and access control architecture for other +hypervisor systems, we will describe below specifically its +implementation and use in the Xen hypervisor. The policy enforcement +is called mandatory regarding user domains since the policy it is +given by the security administration and enforced independently of the +user domains by the Xen hypervisor in cooperation with the domain +management. + +The access control architecture consists of three parts: + +i) The access control policy determines the "command set" of the ACM +and the hooks with which they can be configured to constrain the +sharing of virtual resources. The current access control architecture +implemented for Xen supports two policies: Chinese Wall and Simple +Type Enforcement, which we describe in turn below. + + +ii) The actually enforced policy instantiation uses the policy +language (i) to configure the Xen access control in a way that suits +the specific application (home desktop environment, company desktop, +Web server system, etc.). We have defined an exemplary policy +instantiation for Chinese Wall (chwall policy) and Simple Type +Enforcement (ste policy) for a desktop system. We offer these policies +in combination since they are controlling orthogonal events. + + +iii) The access control module (ACM) and related hooks are part of the +core hypervisor and their controls cannot be bypassed by domains. The +ACM and hooks are the active security components. We refer to +publications that describe how access control is enforced in the Xen +hypervisor using the ACM (access decision) and the hooks (decision +enforcement) inserted into the setup of event channels and grant +tables, and into domain operations (create, destroy, save, restore, +migrate). These controls decide based on the active policy +configuration (see i. and ii.) if the operation proceeds of if the +operation is aborted (denied). + + +In general, security policy instantiations in the Xen access control +framework are defined by two files: + +a) a single "policy-name"-security_policy.xml file that defines the +types known to the ACM and policy rules based on these types + +b) a single "policy-name"-security_label_template.xml file that +defines labels based on known types + +Every security policy has its own sub-directory under +"Xen-root"/tools/security/policies in order to simplify their +management and the security policy tools. We will describe those files +for our example policy (Chinese Wall and Simple Type Enforcement) in +more detail as we go along. Eventually, we will move towards a system +installation where the policies will reside under /etc. + + +CHINESE WALL +============ + +The Chinese Wall policy enables the user to define "which workloads +(domain payloads) cannot run on a single physical system at the same +time". Why would we want to prevent workloads from running at the same +time on the same system? This supports requirements that can (but +don't have to) be rooted in the measure of trust into the isolation of +different domains that share the same hardware. Since the access +control architecture aims at high performance and non-intrusive +implementation, it currently does not address covert (timing) channels +and aims at medium assurance. Users can apply the Chinese Wall policy +to guarantee an air-gap between very sensitive payloads both regarding +covert information channels and regarding resource starvation. + +To enable the CW control, each domain is labeled with a set of Chinese +Wall types and CW Conflict Sets are defined which include those CW +types that cannot run simultaneously on the same hardware. This +interpretation of conflict sets is the only policy rule for the Chines +Wall policy. + +This is enforced by controlling the start of domains according to +their assigned CW worload types. Domains with Chinese Wall types that +appear in a common conflict set are running mutually exclusive on a +platform, i.e., once a domain with one of the cw-types of a conflict +set is running, no domain with another cw-type of the same conflict +set can start until the first domain is destroyed, paused, or migrated +away from the physical system (this assumes that such a partition can +no longer be observed). The idea is to assign cw-types according to +the type of payload that a domain runs and to use the Chinese Wall +policy to ensure that payload types can be differentiated by the +hypervisor and can be prevented from being executed on the same system +at the same time. Using the flexible CW policy maintains system +consolidation and workload-balancing while introducing guaranteed +constraints where necessary. + + +Example of a Chinese Wall Policy Instantiation +---------------------------------------------- + +The file chwall-security_policy.xml defines the Chinese Wall types as +well as the conflict sets for our example policy (you find it in the +directory "xen_root"/tools/security/policies/chwall). + +It defines four Chinese Wall types (prefixed with cw_) with the +following meaning: + +* cw_SystemsManagement is a type identifying workloads for systems +management, e.g., domain management, device management, or hypervisor +management. + +* cw_Sensitive is identifying workloads that are critical to the user +for one reason or another. + +* cw_Distrusted is identifying workloads a user does not have much +confidence in. E.g. a domain used for surfing in the internet without +protection( i.e., active-X, java, java-script, executing web content) +or for (Internet) Games should be typed this way. + +* cw_Isolated is identifying workloads that are supposedly isolated by +use of the type enforcement policy (described below). For example, if +a user wants to donate cycles to seti@home, she can setup a separate +domain for a Boinc (http://boinc.ssl.berkeley.edu/) client, disable +this domain from accessing the hard drive and from communicating to +other local domains, and type it as cw_Isolated. We will look at a +specific example later. + +The example policy uses the defined types to define one conflict set: +Protection1 = {cw_Sensitive, cw_Distrusted}. This conflict set tells +the hypervisor that once a domain typed as cw_Sensitive is running, a +domain typed as cw_Distrusted cannot run concurrently (and the other +way round). With this policy, a domain typed as cw_Isolated is allowed +to run simultaneously with domains tagged as cw_Sensitive. + +Consequently, the access control module in the Xen hypervisor +distinguishes in this example policy 4 different workload types in +this example policy. It is the user's responsibility to type the +domains in a way that reflects the workloads of these domains and, in +the case of cw_Isolated, its properties, e.g. by configuring the +sharing capabilities of the domain accordingly by using the simple +type enforcement policy. + +Users can define their own or change the existing example policy +according to their working environment and security requirements. To +do so, replace the file chwall-security_policy.xml with the new +policy. + + +SIMPLE TYPE ENFORCEMENT +======================= + +The file ste-security_policy.xml defines the simple type enforcement +types for our example policy (you find it in the directory +"xen_root"/tools/security/policies/ste). The Simple Type Enforcement +policy defines which domains can share information with which other +domains. To this end, it controls + +i) inter-domain communication channels (e.g., network traffic, events, +and shared memory). + +ii) access of domains to physical resources (e.g., hard drive, network +cards, graphics adapter, keyboard). + +In order to enable the hypervisor to distinguish different domains and +the user to express access rules, the simple type enforcement defines +a set of types (ste_types). + +The policy defines that communication between domains is allowed if +the domains share a common STE type. As with the chwall types, STE +types should enable the differentiation of workloads. The simple type +enforcement access control implementation in the hypervisor enforces +that domains can only communicate (setup event channels, grant tables) +if they share a common type, i.e., both domains have assigned at least +on type in common. A domain can access a resource, if the domain and +the resource share a common type. Hence, assigning STE types to +domains and resources allows users to define constraints on sharing +between domains and to keep sensitive data confined from distrusted +domains. + +Domain <--> Domain Sharing +'''''''''''''''''''''''''' +(implemented but its effective use requires factorization of Dom0) + +a) Domains with a single STE type (general user domains): Sharing +between such domains is enforced entirely by the hypervisor access +control. It is independent of the domains and does not require their +co-operation. + +b) Domains with multiple STE types: One example is a domain that +virtualizes a physical resource (e.g., hard drive) and serves it as +multiple virtual resources (virtual block drives) to other domains of +different types. The idea is that only a specific device domain has +assigned the type required to access the physical hard-drive. Logical +drives are then assigned the types of domains that have access to this +logical drive. Since the Xen hypervisor cannot distinguish between the +logical drives, the access control (type enforcement) is delegated to +the device domain, which has access to the types of domains requesting +to mount a logical drive as well as the types assigned to the +different available logical drives. + +Currently in Xen, Dom0 controls all hardware, needs to communicate +with all domains during their setup, and intercepts all communication +between domains. Consequently, Dom0 needs to be assigned all types +used and must be completely trusted to maintain the separation of +informatio ncoming from domains with different STE types. Thus a +refactoring of Dom0 is recommended for stronger confinement +guarantees. + +Domain --> RESOURCES Access +''''''''''''''''''''''''''' +(current work) + +We define for each resource that we want to distinguish a separate STE +type. Each STE type is assigned to the respective resource and to +those domains that are allowed to access this resource. Type +enforcement will guarantee that other domains cannot access this +resource since they don't share the resource's STE type. + +Since in the current implementation of Xen, Dom0 controls access to +all hardware (e.g., disk drives, network), Domain-->Resource access +control enforcement must be implemented in Dom0. This is possible +since Dom0 has access to both the domain configuration (including the +domain STE types) and the resource configuration (including the +resource STE types). + +For purposes of gaining higher assurance in the resulting system, it +may be desirable to reduce the size of dom0 by adding one or more +"device domains" (DDs). These DDs, e.g. providing storage or network +access, can support one or more physical devices, and manage +enforcement of MAC policy relevant for said devices. Security benefits +come from the smaller size of these DDs, as they can be more easily +audited than monolithic device driver domains. DDs can help to obtain +maximum security benefit from sHype. + + +Example of a Simple Type Enforcement Policy Instantiation +--------------------------------------------------------- + +We define the following types: + +* ste_SystemManagement identifies workloads (and domains that runs +them) that must share information to accomplish the management of the +system + +* ste_PersonalFinances identifies workloads that are related to +sensitive programs such as HomeBanking applications or safely +configured web browsers for InternetBanking + +* ste_InternetInsecure identifies workloads that are very +function-rich and unrestricted to offer for example an environment +where internet games can run efficiently + +* ste_DonatedCycles identifies workloads that run on behalf of others, +e.g. a Boinc client + +* ste_PersistentStorage identifies workloads that have direct access +to persistent storage (e.g., hard drive) + +* ste_NetworkAccess identifies workload that have direct access to +network cards and related networks + + + +SECURITY LABEL TEMPLATES +======================== + +We introduce security label templates because it is difficult for +users to ensure tagging of domains consistently and since there are +--as we have seen in the case of isolation-- useful dependencies +between the policies. Security Label Templates define type sets that +can be addressed by more user-friendly label names, +e.g. dom_Homebanking describes a typical typeset tagged to domains +used for sensitive Homebanking work-loads. Labels are defined in the +file + +Using Security Label Templates has multiple advantages: +a) easy reference of typical sets of type assignments +b) consistent interpretation of type combinations +c) meaningful application-level label names + +The definition of label templates depends on the combination of +policies that are used. We will describe some of the labels defined +for the Chinese Wall and Simple Type Enforcement combination. + +In the BoincClient example, the label_template file specifies that +this Label is assigned the Chinese Wall type cw_Isolated. We do this +assuming that this BoincClient is isolated against the rest of the +system infrastructure (no persistent memory, no sharing with local +domains). Since cw_Isolated is not included in any conflict set, it +can run at any time concurrently with any other domain. The +ste_DonatedCycles type assigned to the BoincClient reflect the +isolation assumption: it is only assigned to the dom_NetworkDomain +giving the BoincClient domain access to the network to communicate +with its BoincServer. + +The strategy for combining types into Labels is the following: First +we define a label for each type of general user domain +(workload-oriented). Then we define a new label for each physical +resource that shall be shared using a DD domain (e.g., disk) and for +each logical resource offered through this physical resource (logical +disk partition). We define then device domain labels (here: +dom_SystemManagement, dom_StorageDomain, dom_NetworkDomain) which +include the types of the physical resources (e.g. hda) their domains +need to connect to. Such physical resources can only be accessed +directly by device domains types with the respective device's STE +type. Additionally we assign to such a device domain Label the STE +types of those user domains that are allowed to access one of the +logical resources (e.g., hda1, hda2) built on top of this physical +resource through the device domain. + + +Label Construction Example: +--------------------------- + +We define here a storage domain label for a domain that owns a real +disk drive and creates the logical disk partitions hda1 and hda2 which +it serves to domains labeled dom_HomeBanking and dom_Fun +respectively. The labels we refer to are defined in the label template +file policies/chwall_ste/chwall_ste-security-label-template.xml. + +step1: To distinguish different shared disk drives, we create a +separate Label and STE type for each of them. Here: we create a type +ste_PersistentStorageA for disk drive hda. If you have another disk +drive, you may define another persistent storage type +ste_PersistentStorageB in the chwall_ste-security_policy.xml. + +step2: To distinguish different domains, we create multiple domain +labels including different types. Here: label dom_HomeBanking includes +STE type ste_PersonalFinances, label dom_Fun includes STE type +ste_InternetInsecure. + +step3: The storage domain in charge of the hard drive A needs access +to this hard drive. Therefore the storage domain label +dom_StorageDomain must include the type assigned to the hard drive +(ste_PersistentStorageA). + +step4: In order to serve dom hda1 to domains labeled dom_HomeBanking +and hda2 to domains labeled dom_Fun, the storage domain label must +include the types of those domains as well (ste_PersonalFinance, +ste_InternetInsecure). + +step5: In order to keep the data for different types safely apart, the +different logical disk partitions must be assigned unique labels and +types, which are used inside the storage domain to extend the ACM +access enforcement to logical resources served from inside the storage +domain. We define labels "res_LogicalDiskPartition1 (hda1)" and assign +it to hda1 and "res_LogicalDiskPartition2 (hda2)" and assign it to +hda2. These labels must include the STE types of those domains that +are allowed to use them (e.g., ste_PersonalFinances for hda1). + +The overall mandatory access control is then enforced in 3 different +Xen components and these components use a single consistent policy to +co-operatively enforce the policy. In the storage domain example, we +have three components that co-operate: + +1. The ACM module inside the hypervisor enforces: communication between +user domains and the storage domain (only domains including types +ste_PersonalFinances or ste_InternetInsecure can communicate with the +storage domain and request access to logical resource). This confines +the sharing to the types assigned to the storage domain. + +2. The domain management will enforce (work in progress): assignment of +real resources (hda) to domains (storage domain) that share a +type with the resource. + +3. If the storage domain serves multiple STE types (as in our example), +it enforces (work in progress): that domains can access (mount) +logical resources only if they share an STE type with the respective +resource. In our example, domains with the STE type +ste_PersonalFinances can request access (mount) to logical resource +hda1 from the storage domain. + +If you look at the virtual machine label dom_StorageDomain, you will +see the minimal set of types assigned to our domain manageing disk +drive hda for serving logical disk partitions exclusively to +dom_HomeBanking and dom_Fun. + +Similary, network domains can confine access to the network or +network communication between user domains. + +As a result, device domains (e.g., storage domain, network domain) +must be simple and small to ensure their correct co-operation in the +type enforcement model. If such trust is not possible, then hardware +should be assigned exclusively to a single type (or to a single +partition) in which case the hypervisor ACM enforcement enforces the +types independently. diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/readme.txt --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/readme.txt Fri Aug 19 18:19:28 2005 @@ -0,0 +1,29 @@ + +## +# readme.txt <description to the xen access control architecture> +# +# Author: +# Reiner Sailer 08/15/2005 <sailer@xxxxxxxxxxxxxx> +# +# +# This file is a toc for information regarding +# the access control policy and tools in Xen. +## + +1. policy.txt: + + describes the general reasoning and examples for access + control policies in Xen + + +2. install.txt + + describes the activation of the access control framework + in Xen + +3. example.txt + + describes the available tools for managing security policies + in Xen and the tools to label domains + + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/secpol_compat.h --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/secpol_compat.h Fri Aug 19 18:19:28 2005 @@ -0,0 +1,14 @@ +/* secpol_compat.h + * 'translates' data types necessary to + * include <xen/acm.h> + */ +#include <stdint.h> + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/secpol_xml2bin.c --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/secpol_xml2bin.c Fri Aug 19 18:19:28 2005 @@ -0,0 +1,1396 @@ +/**************************************************************** + * secpol_xml2bin.c + * + * Copyright (C) 2005 IBM Corporation + * + * Author: Reiner Sailer <sailer@xxxxxxxxxx> + * + * Maintained: + * Reiner Sailer <sailer@xxxxxxxxxx> + * Ray Valdez <rvaldez@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * sHype policy translation tool. This tool takes an XML + * policy specification as input and produces a binary + * policy file that can be loaded into Xen through the + * ACM operations (secpol_tool loadpolicy) interface or at + * boot time (grub module parameter) + * + * indent -i4 -kr -nut + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <libgen.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/queue.h> +#include <netinet/in.h> +#include <libxml/xmlschemas.h> +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xmlreader.h> +#include "secpol_compat.h" +#include <xen/acm.h> + +#include "secpol_xml2bin.h" + +#define DEBUG 0 + +/* primary / secondary policy component setting */ +enum policycomponent { CHWALL, STE, NULLPOLICY } + primary = NULLPOLICY, secondary = NULLPOLICY; + +/* general list element for ste and chwall type queues */ +struct type_entry { + TAILQ_ENTRY(type_entry) entries; + char *name; /* name of type from xml file */ + type_t mapping; /* type mapping into 16bit */ +}; + +TAILQ_HEAD(tailhead, type_entry) ste_head, chwall_head; + +/* general list element for all label queues */ +enum label_type { VM, RES, ANY }; +struct ssid_entry { + TAILQ_ENTRY(ssid_entry) entries; + char *name; /* label name */ + enum label_type type; /* type: VM / RESOURCE LABEL */ + u_int32_t num; /* ssid or referenced ssid */ + int is_ref; /* if this entry references earlier ssid number */ + unsigned char *row; /* index of types (if not a reference) */ +}; + +TAILQ_HEAD(tailhead_ssid, ssid_entry) ste_ssid_head, chwall_ssid_head, + conflictsets_head; +struct ssid_entry *current_chwall_ssid_p = NULL; +struct ssid_entry *current_ste_ssid_p = NULL; +struct ssid_entry *current_conflictset_p = NULL; + +/* which label to assign to dom0 during boot */ +char *bootstrap_label; + +u_int32_t max_ste_ssids = 0; +u_int32_t max_chwall_ssids = 0; +u_int32_t max_chwall_labels = 0; +u_int32_t max_ste_labels = 0; +u_int32_t max_conflictsets = 0; + +char *current_ssid_name; /* store name until structure is allocated */ +char *current_conflictset_name; /* store name until structure is allocated */ + +/* dynamic list of type mappings for STE */ +u_int32_t max_ste_types = 0; + +/* dynamic list of type mappings for CHWALL */ +u_int32_t max_chwall_types = 0; + +/* dynamic list of conflict sets */ +int max_conflict_set = 0; + +/* which policies are defined */ +int have_ste = 0; +int have_chwall = 0; + +/* input/output file names */ +char *policy_filename = NULL, + *label_filename = NULL, + *binary_filename = NULL, *mapping_filename = NULL; + +void usage(char *prg) +{ + printf("usage:\n%s policyname[-policy.xml/-security_label_template.xml]\n", + prg); + exit(EXIT_FAILURE); +} + + +/***************** policy-related parsing *********************/ + +char *type_by_mapping(struct tailhead *head, u_int32_t mapping) +{ + struct type_entry *np; + for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) + if (np->mapping == mapping) + return np->name; + return NULL; +} + + +struct type_entry *lookup(struct tailhead *head, char *name) +{ + struct type_entry *np; + for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) + if (!(strcmp(np->name, name))) + return np; + return NULL; +} + +/* enforces single-entry lists */ +int add_entry(struct tailhead *head, char *name, type_t mapping) +{ + struct type_entry *e; + if (lookup(head, name)) + { + printf("Error: Type >%s< defined more than once.\n", name); + return -EFAULT; /* already in the list */ + } + if (!(e = malloc(sizeof(struct type_entry)))) + return -ENOMEM; + + e->name = name; + e->mapping = mapping; + TAILQ_INSERT_TAIL(head, e, entries); + return 0; +} + +int totoken(char *tok) +{ + int i; + for (i = 0; token[i] != NULL; i++) + if (!strcmp(token[i], tok)) + return i; + return -EFAULT; +} + +/* conflictsets use the same data structure as ssids; since + * they are similar in structure (set of types) + */ +int init_next_conflictset(void) +{ + struct ssid_entry *conflictset = malloc(sizeof(struct ssid_entry)); + + if (!conflictset) + return -ENOMEM; + + conflictset->name = current_conflictset_name; + conflictset->num = max_conflictsets++; + conflictset->is_ref = 0; /* n/a for conflictsets */ + /** + * row: allocate one byte per type; + * [i] != 0 --> mapped type >i< is part of the conflictset + */ + conflictset->row = malloc(max_chwall_types); + if (!conflictset->row) + return -ENOMEM; + + memset(conflictset->row, 0, max_chwall_types); + TAILQ_INSERT_TAIL(&conflictsets_head, conflictset, entries); + current_conflictset_p = conflictset; + return 0; +} + +int register_type(xmlNode * cur_node, xmlDocPtr doc, unsigned long state) +{ + xmlChar *text; + struct type_entry *e; + + + text = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + if (!text) + { + printf("Error reading type name!\n"); + return -EFAULT; + } + + switch (state) { + case XML2BIN_stetype_S: + if (add_entry(&ste_head, (char *) text, max_ste_types)) + { + xmlFree(text); + return -EFAULT; + } + max_ste_types++; + break; + + case XML2BIN_chwalltype_S: + if (add_entry(&chwall_head, (char *) text, max_chwall_types)) + { + xmlFree(text); + return -EFAULT; + } + max_chwall_types++; + break; + + case XML2BIN_conflictsettype_S: + /* a) search the type in the chwall_type list */ + e = lookup(&chwall_head, (char *) text); + if (e == NULL) + { + printf("CS type >%s< not a CHWALL type.\n", text); + xmlFree(text); + return -EFAULT; + } + /* b) add type entry to the current cs set */ + if (current_conflictset_p->row[e->mapping]) + { + printf("ERROR: Double entry of type >%s< in conflict set %d.\n", + text, current_conflictset_p->num); + xmlFree(text); + return -EFAULT; + } + current_conflictset_p->row[e->mapping] = 1; + break; + + default: + printf("Incorrect type environment (state = %lx, text = %s).\n", + state, text); + xmlFree(text); + return -EFAULT; + } + return 0; +} + +void set_component_type(xmlNode * cur_node, enum policycomponent pc) +{ + xmlChar *order; + + if ((order = xmlGetProp(cur_node, (xmlChar *) PRIMARY_COMPONENT_ATTR_NAME))) { + if (strcmp((char *) order, PRIMARY_COMPONENT)) + { + printf("ERROR: Illegal attribut value >order=%s<.\n", + (char *) order); + xmlFree(order); + exit(EXIT_FAILURE); + } + if (primary != NULLPOLICY) + { + printf("ERROR: Primary Policy Component set twice!\n"); + exit(EXIT_FAILURE); + } + primary = pc; + xmlFree(order); + } +} + +void walk_policy(xmlNode * start, xmlDocPtr doc, unsigned long state) +{ + xmlNode *cur_node = NULL; + int code; + + for (cur_node = start; cur_node; cur_node = cur_node->next) + { + if ((code = totoken((char *) cur_node->name)) < 0) + { + printf("Unknown token: >%s<. Aborting.\n", cur_node->name); + exit(EXIT_FAILURE); + } + switch (code) { /* adjust state to new state */ + case XML2BIN_SECPOL: + case XML2BIN_STETYPES: + case XML2BIN_CHWALLTYPES: + case XML2BIN_CONFLICTSETS: + walk_policy(cur_node->children, doc, state | (1 << code)); + break; + + case XML2BIN_STE: + if (WRITTEN_AGAINST_ACM_STE_VERSION != ACM_STE_VERSION) + { + printf("ERROR: This program was written against another STE version.\n"); + exit(EXIT_FAILURE); + } + have_ste = 1; + set_component_type(cur_node, STE); + walk_policy(cur_node->children, doc, state | (1 << code)); + break; + + case XML2BIN_CHWALL: + if (WRITTEN_AGAINST_ACM_CHWALL_VERSION != ACM_CHWALL_VERSION) + { + printf("ERROR: This program was written against another CHWALL version.\n"); + exit(EXIT_FAILURE); + } + have_chwall = 1; + set_component_type(cur_node, CHWALL); + walk_policy(cur_node->children, doc, state | (1 << code)); + break; + + case XML2BIN_CSTYPE: + current_conflictset_name = + (char *) xmlGetProp(cur_node, (xmlChar *) "name"); + if (!current_conflictset_name) + current_conflictset_name = ""; + + if (init_next_conflictset()) + { + printf + ("ERROR: creating new conflictset structure failed.\n"); + exit(EXIT_FAILURE); + } + walk_policy(cur_node->children, doc, state | (1 << code)); + break; + + case XML2BIN_TYPE: + if (register_type(cur_node, doc, state)) + exit(EXIT_FAILURE); + /* type leaf */ + break; + + case XML2BIN_TEXT: + case XML2BIN_COMMENT: + case XML2BIN_POLICYHEADER: + /* leaf - nothing to do */ + break; + + default: + printf("Unkonwn token Error (%d)\n", code); + exit(EXIT_FAILURE); + } + + } + return; +} + +int create_type_mapping(xmlDocPtr doc) +{ + xmlNode *root_element = xmlDocGetRootElement(doc); + struct type_entry *te; + struct ssid_entry *se; + int i; + + printf("Creating ssid mappings ...\n"); + + /* initialize the ste and chwall type lists */ + TAILQ_INIT(&ste_head); + TAILQ_INIT(&chwall_head); + TAILQ_INIT(&conflictsets_head); + + walk_policy(root_element, doc, XML2BIN_NULL); + + /* determine primary/secondary policy component orders */ + if ((primary == NULLPOLICY) && have_chwall) + primary = CHWALL; /* default if not set */ + else if ((primary == NULLPOLICY) && have_ste) + primary = STE; + + switch (primary) { + + case CHWALL: + if (have_ste) + secondary = STE; + /* else default = NULLPOLICY */ + break; + + case STE: + if (have_chwall) + secondary = CHWALL; + /* else default = NULLPOLICY */ + break; + + default: + /* NULL/NULL policy */ + break; + } + + if (!DEBUG) + return 0; + + /* print queues */ + if (have_ste) + { + printf("STE-Type queue (%s):\n", + (primary == STE) ? "PRIMARY" : "SECONDARY"); + for (te = ste_head.tqh_first; te != NULL; + te = te->entries.tqe_next) + printf("name=%22s, map=%x\n", te->name, te->mapping); + } + if (have_chwall) + { + printf("CHWALL-Type queue (%s):\n", + (primary == CHWALL) ? "PRIMARY" : "SECONDARY"); + for (te = chwall_head.tqh_first; te != NULL; + te = te->entries.tqe_next) + printf("name=%s, map=%x\n", te->name, te->mapping); + + printf("Conflictset queue (max=%d):\n", max_conflictsets); + for (se = conflictsets_head.tqh_first; se != NULL; + se = se->entries.tqe_next) + { + printf("conflictset name >%s<\n", + se->name ? se->name : "NONAME"); + for (i = 0; i < max_chwall_types; i++) + if (se->row[i]) + printf("#%x ", i); + printf("\n"); + } + } + return 0; +} + + +/***************** template-related parsing *********************/ + +/* add default ssid at head of ssid queues */ +int init_ssid_queues(void) +{ + struct ssid_entry *default_ssid_chwall, *default_ssid_ste; + + default_ssid_chwall = malloc(sizeof(struct ssid_entry)); + default_ssid_ste = malloc(sizeof(struct ssid_entry)); + + if ((!default_ssid_chwall) || (!default_ssid_ste)) + return -ENOMEM; + + /* default chwall ssid */ + default_ssid_chwall->name = "DEFAULT"; + default_ssid_chwall->num = max_chwall_ssids++; + default_ssid_chwall->is_ref = 0; + default_ssid_chwall->type = ANY; + + default_ssid_chwall->row = malloc(max_chwall_types); + + if (!default_ssid_chwall->row) + return -ENOMEM; + + memset(default_ssid_chwall->row, 0, max_chwall_types); + + TAILQ_INSERT_TAIL(&chwall_ssid_head, default_ssid_chwall, entries); + current_chwall_ssid_p = default_ssid_chwall; + max_chwall_labels++; + + /* default ste ssid */ + default_ssid_ste->name = "DEFAULT"; + default_ssid_ste->num = max_ste_ssids++; + default_ssid_ste->is_ref = 0; + default_ssid_ste->type = ANY; + + default_ssid_ste->row = malloc(max_ste_types); + + if (!default_ssid_ste->row) + return -ENOMEM; + + memset(default_ssid_ste->row, 0, max_ste_types); + + TAILQ_INSERT_TAIL(&ste_ssid_head, default_ssid_ste, entries); + current_ste_ssid_p = default_ssid_ste; + max_ste_labels++; + return 0; +} + +int init_next_chwall_ssid(unsigned long state) +{ + struct ssid_entry *ssid = malloc(sizeof(struct ssid_entry)); + + if (!ssid) + return -ENOMEM; + + ssid->name = current_ssid_name; + ssid->num = max_chwall_ssids++; + ssid->is_ref = 0; + + if (state & (1 << XML2BIN_VM)) + ssid->type = VM; + else + ssid->type = RES; + /** + * row: allocate one byte per type; + * [i] != 0 --> mapped type >i< is part of the ssid + */ + ssid->row = malloc(max_chwall_types); + if (!ssid->row) + return -ENOMEM; + + memset(ssid->row, 0, max_chwall_types); + TAILQ_INSERT_TAIL(&chwall_ssid_head, ssid, entries); + current_chwall_ssid_p = ssid; + max_chwall_labels++; + return 0; +} + +int init_next_ste_ssid(unsigned long state) +{ + struct ssid_entry *ssid = malloc(sizeof(struct ssid_entry)); + + if (!ssid) + return -ENOMEM; + + ssid->name = current_ssid_name; + ssid->num = max_ste_ssids++; + ssid->is_ref = 0; + + if (state & (1 << XML2BIN_VM)) + ssid->type = VM; + else + ssid->type = RES; + + /** + * row: allocate one byte per type; + * [i] != 0 --> mapped type >i< is part of the ssid + */ + ssid->row = malloc(max_ste_types); + if (!ssid->row) + return -ENOMEM; + + memset(ssid->row, 0, max_ste_types); + TAILQ_INSERT_TAIL(&ste_ssid_head, ssid, entries); + current_ste_ssid_p = ssid; + max_ste_labels++; + + return 0; +} + + +/* adds a type to the current ssid */ +int add_type(xmlNode * cur_node, xmlDocPtr doc, unsigned long state) +{ + xmlChar *text; + struct type_entry *e; + + text = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + if (!text) + { + printf("Error reading type name!\n"); + return -EFAULT; + } + /* same for all: 1. lookup type mapping, 2. mark type in ssid */ + switch (state) { + case XML2BIN_VM_STE_S: + case XML2BIN_RES_STE_S: + /* lookup the type mapping and include the type mapping into the array */ + if (!(e = lookup(&ste_head, (char *) text))) + { + printf("ERROR: unknown VM STE type >%s<.\n", text); + exit(EXIT_FAILURE); + } + if (current_ste_ssid_p->row[e->mapping]) + printf("Warning: double entry of VM STE type >%s<.\n", text); + + current_ste_ssid_p->row[e->mapping] = 1; + break; + + case XML2BIN_VM_CHWALL_S: + /* lookup the type mapping and include the type mapping into the array */ + if (!(e = lookup(&chwall_head, (char *) text))) + { + printf("ERROR: unknown VM CHWALL type >%s<.\n", text); + exit(EXIT_FAILURE); + } + if (current_chwall_ssid_p->row[e->mapping]) + printf("Warning: double entry of VM CHWALL type >%s<.\n", + text); + + current_chwall_ssid_p->row[e->mapping] = 1; + break; + + default: + printf("Incorrect type environment (state = %lx, text = %s).\n", + state, text); + xmlFree(text); + return -EFAULT; + } + return 0; +} + +void set_bootstrap_label(xmlNode * cur_node) +{ + xmlChar *order; + + if ((order = xmlGetProp(cur_node, (xmlChar *) BOOTSTRAP_LABEL_ATTR_NAME))) + bootstrap_label = (char *)order; + else { + printf("ERROR: No bootstrap label defined!\n"); + exit(EXIT_FAILURE); + } +} + +void walk_labels(xmlNode * start, xmlDocPtr doc, unsigned long state) +{ + xmlNode *cur_node = NULL; + int code; + + for (cur_node = start; cur_node; cur_node = cur_node->next) + { + if ((code = totoken((char *) cur_node->name)) < 0) + { + printf("Unkonwn token: >%s<. Aborting.\n", cur_node->name); + exit(EXIT_FAILURE); + } + switch (code) { /* adjust state to new state */ + + case XML2BIN_SUBJECTS: + set_bootstrap_label(cur_node); + /* fall through */ + case XML2BIN_VM: + case XML2BIN_RES: + case XML2BIN_SECTEMPLATE: + case XML2BIN_OBJECTS: + walk_labels(cur_node->children, doc, state | (1 << code)); + break; + + case XML2BIN_STETYPES: + /* create new ssid entry to use and point current to it */ + if (init_next_ste_ssid(state)) + { + printf("ERROR: creating new ste ssid structure failed.\n"); + exit(EXIT_FAILURE); + } + walk_labels(cur_node->children, doc, state | (1 << code)); + + break; + + case XML2BIN_CHWALLTYPES: + /* create new ssid entry to use and point current to it */ + if (init_next_chwall_ssid(state)) + { + printf("ERROR: creating new chwall ssid structure failed.\n"); + exit(EXIT_FAILURE); + } + walk_labels(cur_node->children, doc, state | (1 << code)); + + break; + + case XML2BIN_TYPE: + /* add type to current ssid */ + if (add_type(cur_node, doc, state)) + exit(EXIT_FAILURE); + break; + + case XML2BIN_NAME: + if ((state != XML2BIN_VM_S) && (state != XML2BIN_RES_S)) + { + printf("ERROR: >name< out of VM/RES context.\n"); + exit(EXIT_FAILURE); + } + current_ssid_name = (char *) + xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + + if (!current_ssid_name) + { + printf("ERROR: empty >name<!\n"); + exit(EXIT_FAILURE); + } + break; + + case XML2BIN_TEXT: + case XML2BIN_COMMENT: + case XML2BIN_LABELHEADER: + break; + + default: + printf("Unkonwn token Error (%d)\n", code); + exit(EXIT_FAILURE); + } + + } + return; +} + +/* this function walks through a ssid queue + * and transforms double entries into references + * of the first definition (we need to keep the + * entry to map labels but we don't want double + * ssids in the binary policy + */ +void +remove_doubles(struct tailhead_ssid *head, + u_int32_t max_types, u_int32_t * max_ssids) +{ + struct ssid_entry *np, *ni; + + /* walk once through the list */ + for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) + { + /* now search from the start until np for the same entry */ + for (ni = head->tqh_first; ni != np; ni = ni->entries.tqe_next) + { + if (ni->is_ref) + continue; + if (memcmp(np->row, ni->row, max_types)) + continue; + /* found one, set np reference to ni */ + np->is_ref = 1; + np->num = ni->num; + (*max_ssids)--; + } + } + + /* now minimize the ssid numbers used (doubles introduce holes) */ + (*max_ssids) = 0; /* reset */ + + for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) + { + if (np->is_ref) + continue; + + if (np->num != (*max_ssids)) { + /* first reset all later references to the new max_ssid */ + for (ni = np->entries.tqe_next; ni != NULL; ni = ni->entries.tqe_next) + { + if (ni->num == np->num) + ni->num = (*max_ssids); + } + /* now reset num */ + np->num = (*max_ssids)++; + } + else + (*max_ssids)++; + } +} + +/* + * will go away as soon as we have non-static bootstrap ssidref for dom0 + */ +void fixup_bootstrap_label(struct tailhead_ssid *head, + u_int32_t max_types, u_int32_t * max_ssids) +{ + struct ssid_entry *np; + int i; + + /* should not happen if xml / xsd checks work */ + if (!bootstrap_label) + { + printf("ERROR: No bootstrap label defined.\n"); + exit(EXIT_FAILURE); + } + + /* search bootstrap_label */ + for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) + { + if (!strcmp(np->name, bootstrap_label)) + { + break; + } + } + + if (!np) { + /* bootstrap label not found */ + printf("ERROR: Bootstrap label >%s< not found.\n", bootstrap_label); + exit(EXIT_FAILURE); + } + + /* move this entry ahead in the list right after the default entry so it + * receives ssidref 1/1 */ + TAILQ_REMOVE(head, np, entries); + TAILQ_INSERT_AFTER(head, head->tqh_first, np, entries); + + /* renumber the ssids (we could also just switch places with 1st element) */ + for (np = head->tqh_first, i=0; np != NULL; np = np->entries.tqe_next, i++) + np->num = i; + +} + +int create_ssid_mapping(xmlDocPtr doc) +{ + xmlNode *root_element = xmlDocGetRootElement(doc); + struct ssid_entry *np; + int i; + + printf("Creating label mappings ...\n"); + /* initialize the ste and chwall type lists */ + TAILQ_INIT(&chwall_ssid_head); + TAILQ_INIT(&ste_ssid_head); + + /* init with default ssids */ + if (init_ssid_queues()) + { + printf("ERROR adding default ssids.\n"); + exit(EXIT_FAILURE); + } + + /* now walk the template DOM tree and fill in ssids */ + walk_labels(root_element, doc, XML2BIN_NULL); + + /* + * now sort bootstrap label to the head of the list + * (for now), dom0 assumes its label in the first + * defined ssidref (1/1). 0/0 is the default non-Label + */ + if (have_chwall) + fixup_bootstrap_label(&chwall_ssid_head, max_chwall_types, + &max_chwall_ssids); + if (have_ste) + fixup_bootstrap_label(&ste_ssid_head, max_ste_types, + &max_ste_ssids); + + /* remove any double entries (insert reference instead) */ + if (have_chwall) + remove_doubles(&chwall_ssid_head, max_chwall_types, + &max_chwall_ssids); + if (have_ste) + remove_doubles(&ste_ssid_head, max_ste_types, + &max_ste_ssids); + + if (!DEBUG) + return 0; + + /* print queues */ + if (have_chwall) + { + printf("CHWALL SSID queue (max ssidrefs=%d):\n", max_chwall_ssids); + np = NULL; + for (np = chwall_ssid_head.tqh_first; np != NULL; + np = np->entries.tqe_next) + { + printf("SSID #%02u (Label=%s)\n", np->num, np->name); + if (np->is_ref) + printf("REFERENCE"); + else + for (i = 0; i < max_chwall_types; i++) + if (np->row[i]) + printf("#%02d ", i); + printf("\n\n"); + } + } + if (have_ste) + { + printf("STE SSID queue (max ssidrefs=%d):\n", max_ste_ssids); + np = NULL; + for (np = ste_ssid_head.tqh_first; np != NULL; + np = np->entries.tqe_next) + { + printf("SSID #%02u (Label=%s)\n", np->num, np->name); + if (np->is_ref) + printf("REFERENCE"); + else + for (i = 0; i < max_ste_types; i++) + if (np->row[i]) + printf("#%02d ", i); + printf("\n\n"); + } + } + return 0; +} + +/***************** writing the binary policy *********************/ + +/* + * the mapping file is ascii-based since it will likely be used from + * within scripts (using awk, grep, etc.); + * + * We print from high-level to low-level information so that with one + * pass, any symbol can be resolved (e.g. Label -> types) + */ +int write_mapping(char *filename) +{ + + struct ssid_entry *e; + struct type_entry *t; + int i; + FILE *file; + + if ((file = fopen(filename, "w")) == NULL) + return -EIO; + + fprintf(file, "MAGIC %08x\n", ACM_MAGIC); + fprintf(file, "POLICY %s\n", + basename(policy_filename)); + fprintf(file, "BINARY %s\n", + basename(binary_filename)); + if (have_chwall) + { + fprintf(file, "MAX-CHWALL-TYPES %08x\n", max_chwall_types); + fprintf(file, "MAX-CHWALL-SSIDS %08x\n", max_chwall_ssids); + fprintf(file, "MAX-CHWALL-LABELS %08x\n", max_chwall_labels); + } + if (have_ste) + { + fprintf(file, "MAX-STE-TYPES %08x\n", max_ste_types); + fprintf(file, "MAX-STE-SSIDS %08x\n", max_ste_ssids); + fprintf(file, "MAX-STE-LABELS %08x\n", max_ste_labels); + } + fprintf(file, "\n"); + + /* primary / secondary order for combined ssid synthesis/analysis + * if no primary is named, then chwall is primary */ + switch (primary) { + case CHWALL: + fprintf(file, "PRIMARY CHWALL\n"); + break; + + case STE: + fprintf(file, "PRIMARY STE\n"); + break; + + default: + fprintf(file, "PRIMARY NULL\n"); + break; + } + + switch (secondary) { + case CHWALL: + fprintf(file, "SECONDARY CHWALL\n"); + break; + + case STE: + fprintf(file, "SECONDARY STE\n"); + break; + + default: + fprintf(file, "SECONDARY NULL\n"); + break; + } + fprintf(file, "\n"); + + /* first labels to ssid mappings */ + if (have_chwall) + { + for (e = chwall_ssid_head.tqh_first; e != NULL; + e = e->entries.tqe_next) + { + fprintf(file, "LABEL->SSID %s CHWALL %-25s %8x\n", + (e->type == + VM) ? "VM " : ((e->type == RES) ? "RES" : "ANY"), + e->name, e->num); + } + fprintf(file, "\n"); + } + if (have_ste) + { + for (e = ste_ssid_head.tqh_first; e != NULL; + e = e->entries.tqe_next) + { + fprintf(file, "LABEL->SSID %s STE %-25s %8x\n", + (e->type == + VM) ? "VM " : ((e->type == RES) ? "RES" : "ANY"), + e->name, e->num); + } + fprintf(file, "\n"); + } + + /* second ssid to type mappings */ + if (have_chwall) + { + for (e = chwall_ssid_head.tqh_first; e != NULL; + e = e->entries.tqe_next) + { + if (e->is_ref) + continue; + + fprintf(file, "SSID->TYPE CHWALL %08x", e->num); + + for (i = 0; i < max_chwall_types; i++) + if (e->row[i]) + fprintf(file, " %s", type_by_mapping(&chwall_head, i)); + + fprintf(file, "\n"); + } + fprintf(file, "\n"); + } + if (have_ste) { + for (e = ste_ssid_head.tqh_first; e != NULL; + e = e->entries.tqe_next) + { + if (e->is_ref) + continue; + + fprintf(file, "SSID->TYPE STE %08x", e->num); + + for (i = 0; i < max_ste_types; i++) + if (e->row[i]) + fprintf(file, " %s", type_by_mapping(&ste_head, i)); + + fprintf(file, "\n"); + } + fprintf(file, "\n"); + } + /* third type mappings */ + if (have_chwall) + { + for (t = chwall_head.tqh_first; t != NULL; t = t->entries.tqe_next) + { + fprintf(file, "TYPE CHWALL %-25s %8x\n", + t->name, t->mapping); + } + fprintf(file, "\n"); + } + if (have_ste) { + for (t = ste_head.tqh_first; t != NULL; t = t->entries.tqe_next) + { + fprintf(file, "TYPE STE %-25s %8x\n", + t->name, t->mapping); + } + fprintf(file, "\n"); + } + fclose(file); + return 0; +} + +unsigned char *write_chwall_binary(u_int32_t * len_chwall) +{ + unsigned char *buf, *ptr; + struct acm_chwall_policy_buffer *chwall_header; + u_int32_t len; + struct ssid_entry *e; + int i; + + if (!have_chwall) + return NULL; + + len = sizeof(struct acm_chwall_policy_buffer) + + sizeof(type_t) * max_chwall_types * max_chwall_ssids + + sizeof(type_t) * max_chwall_types * max_conflictsets; + + buf = malloc(len); + ptr = buf; + + if (!buf) + { + printf("ERROR: out of memory allocating chwall buffer.\n"); + exit(EXIT_FAILURE); + } + /* chwall has 3 parts : header, types, conflictsets */ + + chwall_header = (struct acm_chwall_policy_buffer *) buf; + chwall_header->chwall_max_types = htonl(max_chwall_types); + chwall_header->chwall_max_ssidrefs = htonl(max_chwall_ssids); + chwall_header->policy_code = htonl(ACM_CHINESE_WALL_POLICY); + chwall_header->policy_version = htonl(ACM_CHWALL_VERSION); + chwall_header->chwall_ssid_offset = + htonl(sizeof(struct acm_chwall_policy_buffer)); + chwall_header->chwall_max_conflictsets = htonl(max_conflictsets); + chwall_header->chwall_conflict_sets_offset = + htonl(ntohl(chwall_header->chwall_ssid_offset) + + sizeof(domaintype_t) * max_chwall_ssids * max_chwall_types); + chwall_header->chwall_running_types_offset = 0; /* not set, only retrieved */ + chwall_header->chwall_conflict_aggregate_offset = 0; /* not set, only retrieved */ + ptr += sizeof(struct acm_chwall_policy_buffer); + + /* types */ + for (e = chwall_ssid_head.tqh_first; e != NULL; + e = e->entries.tqe_next) + { + if (e->is_ref) + continue; + + for (i = 0; i < max_chwall_types; i++) + ((type_t *) ptr)[i] = htons((type_t) e->row[i]); + + ptr += sizeof(type_t) * max_chwall_types; + } + + /* conflictsets */ + for (e = conflictsets_head.tqh_first; e != NULL; + e = e->entries.tqe_next) + { + for (i = 0; i < max_chwall_types; i++) + ((type_t *) ptr)[i] = htons((type_t) e->row[i]); + + ptr += sizeof(type_t) * max_chwall_types; + } + + if ((ptr - buf) != len) + { + printf("ERROR: wrong lengths in %s.\n", __func__); + exit(EXIT_FAILURE); + } + + (*len_chwall) = len; + return buf; +} + +unsigned char *write_ste_binary(u_int32_t * len_ste) +{ + unsigned char *buf, *ptr; + struct acm_ste_policy_buffer *ste_header; + struct ssid_entry *e; + u_int32_t len; + int i; + + if (!have_ste) + return NULL; + + len = sizeof(struct acm_ste_policy_buffer) + + sizeof(type_t) * max_ste_types * max_ste_ssids; + + buf = malloc(len); + ptr = buf; + + if (!buf) + { + printf("ERROR: out of memory allocating chwall buffer.\n"); + exit(EXIT_FAILURE); + } + + /* fill buffer */ + ste_header = (struct acm_ste_policy_buffer *) buf; + ste_header->policy_version = htonl(ACM_STE_VERSION); + ste_header->policy_code = htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); + ste_header->ste_max_types = htonl(max_ste_types); + ste_header->ste_max_ssidrefs = htonl(max_ste_ssids); + ste_header->ste_ssid_offset = + htonl(sizeof(struct acm_ste_policy_buffer)); + + ptr += sizeof(struct acm_ste_policy_buffer); + + /* types */ + for (e = ste_ssid_head.tqh_first; e != NULL; e = e->entries.tqe_next) + { + if (e->is_ref) + continue; + + for (i = 0; i < max_ste_types; i++) + ((type_t *) ptr)[i] = htons((type_t) e->row[i]); + + ptr += sizeof(type_t) * max_ste_types; + } + + if ((ptr - buf) != len) + { + printf("ERROR: wrong lengths in %s.\n", __func__); + exit(EXIT_FAILURE); + } + (*len_ste) = len; + return buf; /* for now */ +} + +int write_binary(char *filename) +{ + struct acm_policy_buffer header; + unsigned char *ste_buffer = NULL, *chwall_buffer = NULL; + u_int32_t len; + int fd; + + u_int32_t len_ste = 0, len_chwall = 0; /* length of policy components */ + + /* open binary file */ + if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) <= 0) + return -EIO; + + ste_buffer = write_ste_binary(&len_ste); + chwall_buffer = write_chwall_binary(&len_chwall); + + /* determine primary component (default chwall) */ + header.policy_version = htonl(ACM_POLICY_VERSION); + header.magic = htonl(ACM_MAGIC); + + len = sizeof(struct acm_policy_buffer); + if (have_chwall) + len += len_chwall; + if (have_ste) + len += len_ste; + header.len = htonl(len); + + header.primary_buffer_offset = htonl(sizeof(struct acm_policy_buffer)); + if (primary == CHWALL) + { + header.primary_policy_code = htonl(ACM_CHINESE_WALL_POLICY); + header.secondary_buffer_offset = + htonl((sizeof(struct acm_policy_buffer)) + len_chwall); + } + else if (primary == STE) + { + header.primary_policy_code = + htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); + header.secondary_buffer_offset = + htonl((sizeof(struct acm_policy_buffer)) + len_ste); + } + else + { + /* null policy */ + header.primary_policy_code = htonl(ACM_NULL_POLICY); + header.secondary_buffer_offset = + htonl(header.primary_buffer_offset); + } + + if (secondary == CHWALL) + header.secondary_policy_code = htonl(ACM_CHINESE_WALL_POLICY); + else if (secondary == STE) + header.secondary_policy_code = + htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); + else + header.secondary_policy_code = htonl(ACM_NULL_POLICY); + + if (write(fd, (void *) &header, sizeof(struct acm_policy_buffer)) + != sizeof(struct acm_policy_buffer)) + return -EIO; + + /* write primary policy component */ + if (primary == CHWALL) + { + if (write(fd, chwall_buffer, len_chwall) != len_chwall) + return -EIO; + } + else if (primary == STE) + { + if (write(fd, ste_buffer, len_ste) != len_ste) + return -EIO; + } else + ; /* NULL POLICY has no policy data */ + + /* write secondary policy component */ + if (secondary == CHWALL) + { + if (write(fd, chwall_buffer, len_chwall) != len_chwall) + return -EIO; + } + else if (secondary == STE) + { + if (write(fd, ste_buffer, len_ste) != len_ste) + return -EIO; + } else; /* NULL POLICY has no policy data */ + + close(fd); + return 0; +} + +int is_valid(xmlDocPtr doc) +{ + int err = 0; + xmlSchemaPtr schema_ctxt = NULL; + xmlSchemaParserCtxtPtr schemaparser_ctxt = NULL; + xmlSchemaValidCtxtPtr schemavalid_ctxt = NULL; + + schemaparser_ctxt = xmlSchemaNewParserCtxt(SCHEMA_FILENAME); + schema_ctxt = xmlSchemaParse(schemaparser_ctxt); + schemavalid_ctxt = xmlSchemaNewValidCtxt(schema_ctxt); + +#ifdef VALIDATE_SCHEMA + /* only tested to be available from libxml2-2.6.20 upwards */ + if ((err = xmlSchemaIsValid(schemavalid_ctxt)) != 1) + { + printf("ERROR: Invalid schema file %s (err=%d)\n", + SCHEMA_FILENAME, err); + err = -EIO; + goto out; + } + else + printf("XML Schema %s valid.\n", SCHEMA_FILENAME); +#endif + if ((err = xmlSchemaValidateDoc(schemavalid_ctxt, doc))) + { + err = -EIO; + goto out; + } + out: + xmlSchemaFreeValidCtxt(schemavalid_ctxt); + xmlSchemaFreeParserCtxt(schemaparser_ctxt); + xmlSchemaFree(schema_ctxt); + return (err != 0) ? 0 : 1; +} + +int main(int argc, char **argv) +{ + xmlDocPtr labeldoc = NULL; + xmlDocPtr policydoc = NULL; + + int err = EXIT_SUCCESS; + + char *file_prefix; + int prefix_len; + + if (ACM_POLICY_VERSION != WRITTEN_AGAINST_ACM_POLICY_VERSION) + { + printf("ERROR: This program was written against an older ACM version.\n"); + exit(EXIT_FAILURE); + } + + if (argc != 2) + usage(basename(argv[0])); + + prefix_len = strlen(POLICY_SUBDIR) + + strlen(argv[1]) + 1 /* "/" */ + + strlen(argv[1]) + 1 /* "/" */ ; + + file_prefix = malloc(prefix_len); + policy_filename = malloc(prefix_len + strlen(POLICY_EXTENSION)); + label_filename = malloc(prefix_len + strlen(LABEL_EXTENSION)); + binary_filename = malloc(prefix_len + strlen(BINARY_EXTENSION)); + mapping_filename = malloc(prefix_len + strlen(MAPPING_EXTENSION)); + + if (!file_prefix || !policy_filename || !label_filename || + !binary_filename || !mapping_filename) + { + printf("ERROR allocating file name memory.\n"); + goto out2; + } + + /* create input/output filenames out of prefix */ + strcat(file_prefix, POLICY_SUBDIR); + strcat(file_prefix, argv[1]); + strcat(file_prefix, "/"); + strcat(file_prefix, argv[1]); + + strcpy(policy_filename, file_prefix); + strcpy(label_filename, file_prefix); + strcpy(binary_filename, file_prefix); + strcpy(mapping_filename, file_prefix); + + strcat(policy_filename, POLICY_EXTENSION); + strcat(label_filename, LABEL_EXTENSION); + strcat(binary_filename, BINARY_EXTENSION); + strcat(mapping_filename, MAPPING_EXTENSION); + + labeldoc = xmlParseFile(label_filename); + + if (labeldoc == NULL) + { + printf("Error: could not parse file %s.\n", argv[1]); + goto out2; + } + + printf("Validating label file %s...\n", label_filename); + if (!is_valid(labeldoc)) + { + printf("ERROR: Failed schema-validation for file %s (err=%d)\n", + label_filename, err); + goto out1; + } + + policydoc = xmlParseFile(policy_filename); + + if (policydoc == NULL) + { + printf("Error: could not parse file %s.\n", argv[1]); + goto out1; + } + + printf("Validating policy file %s...\n", policy_filename); + + if (!is_valid(policydoc)) + { + printf("ERROR: Failed schema-validation for file %s (err=%d)\n", + policy_filename, err); + goto out; + } + + /* Init queues and parse policy */ + create_type_mapping(policydoc); + + /* create ssids */ + create_ssid_mapping(labeldoc); + + /* write label mapping file */ + if (write_mapping(mapping_filename)) + { + printf("ERROR: writing mapping file %s.\n", mapping_filename); + goto out; + } + + /* write binary file */ + if (write_binary(binary_filename)) + { + printf("ERROR: writing binary file %s.\n", binary_filename); + goto out; + } + + /* write stats */ + if (have_chwall) + { + printf("Max chwall labels: %u\n", max_chwall_labels); + printf("Max chwall-types: %u\n", max_chwall_types); + printf("Max chwall-ssids: %u\n", max_chwall_ssids); + } + + if (have_ste) + { + printf("Max ste labels: %u\n", max_ste_labels); + printf("Max ste-types: %u\n", max_ste_types); + printf("Max ste-ssids: %u\n", max_ste_ssids); + } + /* cleanup */ + out: + xmlFreeDoc(policydoc); + out1: + xmlFreeDoc(labeldoc); + out2: + xmlCleanupParser(); + return err; +} + diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/secpol_xml2bin.h --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/secpol_xml2bin.h Fri Aug 19 18:19:28 2005 @@ -0,0 +1,139 @@ +/**************************************************************** + * secpol_xml2bin.h + * + * Copyright (C) 2005 IBM Corporation + * + * Authors: + * Reiner Sailer <sailer@xxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + */ +#define POLICY_SUBDIR "policies/" +#define POLICY_EXTENSION "-security_policy.xml" +#define LABEL_EXTENSION "-security_label_template.xml" +#define BINARY_EXTENSION ".bin" +#define MAPPING_EXTENSION ".map" +#define PRIMARY_COMPONENT_ATTR_NAME "order" +#define BOOTSTRAP_LABEL_ATTR_NAME "bootstrap" +#define PRIMARY_COMPONENT "PrimaryPolicyComponent" +#define SCHEMA_FILENAME "policies/security_policy.xsd" + +/* basic states (used as 1 << X) */ +#define XML2BIN_SECPOL 0 /* policy tokens */ +#define XML2BIN_STE 1 +#define XML2BIN_CHWALL 2 +#define XML2BIN_CONFLICTSETS 3 +#define XML2BIN_CSTYPE 4 + +#define XML2BIN_SECTEMPLATE 5 /* label tokens */ +#define XML2BIN_POLICYHEADER 6 +#define XML2BIN_LABELHEADER 7 +#define XML2BIN_SUBJECTS 8 +#define XML2BIN_OBJECTS 9 +#define XML2BIN_VM 10 +#define XML2BIN_RES 11 + +#define XML2BIN_STETYPES 12 /* shared tokens */ +#define XML2BIN_CHWALLTYPES 13 +#define XML2BIN_TYPE 14 +#define XML2BIN_NAME 15 +#define XML2BIN_TEXT 16 +#define XML2BIN_COMMENT 17 + +/* type "data type" (currently 16bit) */ +typedef u_int16_t type_t; + +/* list of known elements and token equivalent * + * state constants and token positions must be * + * in sync for correct state recognition */ + +char *token[20] = /* parser triggers */ +{ + [0] = "SecurityPolicyDefinition", /* policy xml */ + [1] = "SimpleTypeEnforcement", + [2] = "ChineseWall", + [3] = "ConflictSets", + [4] = "Conflict", /* label-template xml */ + [5] = "SecurityLabelTemplate", + [6] = "PolicyHeader", + [7] = "LabelHeader", + [8] = "SubjectLabels", + [9] = "ObjectLabels", + [10] = "VirtualMachineLabel", + [11] = "ResourceLabel", + [12] = "SimpleTypeEnforcementTypes", /* common tags */ + [13] = "ChineseWallTypes", + [14] = "Type", + [15] = "Name", + [16] = "text", + [17] = "comment", + [18] = NULL, +}; + +/* important combined states */ +#define XML2BIN_NULL 0 + +/* policy xml parsing states _S */ + +/* e.g., here we are in a <secpol,ste,stetypes> environment, * + * so when finding a type element, we know where to put it */ +#define XML2BIN_stetype_S ((1 << XML2BIN_SECPOL) | \ + (1 << XML2BIN_STE) | \ + (1 << XML2BIN_STETYPES)) + +#define XML2BIN_chwalltype_S ((1 << XML2BIN_SECPOL) | \ + (1 << XML2BIN_CHWALL) | \ + (1 << XML2BIN_CHWALLTYPES)) + +#define XML2BIN_conflictset_S ((1 << XML2BIN_SECPOL) | \ + (1 << XML2BIN_CHWALL) | \ + (1 << XML2BIN_CONFLICTSETS)) + +#define XML2BIN_conflictsettype_S ((1 << XML2BIN_SECPOL) | \ + (1 << XML2BIN_CHWALL) | \ + (1 << XML2BIN_CONFLICTSETS) | \ + (1 << XML2BIN_CSTYPE)) + + +/* label xml states */ +#define XML2BIN_VM_S ((1 << XML2BIN_SECTEMPLATE) | \ + (1 << XML2BIN_SUBJECTS) | \ + (1 << XML2BIN_VM)) + +#define XML2BIN_RES_S ((1 << XML2BIN_SECTEMPLATE) | \ + (1 << XML2BIN_OBJECTS) | \ + (1 << XML2BIN_RES)) + +#define XML2BIN_VM_STE_S ((1 << XML2BIN_SECTEMPLATE) | \ + (1 << XML2BIN_SUBJECTS) | \ + (1 << XML2BIN_VM) | \ + (1 << XML2BIN_STETYPES)) + +#define XML2BIN_VM_CHWALL_S ((1 << XML2BIN_SECTEMPLATE) | \ + (1 << XML2BIN_SUBJECTS) | \ + (1 << XML2BIN_VM) | \ + (1 << XML2BIN_CHWALLTYPES)) + +#define XML2BIN_RES_STE_S ((1 << XML2BIN_SECTEMPLATE) | \ + (1 << XML2BIN_OBJECTS) | \ + (1 << XML2BIN_RES) | \ + (1 << XML2BIN_STETYPES)) + + + +/* check versions of headers against which the + * xml2bin translation tool was written + */ + +/* protects from unnoticed changes in struct acm_policy_buffer */ +#define WRITTEN_AGAINST_ACM_POLICY_VERSION 1 + +/* protects from unnoticed changes in struct acm_chwall_policy_buffer */ +#define WRITTEN_AGAINST_ACM_CHWALL_VERSION 1 + +/* protects from unnoticed changes in struct acm_ste_policy_buffer */ +#define WRITTEN_AGAINST_ACM_STE_VERSION 1 diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/setlabel.sh --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/setlabel.sh Fri Aug 19 18:19:28 2005 @@ -0,0 +1,345 @@ +#!/bin/sh +# * +# * setlabel +# * +# * Copyright (C) 2005 IBM Corporation +# * +# * Authors: +# * Stefan Berger <stefanb@xxxxxxxxxx> +# * +# * This program is free software; you can redistribute it and/or +# * modify it under the terms of the GNU General Public License as +# * published by the Free Software Foundation, version 2 of the +# * License. +# * +# * 'setlabel' labels virtual machine (domain) configuration files with +# * security identifiers that can be enforced in Xen. +# * +# * 'setlabel -?' shows the usage of the program +# * +# * 'setlabel -l vmconfig-file' lists all available labels (only VM +# * labels are used right now) +# * +# * 'setlabel vmconfig-file security-label map-file' inserts the 'ssidref' +# * that corresponds to the security-label under the +# * current policy (if policy changes, 'label' +# * must be re-run over the configuration files; +# * map-file is created during policy translation and +# * is found in the policy's directory +# + +if [ -z "$runbash" ]; then + runbash="1" + export runbash + exec sh -c "bash $0 $*" +fi + + +usage () +{ + echo "Usage: $0 [Option] <vmfile> <label> <policy name> " + echo " or $0 -l <policy name>" + echo "" + echo "Valid Options are:" + echo "-r : to relabel a file without being prompted" + echo "" + echo "vmfile : XEN vm configuration file" + echo "label : the label to map" + echo "policy name : the name of the policy, i.e. 'chwall'" + echo "" + echo "-l <policy name> is used to show valid labels in the map file" + echo "" +} + + +findMapFile () +{ + mapfile="./$1.map" + if [ -r "$mapfile" ]; then + return 1 + fi + + mapfile="./policies/$1/$1.map" + if [ -r "$mapfile" ]; then + return 1 + fi + + return 0 +} + +showLabels () +{ + mapfile=$1 + if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then + echo "Cannot read from vm configuration file $vmfile." + return -1 + fi + + getPrimaryPolicy $mapfile + getSecondaryPolicy $mapfile + + echo "The following labels are available:" + let line=1 + while [ 1 ]; do + ITEM=`cat $mapfile | \ + awk -vline=$line \ + -vprimary=$primary \ + '{ \ + if ($1 == "LABEL->SSID" && \ + $2 == "VM" && \ + $3 == primary ) { \ + ctr++; \ + if (ctr == line) { \ + print $4; \ + } \ + } \ + } END { \ + }'` + + if [ "$ITEM" == "" ]; then + break + fi + if [ "$secondary" != "NULL" ]; then + LABEL=`cat $mapfile | \ + awk -vitem=$ITEM \ + '{ + if ($1 == "LABEL->SSID" && \ + $2 == "VM" && \ + $3 == "CHWALL" && \ + $4 == item ) { \ + result = item; \ + } \ + } END { \ + print result \ + }'` + else + LABEL=$ITEM + fi + + if [ "$LABEL" != "" ]; then + echo "$LABEL" + found=1 + fi + let line=line+1 + done + if [ "$found" != "1" ]; then + echo "No labels found." + fi +} + +getPrimaryPolicy () +{ + mapfile=$1 + primary=`cat $mapfile | \ + awk ' \ + { \ + if ( $1 == "PRIMARY" ) { \ + res=$2; \ + } \ + } END { \ + print res; \ + } '` +} + +getSecondaryPolicy () +{ + mapfile=$1 + secondary=`cat $mapfile | \ + awk ' \ + { \ + if ( $1 == "SECONDARY" ) { \ + res=$2; \ + } \ + } END { \ + print res; \ + } '` +} + + +getDefaultSsid () +{ + mapfile=$1 + pol=$2 + RES=`cat $mapfile \ + awk -vpol=$pol \ + { \ + if ($1 == "LABEL->SSID" && \ + $2 == "ANY" && \ + $3 == pol && \ + $4 == "DEFAULT" ) {\ + res=$5; \ + } \ + } END { \ + printf "%04x", strtonum(res) \ + }'` + echo "default NULL mapping is $RES" + defaultssid=$RES +} + +relabel () +{ + vmfile=$1 + label=$2 + mapfile=$3 + mode=$4 + + if [ ! -r "$vmfile" ]; then + echo "Cannot read from vm configuration file $vmfile." + return -1 + fi + + if [ ! -w "$vmfile" ]; then + echo "Cannot write to vm configuration file $vmfile." + return -1 + fi + + if [ ! -r "$mapfile" ] ; then + echo "Cannot read mapping file $mapfile." + return -1 + fi + + # Determine which policy is primary, which sec. + getPrimaryPolicy $mapfile + getSecondaryPolicy $mapfile + + # Calculate the primary policy's SSIDREF + if [ "$primary" == "NULL" ]; then + SSIDLO="0000" + else + SSIDLO=`cat $mapfile | \ + awk -vlabel=$label \ + -vprimary=$primary \ + '{ \ + if ( $1 == "LABEL->SSID" && \ + $2 == "VM" && \ + $3 == primary && \ + $4 == label ) { \ + result=$5 \ + } \ + } END { \ + if (result != "" ) \ + {printf "%04x", strtonum(result)}\ + }'` + fi + + # Calculate the secondary policy's SSIDREF + if [ "$secondary" == "NULL" ]; then + SSIDHI="0000" + else + SSIDHI=`cat $mapfile | \ + awk -vlabel=$label \ + -vsecondary=$secondary \ + '{ \ + if ( $1 == "LABEL->SSID" && \ + $2 == "VM" && \ + $3 == secondary && \ + $4 == label ) { \ + result=$5 \ + } \ + } END { \ + if (result != "" ) \ + {printf "%04x", strtonum(result)}\ + }'` + fi + + if [ "$SSIDLO" == "" -o \ + "$SSIDHI" == "" ]; then + echo "Could not map the given label '$label'." + return -1 + fi + + ACM_POLICY=`cat $mapfile | \ + awk ' { if ( $1 == "POLICY" ) { \ + result=$2 \ + } \ + } \ + END { \ + if (result != "") { \ + printf result \ + } \ + }'` + + if [ "$ACM_POLICY" == "" ]; then + echo "Could not find 'POLICY' entry in map file." + return -1 + fi + + SSIDREF="0x$SSIDHI$SSIDLO" + + if [ "$mode" != "relabel" ]; then + RES=`cat $vmfile | \ + awk '{ \ + if ( substr($1,0,7) == "ssidref" ) {\ + print $0; \ + } \ + }'` + if [ "$RES" != "" ]; then + echo "Do you want to overwrite the existing mapping ($RES)? (y/N)" + read user + if [ "$user" != "y" -a "$user" != "Y" ]; then + echo "Aborted." + return 0 + fi + fi + fi + + #Write the output + vmtmp1="/tmp/__setlabel.tmp1" + vmtmp2="/tmp/__setlabel.tmp2" + touch $vmtmp1 + touch $vmtmp2 + if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then + echo "Cannot create temporary files. Aborting." + return -1 + fi + RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1` + RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2` + RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1` + echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1 + echo "#ACM_LABEL=$label" >> $vmtmp1 + echo "ssidref = $SSIDREF" >> $vmtmp1 + mv -f $vmtmp1 $vmfile + rm -rf $vmtmp1 $vmtmp2 + echo "Mapped label '$label' to ssidref '$SSIDREF'." +} + + + +if [ "$1" == "-r" ]; then + mode="relabel" + shift +elif [ "$1" == "-l" ]; then + mode="show" + shift +elif [ "$1" == "-?" ]; then + mode="usage" +fi + +if [ "$mode" == "show" ]; then + if [ "$1" == "" ]; then + usage + exit -1; + fi + findMapFile $1 + res=$? + if [ "$res" != "0" ]; then + showLabels $mapfile + else + echo "Could not find map file for policy '$1'." + fi +elif [ "$mode" == "usage" ]; then + usage +else + if [ "$3" == "" ]; then + usage + exit -1; + fi + findMapFile $3 + res=$? + if [ "$res" != "0" ]; then + relabel $1 $2 $mapfile $mode + else + echo "Could not find map file for policy '$3'." + fi + +fi diff -r 99914b54f7bf -r 81576d3d1ca8 tools/security/updategrub.sh --- /dev/null Thu Aug 18 18:40:02 2005 +++ b/tools/security/updategrub.sh Fri Aug 19 18:19:28 2005 @@ -0,0 +1,171 @@ +#!/bin/sh +# * +# * updategrub +# * +# * Copyright (C) 2005 IBM Corporation +# * +# * Authors: +# * Stefan Berger <stefanb@xxxxxxxxxx> +# * +# * This program is free software; you can redistribute it and/or +# * modify it under the terms of the GNU General Public License as +# * published by the Free Software Foundation, version 2 of the +# * License. +# * +# * +# + +if [ -z "$runbash" ]; then + runbash="1" + export runbash + exec sh -c "bash $0 $*" + exit +fi + + +# Show usage of this program +usage () +{ + echo "Usage: $0 <policy name> <root of xen repository>" + echo "" + echo "<policy name> : The name of the policy, i.e. xen_null" + echo "<root of xen repository> : The root of the XEN repositrory." + echo "" +} + +# This function sets the global variable 'linux' +# to the name of the linux kernel that was compiled +# For now a pattern should do the trick +getLinuxVersion () +{ + path=$1 + linux="" + for f in $path/linux-*-xen0 ; do + versionfile=$f/include/linux/version.h + if [ -r $versionfile ]; then + lnx=`cat $versionfile | \ + grep UTS_RELEASE | \ + awk '{ \ + len=length($3); \ + print substr($3,2,len-2) }'` + fi + if [ "$lnx" != "" ]; then + linux="[./0-9a-zA-z]*$lnx" + return; + fi + done + + #Last resort. + linux="vmlinuz-2.[45678].[0-9]*[.0-9]*-xen0$" +} + +#Return where the grub.conf file is. +#I only know of one place it can be. +findGrubConf() +{ + grubconf="/boot/grub/grub.conf" + if [ -w $grubconf ]; then + return 1 + fi + return 0 +} + + +#Update the grub configuration file. +#Search for existing entries and replace the current +#policy entry with the policy passed to this script +# +#Arguments passed to this function +# 1st : the grub configuration file +# 2nd : the binary policy file name +# 3rd : the name or pattern of the linux kernel name to match +# +# The algorithm here is based on pattern matching +# and is working correctly if +# - under a title a line beginning with 'kernel' is found +# whose following item ends with "xen.gz" +# Example: kernel /xen.gz dom0_mem=.... +# - a module line matching the 3rd parameter is found +# +updateGrub () +{ + grubconf=$1 + policyfile=$2 + linux=$3 + + tmpfile="/tmp/new_grub.conf" + + cat $grubconf | \ + awk -vpolicy=$policyfile \ + -vlinux=$linux '{ \ + if ( $1 == "title" ) { \ + kernelfound = 0; \ + if ( policymaycome == 1 ){ \ + printf ("\tmodule %s%s\n", path, policy); \ + } \ + policymaycome = 0; \ + } \ + else if ( $1 == "kernel" ) { \ + if ( match($2,"xen.gz$") ) { \ + path=substr($2,1,RSTART-1); \ + kernelfound = 1; \ + } \ + } \ + else if ( $1 == "module" && \ + kernelfound == 1 && \ + match($2,linux) ) { \ + policymaycome = 1; \ + } \ + else if ( $1 == "module" && \ + kernelfound == 1 && \ + policymaycome == 1 && \ + match($2,"[0-9a-zA-Z]*.bin$") ) { \ + printf ("\tmodule %s%s\n", path, policy); \ + policymaycome = 0; \ + kernelfound = 0; \ + dontprint = 1; \ + } \ + else if ( $1 == "" && \ + kernelfound == 1 && \ + policymaycome == 1) { \ + dontprint = 1; \ + } \ + if (dontprint == 0) { \ + printf ("%s\n", $0); \ + } \ + dontprint = 0; \ + } END { \ + if ( policymaycome == 1 ) { \ + printf ("\tmodule %s%s\n", path, policy); \ + } \ + }' > $tmpfile + if [ ! -r $tmpfile ]; then + echo "Could not create temporary file! Aborting." + exit -1 + fi + mv -f $tmpfile $grubconf +} + +if [ "$1" == "" -o "$2" == "" ]; then + usage + exit -1 +fi + +if [ "$1" == "-?" ]; then + usage + exit 0 +fi + +policy=$1 +policyfile=$policy.bin + +getLinuxVersion $2 + +findGrubConf +ERR=$? +if [ $ERR -eq 0 ]; then + echo "Could not find grub.conf. Aborting." + exit -1 +fi + +updateGrub $grubconf $policyfile $linux diff -r 99914b54f7bf -r 81576d3d1ca8 docs/misc/shype4xen_readme.txt --- a/docs/misc/shype4xen_readme.txt Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,588 +0,0 @@ -Copyright: IBM Corporation (C) -20 June 2005 -Author: Reiner Sailer - -This document is a very short introduction into the sHype access control -security architecture implementation and how it is perceived by users. It -is a very preliminary draft for the courageous ones to get "their feet wet" -and to be able to give feedback (via the xen-devel/xense-devel mailing lists). - -Install: - -cd into xeno-unstable.bk -(use --dry-run option if you want to test the patch only) -patch -p1 -g0 < *tools.diff -patch -p1 -g0 < *xen.diff - -(no rejects, probably some line offsets) - -make uninstall; make mrproper; make; ./install.sh should install the default -sHype into Xen (rebuild your initrd images if necessary). Reboot. - -Debug output: there are two triggers for debug output: -a) General sHype debug: - xeno-unstable.bk/xen/include/public/acm.h - undefine ACM_DEBUG to switch this debug off - -b) sHype enforcement hook trace: This prints a small trace for each enforcement -hook that is executed. The trigger is in - xeno-unstable.bk/xen/include/acm/acm_hooks.h - undefine ACM_TRACE_MODE to switch this debug off - -1. The default NULL policy -*************************** -When you apply the patches and startup xen, you should at first not notice any -difference because the default policy is the "NULL" policy, which as the name -implies does not enforce anything. - -To display the currently enforced policy, use the policy tool under xeno- -unstable.bk/tools/policy: policy_tool getpolicy. You should see output like the -one below. - -[root@laptop policy]#./policy_tool getpolicy - -Policy dump: -============ -Magic = 1debc. -PolVer = aaaa0000. -Len = 14. -Primary = NULL policy (c=0, off=14). -Secondary = NULL policy (c=0, off=14). -No primary policy (NULL). -No secondary policy (NULL). - -Policy dump End. - -Since this is a dump of a binary policy, it's not pretty. The important parts -are the "Primary" and "Secondary" policy fields set to "NULL policy". sHype -currently allows to set two independent policies; thus the two SSID-REF parts -shown in 'xm list'. Right here: primary policy only means this policy is -checked first, the secondary policy is checked if the primary results in -"permitted access". The result of the combined policy is "permitted" if both -policies return permitted (NULL policy always returns permitted). The result is -"denied" if at least one of the policies returns "denied". Look into xeno- -unstable.bk/xen/include/acm/acm_hooks.h for the general hook structure -integrating the policy decisions (if you like, you won't need it for the rest -of the Readme file). - -2. Setting Chinese Wall and Simple Type Enforcement policies: -************************************************************* - -We'll get fast to the point. However, in order to understand what we are doing, -we must at least understand the purpose of the policies that we are going to -enforce. The two policies presented here are just examples and the -implementation encourages adding new policies easily. - -2.1. Chinese Wall policy: "decides whether a domain can be started based on -this domain's ssidref and the ssidrefs of the currently running domains". -Generally, the Chinese wall policy allows specifying certain types (or classes -or categories, whatever the preferred word) that conflict; we usually assign a -type to a workload and the set of types of those workloads running in a domain -make up the type set for this domain. Each domain is assigned a set of types -through its SSID-REF (we register Chinese Wall as primary policy, so the -ssidref used for determining the Chinese Wall types is the one annotated with -"p:" in xm list) since each SSID-REF points at a set of types. We'll see how -SSIDREFs are represented in Xen later when we will look at the policy. (A good -read for Chinese Wall is: Brewer/Nash The Chinese Wall Security Policy 1989.) - -So let's assume the Chinese Wall policy we are running distinguishes 10 types: -t0 ... t9. Let us assume further that each SSID-REF points to a set that -includes exactly one type (attached to domains that run workloads of a single -type). SSID-REF 0 points to {t0}, ssidref 1 points to {t1} ... 9 points to -{t9}. [This is actually the example policy we are going to push into xen later] - -Now the Chinese Wall policy allows you to define "Conflict type sets" and it -guarantees that of any conflict set at most one type is "running" at any time. -As an example, we have defined 2 conflict set: {t2, t3} and {t0, t5, t6}. -Specifying these conflict sets, sHype ensures that at most one type of each set -is running (either t2 or t3 but not both; either t0 or t5 or t6 but not -multiple of them). - -The effect is that administrators can define which workload types cannot run -simultaneously on a single Xen system. This is useful to limit the covert -timing channels between such payloads or to ensure that payloads don't -interfere with each other through existing resource dependencies. - -2.2. Simple Type Enforcement (ste) policy: "decides whether two domains can -share data, e.g., setup event channels or grant tables to each other, based on -the two domains' ssidref. This, as the name says, is a simple policy. Think of -each type as of a single color. Each domain has one or more colors, i.e., the -domains ssid for the ste policy points to a set that has set one or multiple -types. Let us assume in our example policy we differentiate 5 colors (types) -and define 5 different ssids referenced by ssidref=0..4. Each ssid shall have -exactly one type set, i.e., describes a uni-color. Only ssid(0) has all types -set, i.e., has all defined colors. - -Sharing is enforced by the ste policy by requiring that two domains that want -to establish an event channel or grant pages to each other must have a common -color. Currently all domains communicate through DOM0 by default; i.e., Domain0 -will necessarily have all colors to be able to create domains (thus, we will -assign ssidref(0) to Domain0 in our example below. - -More complex mandatory access control policies governing sharing will follow; -such policies are more sophisticated than the "color" scheme above by allowing -more flexible (and complex :_) access control decisions than "share a color" or -"don't share a color" and will be able to express finer-grained policies. - - -2.3 Binary Policy: -In the future, we will have a policy tool that takes as input a more humane -policy description, using types such as development, home-banking, donated- -Grid, CorpA-Payload ... and translates the respective policy into what we see -today as the binary policy using 1s and 0s and sets of them. For now, we must -live with the binary policy when working with sHype. - - -2.4 Exemplary use of a real sHype policy on Xen. To activate a real policy, -edit the file (yes, this will soon be a compile option): - xeno-unstable.bk/xen/include/public/acm.h - Change: #define ACM_USE_SECURITY_POLICY ACM_NULL_POLICY - To : #define ACM_USE_SECURITY_POLICY ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY - cd xeno-unstable.bk - make mrproper - make uninstall (manually remove /etc/xen.old if necessary) - make - ./install.sh (recreate your kernel initrd's if necessary) - Reboot into new xen.gz - -After booting, check out 'xm dmesg'; should show somewhere in the middle: - -(XEN) acm_init: Enforcing Primary CHINESE WALL policy, Secondary SIMPLE TYPE -ENFORCEMENT policy. - -Even though you can activate those policies in any combination and also -independently, the policy tool currently only supports setting the policy for -the above combination. - -Now look at the minimal startup policy with: - xeno-unstable.bk/tools/policytool getpolicy - -You should see something like: - -[root@laptop policy]# ./policy_tool getpolicy - -Policy dump: -============ -Magic = 1debc. -PolVer = aaaa0000. -Len = 36. -Primary = CHINESE WALL policy (c=1, off=14). -Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=2c). - - -Chinese Wall policy: -==================== -Max Types = 1. -Max Ssidrefs = 1. -Max ConfSets = 1. -Ssidrefs Off = 10. -Conflicts Off = 12. -Runing T. Off = 14. -C. Agg. Off = 16. - -SSID To CHWALL-Type matrix: - - ssidref 0: 00 - -Confict Sets: - - c-set 0: 00 - -Running -Types: 00 - -Conflict -Aggregate Set: 00 - - -Simple Type Enforcement policy: -=============================== -Max Types = 1. -Max Ssidrefs = 1. -Ssidrefs Off = 8. - -SSID To STE-Type matrix: - - ssidref 0: 01 - - -Policy dump End. - -This is a minimal policy (of little use), except it will disable starting any -domain that does not have ssidref set to 0x0. The Chinese Wall policy has -nothing to enforce and the ste policy only knows one type, which is set for the -only defined ssidref. - -The item that defines the ssidref in a domain configuration is: - -ssidref = 0x12345678 - -Where ssidref is interpreted as a 32bit number, where the lower 16bits become -the ssidref for the primary policy and the higher 16bits become the ssidref for -the secondary policy. sHype currently supports two policies but this is an -implementation decision and can be extended if necessary. - -This reference defines the security information of a domain. The meaning of the -SSID-REF depends on the policy, so we explain it when we explain the real -policies. - - -Setting a new Security Policy: -****************************** -The policy tool with all its current limitations has one usable example policy -compiled-in. Please try at this time to use the setpolicy command: - xeno-unstable.bk/tools/policy/policy_tool setpolicy - -You should see a dump of the policy you are setting. It should say at the very -end: - -Policy successfully set. - -Now try to dump the currently enforced policy, which is the policy we have just -set and the dynamic security state information of this policy -(<<< ... some additional explanations) - -[root@laptop policy]# ./policy_tool getpolicy - -Policy dump: -============ -Magic = 1debc. -PolVer = aaaa0000. -Len = 112. -Primary = CHINESE WALL policy (c=1, off=14). -Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=d8). - - -Chinese Wall policy: -==================== -Max Types = a. -Max Ssidrefs = 5. -Max ConfSets = 2. -Ssidrefs Off = 10. -Conflicts Off = 74. -Runing T. Off = 9c. -C. Agg. Off = b0. - -SSID To CHWALL-Type matrix: - - ssidref 0: 01 00 00 00 00 00 00 00 00 00 <<< type0 is set for ssidref0 - ssidref 1: 00 01 00 00 00 00 00 00 00 00 - ssidref 2: 00 00 01 00 00 00 00 00 00 00 - ssidref 3: 00 00 00 01 00 00 00 00 00 00 - ssidref 4: 00 00 00 00 01 00 00 00 00 00 <<< type4 is set for ssidref4 - <<< types 5-9 are unused -Confict Sets: - - c-set 0: 00 00 01 01 00 00 00 00 00 00 <<< type2 and type3 never run together - c-set 1: 01 00 00 00 00 01 01 00 00 00 <<< only one of types 0, 5 or 6 - <<< can run simultaneously -Running -Types: 01 00 00 00 00 00 00 00 00 00 <<< ref-count for types of running domains - -Conflict -Aggregate Set: 00 00 00 00 00 01 01 00 00 00 <<< aggregated set of types that - <<< cannot run because they - <<< are in conflict set 1 and - <<< (domain 0 is running w t0) - - -Simple Type Enforcement policy: -=============================== -Max Types = 5. -Max Ssidrefs = 5. -Ssidrefs Off = 8. - -SSID To STE-Type matrix: - - ssidref 0: 01 01 01 01 01 <<< ssidref0 points to a set that - <<< has all types set (colors) - ssidref 1: 00 01 00 00 00 <<< ssidref1 has color1 set - ssidref 2: 00 00 01 00 00 <<< ... - ssidref 3: 00 00 00 01 00 - ssidref 4: 00 00 00 00 01 - - -Policy dump End. - - -This is a small example policy with which we will demonstrate the enforcement. - -Starting Domains with policy enforcement -======================================== -Now let us play with this policy. - -Define 3 or 4 domain configurations. I use the following config using a ramdisk -only and about 8MBytes of memory for each DomU (test purposes): - -#-------configuration xmsec1------------------------- -kernel = "/boot/vmlinuz-2.6.11-xenU" -ramdisk="/boot/U1_ramdisk.img" -#security reference identifier -ssidref= 0x00010001 -memory = 10 -name = "xmsec1" -cpu = -1 # leave to Xen to pick -# Number of network interfaces. Default is 1. -nics=1 -dhcp="dhcp" -#----------------------------------------------------- - -xmsec2 and xmsec3 look the same except for the name and the ssidref line. Use -your domain config file and add "ssidref = 0x00010001" to the first (xmsec1), -"ssidref= 0x00020002" to the second (call it xmsec2), and "ssidref=0x00030003" -to the third (we will call this one xmsec3). - -First start xmsec1: xm create -c xmsec1 (succeeds) - -Then -[root@laptop policy]# xm list -Name Id Mem(MB) CPU State Time(s) Console -Domain-0 0 620 0 r---- 42.3 s:00/p:00 -xmnosec 1 9 0 -b--- 0.3 9601 s:00/p:05 -xmsec1 2 9 0 -b--- 0.2 9602 s:01/p:01 - -Shows a new domain xmsec1 running with primary (here: chinese wall) ssidref 1 -and secondary (here: simple type enforcement) ssidref 1. The ssidrefs are -independent and can differ for a domain. - -[root@laptop policy]# ./policy_tool getpolicy - -Policy dump: -============ -Magic = 1debc. -PolVer = aaaa0000. -Len = 112. -Primary = CHINESE WALL policy (c=1, off=14). -Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=d8). - - -Chinese Wall policy: -==================== -Max Types = a. -Max Ssidrefs = 5. -Max ConfSets = 2. -Ssidrefs Off = 10. -Conflicts Off = 74. -Runing T. Off = 9c. -C. Agg. Off = b0. - -SSID To CHWALL-Type matrix: - - ssidref 0: 01 00 00 00 00 00 00 00 00 00 - ssidref 1: 00 01 00 00 00 00 00 00 00 00 - ssidref 2: 00 00 01 00 00 00 00 00 00 00 - ssidref 3: 00 00 00 01 00 00 00 00 00 00 - ssidref 4: 00 00 00 00 01 00 00 00 00 00 - -Confict Sets: - - c-set 0: 00 00 01 01 00 00 00 00 00 00 - c-set 1: 01 00 00 00 00 01 01 00 00 00 <<< t1 is not part of any c-set - -Running -Types: 01 01 00 00 00 00 00 00 00 00 <<< xmsec1 has ssidref 1->type1 - ^^ <<< ref-count at position 1 incr -Conflict -Aggregate Set: 00 00 00 00 00 01 01 00 00 00 <<< domain 1 was allowed to - <<< start since type 1 was not - <<< in conflict with running - <<< types - -Simple Type Enforcement policy: -=============================== -Max Types = 5. -Max Ssidrefs = 5. -Ssidrefs Off = 8. - -SSID To STE-Type matrix: - - ssidref 0: 01 01 01 01 01 <<< the ste policy does not maintain; we - ssidref 1: 00 01 00 00 00 <-- <<< see that domain xmsec1 has ste - ssidref 2: 00 00 01 00 00 <<< ssidref1->type1 and has this type in - ssidref 3: 00 00 00 01 00 <<< common with dom0 - ssidref 4: 00 00 00 00 01 - - -Policy dump End. - -Look at sHype output in xen dmesg: - -[root@laptop xen]# xm dmesg -. -. -[somewhere near the very end] -(XEN) chwall_init_domain_ssid: determined chwall_ssidref to 1. -(XEN) ste_init_domain_ssid. -(XEN) ste_init_domain_ssid: determined ste_ssidref to 1. -(XEN) acm_init_domain_ssid: Instantiated individual ssid for domain 0x01. -(XEN) chwall_post_domain_create. -(XEN) ste_pre_eventchannel_interdomain. -(XEN) ste_pre_eventchannel_interdomain: (evtchn 0 --> 1) common type #01. -(XEN) shype_authorize_domops. -(XEN) ste_pre_eventchannel_interdomain. -(XEN) ste_pre_eventchannel_interdomain: (evtchn 0 --> 1) common type #01. -(XEN) ste_pre_eventchannel_interdomain. -(XEN) ste_pre_eventchannel_interdomain: (evtchn 0 --> 1) common type #01. - - -You can see that the chinese wall policy does not complain and that the ste -policy makes three access control decisions for three event-channels setup -between domain 0 and the new domain 1. Each time, the two domains share the -type1 and setting up the eventchannel is permitted. - - -Starting up a second domain xmsec2: - -[root@laptop xen]# xm create -c xmsec2 -Using config file "xmsec2". -Started domain xmsec2, console on port 9602 -************ REMOTE CONSOLE: CTRL-] TO QUIT ******** -Linux version 2.6.11-xenU (root@xxxxxxxxxxxxxxx) (gcc version 3.4.2 20041017 -(Red Hat 3.4.2-6.fc3)) #1 Wed Mar 30 13:14:31 EST 2005 -. -. -. -[root@laptop policy]# xm list -Name Id Mem(MB) CPU State Time(s) Console -Domain-0 0 620 0 r---- 71.7 s:00/p:00 -xmsec1 1 9 0 -b--- 0.3 9601 s:01/p:01 -xmsec2 2 7 0 -b--- 0.3 9602 s:02/p:02 << our domain runs both policies with ssidref 2 - - -[root@laptop policy]# ./policy_tool getpolicy - -Policy dump: -============ -Magic = 1debc. -PolVer = aaaa0000. -Len = 112. -Primary = CHINESE WALL policy (c=1, off=14). -Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=d8). - - -Chinese Wall policy: -==================== -Max Types = a. -Max Ssidrefs = 5. -Max ConfSets = 2. -Ssidrefs Off = 10. -Conflicts Off = 74. -Runing T. Off = 9c. -C. Agg. Off = b0. - -SSID To CHWALL-Type matrix: - - ssidref 0: 01 00 00 00 00 00 00 00 00 00 - ssidref 1: 00 01 00 00 00 00 00 00 00 00 - ssidref 2: 00 00 01 00 00 00 00 00 00 00 <<< our domain has type 2 set - ssidref 3: 00 00 00 01 00 00 00 00 00 00 - ssidref 4: 00 00 00 00 01 00 00 00 00 00 - -Confict Sets: - - c-set 0: 00 00 01 01 00 00 00 00 00 00 <<< t2 is in c-set0 with type 3 - c-set 1: 01 00 00 00 00 01 01 00 00 00 - -Running -Types: 01 01 01 00 00 00 00 00 00 00 <<< t2 is running since the - ^^ <<< current aggregate conflict - <<< set (see above) does not - <<< include type 2 -Conflict -Aggregate Set: 00 00 00 01 00 01 01 00 00 00 <<< type 3 is added to the - <<< conflict aggregate - - -Simple Type Enforcement policy: -=============================== -Max Types = 5. -Max Ssidrefs = 5. -Ssidrefs Off = 8. - -SSID To STE-Type matrix: - - ssidref 0: 01 01 01 01 01 - ssidref 1: 00 01 00 00 00 - ssidref 2: 00 00 01 00 00 - ssidref 3: 00 00 00 01 00 - ssidref 4: 00 00 00 00 01 - - -Policy dump End. - - -The sHype xen dmesg output looks similar to the one above when starting the -first domain. - -Now we start xmsec3 and it has ssidref3. Thus, it tries to run as type3 which -conflicts with running type2 (from xmsec2). As expected, creating this domain -fails for security policy enforcement reasons. - -[root@laptop xen]# xm create -c xmsec3 -Using config file "xmsec3". -Error: Error creating domain: (22, 'Invalid argument') -[root@laptop xen]# - -[root@laptop xen]# xm dmesg -. -. -[somewhere near the very end] -(XEN) chwall_pre_domain_create. -(XEN) chwall_pre_domain_create: CHINESE WALL CONFLICT in type 03. - -xmsec3 ssidref3 points to type3, which is in the current conflict aggregate -set. This domain cannot start until domain xmsec2 is destroyed, at which time -the aggregate conflict set is reduced and type3 is excluded from it. Then, -xmsec3 can start. Of course, afterwards, xmsec2 cannot be restarted. Try it. - -3. Policy tool -************** -toos/policy/policy_tool.c - -a) ./policy_tool getpolicy - prints the currently enforced policy - (see for example section 1.) - -b) ./policy_tool setpolicy - sets a predefined and hardcoded security - policy (the one described in section 2.) - -c) ./policy_tool dumpstats - prints some status information about the caching - of access control decisions (number of cache hits - and number of policy evaluations for grant_table - and event channels). - -d) ./policy_tool loadpolicy <binary_policy_file> - sets the policy defined in the <binary_policy_file> - please use the policy_processor that is posted to this - mailing list to create such a binary policy from an XML - policy description - -4. Policy interface: -******************** -The Policy interface is working in "network-byte-order" (big endian). The reason for this -is that policy files/management should be portable and independent of the platforms. - -Our policy interface enables managers to create a single binary policy file in a trusted -environment and distributed it to multiple systems for enforcement. - -5. Booting with a binary policy: -******************************** -The grub configuration file can be adapted to boot the hypervisor with an -already active policy. To do this, a binary policy file - this can be -the same file as used by the policy_tool - should be placed into the boot -partition. The following entry from the grub configuration file shows how -a binary policy can be added to the system during boot time. Note that the -binary policy must be of the same type that the hypervisor was compiled -for. The policy module line should also only be added as the last module -line if XEN was compiled with the access control module (ACM). - -title XEN0 3.0 Devel - kernel /xen.gz dom0_mem=400000 - module /vmlinuz-2.6.12-xen0 root=/dev/hda2 ro console=tty0 - module /initrd-2.6.12-xen0.img - module /xen_sample_policy.bin - - -====================end-of file======================================= diff -r 99914b54f7bf -r 81576d3d1ca8 linux-2.6-xen-sparse/drivers/xen/blkback/control.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/control.c Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,61 +0,0 @@ -/****************************************************************************** - * arch/xen/drivers/blkif/backend/control.c - * - * Routines for interfacing with the control plane. - * - * Copyright (c) 2004, Keir Fraser - */ - -#include "common.h" - -static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) -{ - DPRINTK("Received blkif backend message, subtype=%d\n", msg->subtype); - - switch ( msg->subtype ) - { - case CMSG_BLKIF_BE_CREATE: - blkif_create((blkif_be_create_t *)&msg->msg[0]); - break; - case CMSG_BLKIF_BE_DESTROY: - blkif_destroy((blkif_be_destroy_t *)&msg->msg[0]); - break; - case CMSG_BLKIF_BE_CONNECT: - blkif_connect((blkif_be_connect_t *)&msg->msg[0]); - break; - case CMSG_BLKIF_BE_DISCONNECT: - if ( !blkif_disconnect((blkif_be_disconnect_t *)&msg->msg[0],msg->id) ) - return; /* Sending the response is deferred until later. */ - break; - case CMSG_BLKIF_BE_VBD_CREATE: - vbd_create((blkif_be_vbd_create_t *)&msg->msg[0]); - break; - case CMSG_BLKIF_BE_VBD_DESTROY: - vbd_destroy((blkif_be_vbd_destroy_t *)&msg->msg[0]); - break; - default: - DPRINTK("Parse error while reading message subtype %d, len %d\n", - msg->subtype, msg->length); - msg->length = 0; - break; - } - - ctrl_if_send_response(msg); -} - -void blkif_ctrlif_init(void) -{ - ctrl_msg_t cmsg; - blkif_be_driver_status_t st; - - (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); - - /* Send a driver-UP notification to the domain controller. */ - cmsg.type = CMSG_BLKIF_BE; - cmsg.subtype = CMSG_BLKIF_BE_DRIVER_STATUS; - cmsg.length = sizeof(blkif_be_driver_status_t); - st.status = BLKIF_DRIVER_STATUS_UP; - memcpy(cmsg.msg, &st, sizeof(st)); - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); -} diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/Makefile --- a/tools/misc/policyprocessor/Makefile Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,42 +0,0 @@ -XEN_ROOT = ../../.. -include $(XEN_ROOT)/tools/Rules.mk - -CFLAGS += -static -CFLAGS += -Wall -CFLAGS += -Werror -CFLAGS += -O3 -CFLAGS += -fno-strict-aliasing -CFLAGS += -I. - -all: build - -build: mk-symlinks - $(MAKE) xml_to_bin - -default: all - -install: all - -xml_to_bin : make_include XmlToBin.java XmlToBinInterface.java SsidsEntry.java SecurityLabel.java myHandler.java - javac XmlToBin.java - -make_include : c2j_include - ./c2j_include - -c2j_include: c2j_include.c - $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< - -clean: - rm -rf *.class xen c2j_include policy_version.java *.bin - - -LINUX_ROOT := $(XEN_ROOT)/linux-2.6-xen-sparse -mk-symlinks: - [ -e xen/linux ] || mkdir -p xen/linux - [ -e xen/io ] || mkdir -p xen/io - ( cd xen >/dev/null ; \ - ln -sf ../$(XEN_ROOT)/xen/include/public/*.h . ) - ( cd xen/io >/dev/null ; \ - ln -sf ../../$(XEN_ROOT)/xen/include/public/io/*.h . ) - ( cd xen/linux >/dev/null ; \ - ln -sf ../../$(LINUX_ROOT)/include/asm-xen/linux-public/*.h . ) diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/SecurityLabel.java --- a/tools/misc/policyprocessor/SecurityLabel.java Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,34 +0,0 @@ -/** - * (C) Copyright IBM Corp. 2005 - * - * $Id: SecurityLabel.java,v 1.2 2005/06/17 20:00:04 rvaldez Exp $ - * - * Author: Ray Valdez - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * SecurityLabel Class. - * - * <p> - * - * Keeps track of types. - * - * <p> - * - * - */ -import java.util.*; -public class SecurityLabel -{ - Vector ids; - Vector vlans; - Vector slots; - Vector steTypes; - int steSsidPosition; - Vector chwIDs; - Vector chwTypes; - int chwSsidPosition; -} diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/SecurityPolicySpec.xsd --- a/tools/misc/policyprocessor/SecurityPolicySpec.xsd Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,115 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Author: Ray Valdez, rvaldez@xxxxxxxxxx --> -<!-- xml schema definition for xen xml policies --> -<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" -targetNamespace="http://www.ibm.com" -xmlns="http://www.ibm.com" -elementFormDefault="qualified"> - -<xsd:element name="TE" type="xsd:string" /> -<xsd:element name="ChWall" type="xsd:string" /> - -<xsd:element name="Definition"> - <xsd:complexType> - <xsd:sequence> - - <!-- simple type enforcement --> - <xsd:element name="Types" minOccurs ="0" maxOccurs="1"> - <xsd:complexType> - <xsd:sequence> - <xsd:element ref="TE" minOccurs ="1" maxOccurs ="unbounded"/> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - - <!-- chinese wall --> - <!-- type definition --> - <xsd:element name="ChWallTypes" minOccurs ="0" maxOccurs="1"> - <xsd:complexType> - <xsd:sequence> - <xsd:element ref="ChWall" minOccurs ="1" maxOccurs ="unbounded"/> - - </xsd:sequence> - </xsd:complexType> - </xsd:element> - - <!-- conflict set --> - <xsd:element name="ConflictSet" minOccurs ="0" maxOccurs="unbounded"> - <xsd:complexType> - <xsd:sequence> - <xsd:element ref="ChWall" minOccurs ="2" maxOccurs ="unbounded"/> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - - </xsd:sequence> - </xsd:complexType> -</xsd:element> - -<xsd:element name="Policy"> - <xsd:complexType> - <xsd:sequence> - - <xsd:element name="PolicyHeader"> - <xsd:complexType> - <xsd:all> - <xsd:element name = "Name" type="xsd:string"/> - <xsd:element name = "DateTime" type="xsd:dateTime"/> - <xsd:element name = "Tag" minOccurs ="1" maxOccurs ="1" type="xsd:string"/> - <xsd:element name = "TypeDefinition"> - <xsd:complexType> - <xsd:all> - <xsd:element name = "url" type="xsd:string"/> - <xsd:element name = "hash" minOccurs ="0" maxOccurs ="1" type="xsd:string"/> - </xsd:all> - </xsd:complexType> - </xsd:element> - - </xsd:all> - </xsd:complexType> - </xsd:element> - - <xsd:element name="VM" minOccurs ="1" maxOccurs="unbounded"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="id" type="xsd:integer"/> - <xsd:element ref="TE" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element ref="ChWall" minOccurs ="0" maxOccurs="unbounded"/> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - - <xsd:element name="Vlan" minOccurs ="0" maxOccurs="unbounded"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="vid" type="xsd:integer"/> - <xsd:element ref="TE" minOccurs="1" maxOccurs="unbounded" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - - <xsd:element name="Slot" minOccurs ="0" maxOccurs="unbounded"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="bus" type="xsd:integer"/> - <xsd:element name="slot" type="xsd:integer"/> - <xsd:element ref="TE" minOccurs="1" maxOccurs="unbounded" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - - - </xsd:sequence> - </xsd:complexType> -</xsd:element> - -<!-- root element --> -<xsd:element name="SecurityPolicySpec"> - <xsd:complexType> - <xsd:choice> - <xsd:element ref="Definition" minOccurs ="1" maxOccurs="unbounded"/> - <xsd:element ref="Policy" minOccurs ="1" maxOccurs="unbounded"/> - </xsd:choice> - </xsd:complexType> -</xsd:element> -</xsd:schema> diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/SsidsEntry.java --- a/tools/misc/policyprocessor/SsidsEntry.java Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,29 +0,0 @@ -/** - * (C) Copyright IBM Corp. 2005 - * - * $Id: SsidsEntry.java,v 1.2 2005/06/17 20:02:40 rvaldez Exp $ - * - * Author: Ray Valdez - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * SsidsEntry Class. - * <p> - * - * Holds ssid information. - * - * <p> - * - * - */ -public class SsidsEntry - { - int id; /* used for partition and vlan */ - int bus; /* used for slots */ - int slot; - int ste = 0xffffffff; - int chw = 0xffffffff; - } diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/XmlToBin.java --- a/tools/misc/policyprocessor/XmlToBin.java Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,1570 +0,0 @@ -/** - * (C) Copyright IBM Corp. 2005 - * - * $Id: XmlToBin.java,v 1.3 2005/06/20 21:07:37 rvaldez Exp $ - * - * Author: Ray Valdez - * - * Contributors: - * Reiner Sailer - adjust type-lengths - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * XmlToBin Class. - * <p> - * - * Translates a xml representation of a SHYPE policy into a binary - * format. The class processes an xml policy file based on elment tags - * defined in a schema definition files: SecurityPolicySpec.xsd. - * - * XmlToBin Command line Options: - * - * -i inputFile: name of policyfile (.xml) - * -o outputFile: name of binary policy file (Big Endian) - * -xssid SsidFile: xen ssids to types text file - * -xssidconf SsidConf: xen conflict ssids to types text file - * -debug turn on debug messages - * -help help. This printout - * - * <p> - * - * - */ -import java.util.*; -import java.io.*; -import java.io.IOException; -import java.io.FileNotFoundException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.Attr; -import org.w3c.dom.NodeList; -import org.w3c.dom.NamedNodeMap; -import org.xml.sax.*; -import javax.xml.parsers.*; -import org.xml.sax.helpers.*; - -public class XmlToBin - implements XmlToBinInterface -{ - class SlotInfo { - String bus; - String slot; - } - - boolean LittleEndian = false; - boolean debug = false; - - static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; - - static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; - - public static void printUsage() - { - System.out.println("XmlToBin Command line Options: "); - System.out.println("\t-i\t\tinputFile:\tname of policyfile (.xml)"); - System.out.println("\t-o\t\toutputFile:\tname of binary policy file (Big Endian)"); - System.out.println("\t-xssid\t\tSsidFile:\tXen ssids to named types text file"); - System.out.println("\t-xssidconf\tSsidConfFile:\tXen conflict ssids to named types text file"); - System.out.println("\t-debug\t\t\t\tturn on debug messages"); - System.out.println("\t-help\t\t\t\thelp. This printout"); - return; - } - - public void printDebug(String message) - { - if (debug) - System.out.println(message); - } - - public void writeBinPolicy(byte[] binPolicy, String outputFileName) - throws Exception - { - if (debug) - printHex(binPolicy,binPolicy.length); - - DataOutputStream writeObj = new DataOutputStream( - new FileOutputStream(outputFileName)); - - writeObj.write(binPolicy); - writeObj.flush(); - writeObj.close(); - System.out.println(" wBP:: wrote outputfile: " + outputFileName); - - return; - } - - public void writeXenTypeVectorFile(Vector list, String outputFileName) - throws Exception - { - PrintWriter out; - - if (0 == list.size()) - { - printDebug(" wSTF : size of input is zero when writing :" + outputFileName); - return; - } - out = new PrintWriter( - new BufferedWriter( - new FileWriter(outputFileName))); - - - for (int i = 0; i < list.size(); i++) - { - Vector ee = (Vector) list.elementAt(i); - out.println(i + " " +ee.toString()); - } - out.close(); - - return; - } - - public void writeXenTypeFile(Vector list, String outputFileName, boolean slabel) - throws Exception - { - Vector entry; - String strTypes = ""; - SecurityLabel ee; - PrintWriter out; - - if (0 == list.size()) - { - printDebug(" wSTF : size of input is zero when writing :" + outputFileName); - return; - } - out = new PrintWriter( - new BufferedWriter( - new FileWriter(outputFileName))); - - for (int i = 0; i < list.size(); i++) - { - ee = (SecurityLabel) list.elementAt(i); - - if (slabel) - { - entry = ee.steTypes; - } else { - - entry = ee.chwTypes; - } - if (null == entry) continue; - - Enumeration e = entry.elements(); - while (e.hasMoreElements()) - { - String typeName = (String) e.nextElement(); - strTypes = strTypes + " " + typeName; - } - printDebug(" WXTF:: ssid : "+i +" :"+strTypes); - out.println(i +" "+strTypes); - strTypes = ""; - } - out.close(); - - return; - } - - public void setDebug(boolean value) - { - debug=value; - } - - public void setEndian(boolean value) - { - LittleEndian = value; - } - - public byte[] generateVlanSsids(Vector bagOfSsids) - throws Exception - { - /** - typedef struct { - u16 vlan; - u16 ssid_ste; - } acm_vlan_entry_t; - **/ - - Hashtable vlanSsid = new Hashtable(); - printDebug(" gVS::Size of bagOfSsids: "+ bagOfSsids.size()); - - /* Get the number of partitions */ - for (int i = 0; i < bagOfSsids.size(); i++) - { - SecurityLabel entry = (SecurityLabel) bagOfSsids.elementAt(i); - - if (null == entry.vlans) - continue; - - Enumeration e = entry.vlans.elements(); - while (e.hasMoreElements()) - { - String id = (String) e.nextElement(); - printDebug(" gVS:: vlan: " + id + "has ste ssid: " + entry.steSsidPosition); - if (-1 == entry.steSsidPosition) - continue; - - /* Only use ste for vlan */ - SsidsEntry ssidsObj = new SsidsEntry(); - - ssidsObj.id = Integer.parseInt(id); - ssidsObj.ste = entry.steSsidPosition; - - if (vlanSsid.contains(id)) - printDebug(" gVS:: Error already in the Hash part:" + ssidsObj.id); - else - vlanSsid.put(id, ssidsObj); - printDebug(" gVS:: added part: " + id + "has ste ssid: " + entry.steSsidPosition); - } - } - - /* allocate array */ - int numOfVlan = vlanSsid.size(); - int totalSize = (numOfVlan * vlanEntrySz); - - if (0 == numOfVlan) - { - printDebug(" gVS:: vlan: binary ==> zero"); - return new byte[0]; - } - - byte[] vlanArray = new byte[totalSize]; - - int index = 0; - - Enumeration e = vlanSsid.elements(); - while (e.hasMoreElements()) - { - SsidsEntry entry = (SsidsEntry) e.nextElement(); - printDebug(" gVS:: part: " + entry.id + " ste ssid: " + entry.ste); - - /* Write id */ - writeShortToStream(vlanArray,(short)entry.id,index); - index = index + u16Size; - - /* write ste ssid */ - writeShortToStream(vlanArray,(short) entry.ste,index); - index = index + u16Size; - } - - printDebug(" gVS:: vlan: num of vlans " + numOfVlan); - printDebug(" gVS:: vlan: binary ==> Length "+ vlanArray.length); - - if (debug) - printHex(vlanArray,vlanArray.length); - printDebug("\n"); - - return vlanArray; - } - - public byte[] generateSlotSsids(Vector bagOfSsids) - throws Exception - { - /** - typedef struct { - u16 slot_max; - u16 slot_offset; - } acm_slot_buffer_t; - - typedef struct { - u16 bus; - u16 slot; - u16 ssid_ste; - } acm_slot_entry_t; - **/ - Hashtable slotSsid = new Hashtable(); - printDebug(" gSS::Size of bagOfSsids: "+ bagOfSsids.size()); - - /* Find the number of VMs */ - for (int i = 0; i < bagOfSsids.size(); i++) - { - SecurityLabel entry = (SecurityLabel) bagOfSsids.elementAt(i); - - if (null == entry.slots) - continue; - - Enumeration e = entry.slots.elements(); - while (e.hasMoreElements()) - { - SlotInfo item = (SlotInfo) e.nextElement(); - printDebug(" gSS:: bus slot: " + item.bus + " "+ item.slot + " " + entry.steSsidPosition); - if (-1 == entry.steSsidPosition) - continue; - - SsidsEntry ssidsObj = new SsidsEntry(); - - String id = item.bus +" "+item.slot; - ssidsObj.bus = Integer.parseInt(item.bus); - ssidsObj.slot = Integer.parseInt(item.slot); - /* set ste ssid */ - ssidsObj.ste = entry.steSsidPosition; - - if (slotSsid.contains(id)) - printDebug(" gSS:: Error already in the Hash part:" + id); - else - slotSsid.put(id, ssidsObj); - - printDebug(" gSS:: added slot: " + id + "has ste ssid: " + entry.steSsidPosition); - } - } - - /* allocate array */ - int numOfSlot = slotSsid.size(); - - if (0 == numOfSlot) - { - printDebug(" gVS:: slot: binary ==> zero"); - return new byte[0]; - } - - int totalSize = (numOfSlot * slotEntrySz); - - byte[] slotArray = new byte[totalSize]; - - int index = 0; - - Enumeration e = slotSsid.elements(); - while (e.hasMoreElements()) - { - SsidsEntry entry = (SsidsEntry) e.nextElement(); - System.out.println(" gSS:: bus slot: " + entry.bus + " " + entry.slot + " ste ssid: " + entry.ste); - - /* Write bus */ - writeShortToStream(slotArray,(short)entry.bus,index); - index = index + u16Size; - - /* Write slot */ - writeShortToStream(slotArray,(short)entry.slot,index); - index = index + u16Size; - - /* Write ste ssid */ - writeShortToStream(slotArray,(short) entry.ste,index); - index = index + u16Size; - - } - - printDebug(" gSS:: slot: num of vlans " + numOfSlot); - printDebug(" gSS:: slot: binary ==> Length "+ slotArray.length); - - if (debug) - printHex(slotArray,slotArray.length); - printDebug("\n"); - - return slotArray; - - } - - public byte[] generatePartSsids(Vector bagOfSsids, Vector bagOfChwSsids) - throws Exception - { - /** - typedef struct { - u16 id; - u16 ssid_ste; - u16 ssid_chwall; - } acm_partition_entry_t; - - **/ - Hashtable partSsid = new Hashtable(); - printDebug(" gPS::Size of bagOfSsids: "+ bagOfSsids.size()); - - /* Find the number of VMs */ - for (int i = 0; i < bagOfSsids.size(); i++) - { - SecurityLabel entry = (SecurityLabel) bagOfSsids.elementAt(i); - - if (null == entry.ids) - continue; - - Enumeration e = entry.ids.elements(); - while (e.hasMoreElements()) - { - String id = (String) e.nextElement(); - printDebug(" gPS:: part: " + id + "has ste ssid: " + entry.steSsidPosition); - if (-1 == entry.steSsidPosition) - continue; - - SsidsEntry ssidsObj = new SsidsEntry(); - - ssidsObj.id = Integer.parseInt(id); - ssidsObj.ste = entry.steSsidPosition; - - if (partSsid.contains(id)) - printDebug(" gPS:: Error already in the Hash part:" + ssidsObj.id); - else - partSsid.put(id, ssidsObj); - printDebug(" gPS:: added part: " + id + "has ste ssid: " + entry.steSsidPosition); - } - - } - - for (int i = 0; i < bagOfChwSsids.size(); i++) - { - SecurityLabel entry = (SecurityLabel) bagOfChwSsids.elementAt(i); - - Enumeration e = entry.chwIDs.elements(); - while (e.hasMoreElements()) - { - String id = (String) e.nextElement(); - printDebug(" gPS:: part: " + id + "has chw ssid: " + entry.chwSsidPosition); - if (partSsid.containsKey(id)) - { - SsidsEntry item = (SsidsEntry) partSsid.get(id); - item.chw = entry.chwSsidPosition; - printDebug(" gPS:: added :" + item.id +" chw: " + item.chw); - } - else - { - printDebug(" gPS:: creating :" + id +" chw: " + entry.chwSsidPosition); - SsidsEntry ssidsObj = new SsidsEntry(); - ssidsObj.id = Integer.parseInt(id); - ssidsObj.chw = entry.chwSsidPosition; - partSsid.put(id, ssidsObj); - - } - } - } - - /* Allocate array */ - int numOfPar = partSsid.size(); - int totalSize = (numOfPar * partitionEntrySz); - - if (0 == numOfPar) - { - printDebug(" gPS:: part: binary ==> zero"); - return new byte[0]; - } - - byte[] partArray = new byte[totalSize]; - - int index = 0; - - Enumeration e = partSsid.elements(); - while (e.hasMoreElements()) - { - SsidsEntry entry = (SsidsEntry) e.nextElement(); - printDebug(" gPS:: part: " + entry.id + " ste ssid: " + entry.ste + " chw ssid: "+ entry.chw); - - /* Write id */ - writeShortToStream(partArray,(short)entry.id,index); - index = index + u16Size; - - /* Write ste ssid */ - writeShortToStream(partArray,(short) entry.ste,index); - index = index + u16Size; - - /* Write chw ssid */ - writeShortToStream(partArray,(short) entry.chw,index); - index = index + u16Size; - } - - printDebug(" gPS:: part: num of partitions " + numOfPar); - printDebug(" gPS:: part: binary ==> Length " + partArray.length); - - if (debug) - printHex(partArray,partArray.length); - printDebug("\n"); - - return partArray; - } - - public byte[] GenBinaryPolicyBuffer(byte[] chwPolicy, byte[] stePolicy, byte [] partMap, byte[] vlanMap, byte[] slotMap) - { - byte[] binBuffer; - short chwSize =0; - short steSize =0; - int index = 0; - - /* Builds data structure acm_policy_buffer_t */ - /* Get number of colorTypes */ - if (null != chwPolicy) - chwSize = (short) chwPolicy.length; - - if (null != stePolicy) - steSize = (short) stePolicy.length; - - int totalDataSize = chwSize + steSize + resourceOffsetSz + 3 *(2 * u16Size); - - /* Add vlan and slot */ - totalDataSize = totalDataSize +partMap.length + vlanMap.length + slotMap.length; - binBuffer = new byte[binaryBufferHeaderSz +totalDataSize]; - - - try { - index = 0; - /* fill in General Policy Version */ - writeIntToStream(binBuffer, ACM_POLICY_VERSION, index); - index += u32Size; - - /* Write magic */ - writeIntToStream(binBuffer, ACM_MAGIC, index); - index += u32Size; - - /* write len */ - writeIntToStream(binBuffer, binBuffer.length, index); - index += u32Size; - - } catch (IOException ee) { - System.out.println(" GBPB:: got exception : " + ee); - return null; - } - - int offset, address; - address = index; - - if (null != partMap) - offset = binaryBufferHeaderSz + resourceOffsetSz; - else - offset = binaryBufferHeaderSz; - - try { - int skip = 0; - - /* init with NULL policy setting */ - writeIntToStream(binBuffer, ACM_NULL_POLICY, index); - writeIntToStream(binBuffer, 0, index + u32Size); - writeIntToStream(binBuffer, ACM_NULL_POLICY, index + 2*u32Size); - writeIntToStream(binBuffer, 0, index + 3*u32Size); - - index = address; - if (null != chwPolicy) { - - /* Write policy name */ - writeIntToStream(binBuffer, ACM_CHINESE_WALL_POLICY, index); - index += u32Size; - - /* Write offset */ - writeIntToStream(binBuffer, offset, index); - index += u32Size; - - /* Write payload. No need increment index */ - address = offset; - System.arraycopy(chwPolicy, 0, binBuffer,address, chwPolicy.length); - address = address + chwPolicy.length; - } else - skip += 2*u32Size; - - if (null != stePolicy) - { - /* Write policy name */ - writeIntToStream(binBuffer, ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, index); - index += u32Size; - - /* Write offset */ - writeIntToStream(binBuffer, address, index); - index += u32Size; - - /* Copy array */ - System.arraycopy(stePolicy, 0, binBuffer,address, stePolicy.length); - /* Update address */ - address = address + stePolicy.length; - } else - skip += 2*u32Size; - - /* Skip writing policy name and offset for each null policy*/ - index += skip; - - int size; - /* Assumes that you will always have a partition defined in policy */ - if ( 0 < partMap.length) { - writeIntToStream(binBuffer, address, index); - index = address; - - /* Compute num of VMs */ - size = partMap.length / (3 * u16Size); - - writeShortToStream(binBuffer, (short)size,index); - index = index + u16Size; - - /* part, vlan and slot: each one consists of two entries */ - offset = 3 * (2 * u16Size); - writeShortToStream(binBuffer, (short) offset,index); - - /* Write partition array at offset */ - System.arraycopy(partMap, 0, binBuffer,(offset + address), partMap.length); - index = index + u16Size; - offset = offset + partMap.length; - } - - if ( 0 < vlanMap.length) { - size = vlanMap.length / (2 * u16Size); - writeShortToStream(binBuffer, (short) size,index); - index = index + u16Size; - - writeShortToStream(binBuffer, (short) offset,index); - index = index + u16Size; - System.arraycopy(vlanMap, 0, binBuffer,(offset + address), vlanMap.length); - } else { - /* Write vlan max */ - writeShortToStream(binBuffer, (short) 0,index); - index = index + u16Size; - - /* Write vlan offset */ - writeShortToStream(binBuffer, (short) 0,index); - index = index + u16Size; - } - - offset = offset + vlanMap.length; - if ( 0 < slotMap.length) { - size = slotMap.length / (3 * u16Size); - writeShortToStream(binBuffer, (short) size,index); - index = index + u16Size; - - writeShortToStream(binBuffer, (short) offset,index); - index = index + u16Size; - System.arraycopy(slotMap, 0, binBuffer,(offset + address), slotMap.length); - } - } catch (IOException ee) { - System.out.println(" GBPB:: got exception : " + ee); - return null; - } - - printDebug(" GBP:: Binary Policy ==> length " + binBuffer.length); - if (debug) - printHex(binBuffer,binBuffer.length); - - return binBuffer; - } - - public byte[] generateChwBuffer(Vector Ssids, Vector ConflictSsids, Vector ColorTypes) - { - byte[] chwBuffer; - int index = 0; - int position = 0; - - /* Get number of rTypes */ - int maxTypes = ColorTypes.size(); - - /* Get number of SSids entry */ - int maxSsids = Ssids.size(); - - /* Get number of conflict sets */ - int maxConflict = ConflictSsids.size(); - - - if (maxTypes * maxSsids == 0) - return null; - /* - data structure acm_chwall_policy_buffer - se XmlToBinInterface.java - */ - int totalBytes = chwHeaderSize + u16Size *(maxTypes * (maxSsids + maxConflict)); - - chwBuffer = new byte[ totalBytes ]; - int address = chwHeaderSize + (u16Size * maxTypes * maxSsids ); - - printDebug(" gCB:: chwall totalbytes : "+totalBytes); - - try { - index = 0; - /* fill in General Policy Version */ - writeIntToStream(chwBuffer, ACM_CHWALL_VERSION, index); - index += u32Size; - - writeIntToStream(chwBuffer, ACM_CHINESE_WALL_POLICY, index); - index += u32Size; - - writeIntToStream(chwBuffer, maxTypes, index); - index += u32Size; - - writeIntToStream(chwBuffer, maxSsids, index); - index += u32Size; - - writeIntToStream(chwBuffer, maxConflict, index); - index += u32Size; - - /* Write chwall_ssid_offset */ - writeIntToStream(chwBuffer, chwHeaderSize, index); - index += u32Size; - - /* Write chwall_conflict_sets_offset */ - writeIntToStream(chwBuffer, address, index); - index += u32Size; - - /* Write chwall_running_types_offset */ - writeIntToStream(chwBuffer, 0, index); - index += u32Size; - - /* Write chwall_conflict_aggregate_offset */ - writeIntToStream(chwBuffer, 0, index); - index += u32Size; - - } catch (IOException ee) { - System.out.println(" gCB:: got exception : " + ee); - return null; - } - int markPos = 0; - - /* Create the SSids entry */ - for (int i = 0; i < maxSsids; i++) - { - SecurityLabel ssidEntry = (SecurityLabel) Ssids.elementAt(i); - /* Get chwall types */ - ssidEntry.chwSsidPosition = i; - Enumeration e = ssidEntry.chwTypes.elements(); - while (e.hasMoreElements()) - { - String typeName = (String) e.nextElement(); - printDebug(" gCB:: Ssid "+ i+ ": has type : " + typeName); - position = ColorTypes.indexOf(typeName); - - if (position < 0) - { - System.out.println (" gCB:: Error type : " + typeName + " not found in ColorTypes"); - return null; - } - printDebug(" GCB:: type : " + typeName + " found in ColorTypes at position: " + position); - markPos = ((i * maxTypes + position) * u16Size) + index; - - try { - writeShortToStream(chwBuffer,markSymbol,markPos); - } catch (IOException ee) { - System.out.println(" gCB:: got exception : "); - return null; - } - } - } - - if (debug) - printHex(chwBuffer,chwBuffer.length); - - /* Add conflict set */ - index = address; - for (int i = 0; i < maxConflict; i++) - { - /* Get ste types */ - Vector entry = (Vector) ConflictSsids.elementAt(i); - Enumeration e = entry.elements(); - while (e.hasMoreElements()) - { - String typeName = (String) e.nextElement(); - printDebug (" GCB:: conflict Ssid "+ i+ ": has type : " + typeName); - position = ColorTypes.indexOf(typeName); - - if (position < 0) - { - System.out.println (" GCB:: Error type : " + typeName + " not found in ColorTypes"); - return null; - } - printDebug(" GCB:: type : " + typeName + " found in ColorTypes at position: " + position); - markPos = ((i * maxTypes + position) * u16Size) + index; - - try { - writeShortToStream(chwBuffer,markSymbol,markPos); - } catch (IOException ee) { - System.out.println(" GCB:: got exception : "); - return null; - } - } - - } - printDebug(" gSB:: chw binary ==> Length " + chwBuffer.length); - if (debug) - printHex(chwBuffer,chwBuffer.length); - printDebug("\n"); - - return chwBuffer; - } - -/********************************************************************** - Generate byte representation of policy using type information - <p> - @param Ssids Vector - @param ColorTypes Vector - <p> - @return bytes represenation of simple type enforcement policy -**********************************************************************/ - public byte[] generateSteBuffer(Vector Ssids, Vector ColorTypes) - { - byte[] steBuffer; - int index = 0; - int position = 0; - - /* Get number of colorTypes */ - int numColorTypes = ColorTypes.size(); - - /* Get number of SSids entry */ - int numSsids = Ssids.size(); - - if (numColorTypes * numSsids == 0) - return null; - - /* data structure: acm_ste_policy_buffer - * see XmlToBinInterface.java - * total bytes: steHeaderSize * 2B + colorTypes(size) * Ssids(size) - * - */ - steBuffer = new byte[ steHeaderSize + (numColorTypes * numSsids) * 2]; - - try { - - index = 0; - writeIntToStream(steBuffer, ACM_STE_VERSION, index); - index += u32Size; - - writeIntToStream(steBuffer, ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, index); - index += u32Size; - - writeIntToStream(steBuffer, numColorTypes, index); - index += u32Size; - - writeIntToStream(steBuffer, numSsids, index); - index += u32Size; - - writeIntToStream(steBuffer, steHeaderSize, index); - index += u32Size; - - - } catch (IOException ee) { - System.out.println(" gSB:: got exception : " + ee); - return null; - } - int markPos = 0; - for (int i = 0; i < numSsids; i++) - { - - SecurityLabel ssidEntry = (SecurityLabel) Ssids.elementAt(i); - ssidEntry.steSsidPosition = i; - /* Get ste types */ - Enumeration e = ssidEntry.steTypes.elements(); - while (e.hasMoreElements()) - { - String typeName = (String) e.nextElement(); - printDebug (" gSB:: Ssid "+ i+ ": has type : " + typeName); - position = ColorTypes.indexOf(typeName); - - if (position < 0) - { - printDebug(" gSB:: Error type : " + typeName + " not found in ColorTypes"); - return null; - } - printDebug(" gSB:: type : " + typeName + " found in ColorTypes at position: " + position); - markPos = ((i * numColorTypes + position) * u16Size) + index; - - try { - writeShortToStream(steBuffer,markSymbol,markPos); - } catch (IOException ee) - { - System.out.println(" gSB:: got exception : "); - return null; - } - } - - } - - printDebug(" gSB:: ste binary ==> Length " + steBuffer.length); - if (debug) - printHex(steBuffer,steBuffer.length); - printDebug("\n"); - - return steBuffer; - } - - public static void printHex(byte [] dataArray, int length) - { - char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - int hexIndex; - int value; - int arraylength; - - arraylength = length; - - if (dataArray == null) - { - System.err.print("printHex: input byte array is null"); - } - - if (length > dataArray.length || length < 0) - arraylength = dataArray.length; - - System.out.print("\n\t"); - - int i; - for(i = 0; i < arraylength; ) - { - value = dataArray[i] & 0xFF; - hexIndex = (value >>> 4); - System.out.print(hexChars[hexIndex]); - hexIndex = (value & 0x0F); - System.out.print(hexChars[hexIndex]); - - i++; - /* if done, print a final newline */ - if (i == arraylength) { - if (arraylength < dataArray.length) { - System.out.print("..."); - } - System.out.println(); - } - else if ((i % 24) == 0) { - System.out.print("\n\t"); - } - else if ((i % 4) == 0) { - System.out.print(" "); - } - } - - return; - } - - - private void writeShortToStream(byte[] stream, short value, int index) - throws IOException - { - int littleEndian = 0; - int byteVal; - - if (index + 2 > stream.length) - { - throw new IOException("Writing beyond stream length: " + - stream.length + " writing at locations from: " + index + " to " + (index + 4)); - } - - if (!LittleEndian) - { - - byteVal = value >> 8; - stream[index ] = (byte) byteVal; - - byteVal = value; - stream[index + 1] = (byte) byteVal; - } else { - stream[index] = (byte) ((value & 0x00ff) ); - stream[index + 1] = (byte) ((value & 0xff00) >> 8); - } - return; - } - - private void writeIntToStream(byte[] stream, int value, int index) - throws IOException - { - int littleEndian = 0; - int byteVal; - - if (4 > stream.length) - { - throw new IOException("writeIntToStream: stream length less than 4 bytes " + - stream.length); - } - - /* Do not Write beyond range */ - if (index + 4 > stream.length) - { - throw new IOException("writeIntToStream: writing beyond stream length: " + - stream.length + " writing at locations from: " + index + " to " + (index + 4)); - } - if (!LittleEndian) - { - byteVal = value >>> 24; - stream[index] = (byte) byteVal; - - byteVal = value >> 16; - stream[index + 1] = (byte) byteVal; - - byteVal = value >> 8; - stream[index + 2] = (byte) byteVal; - - byteVal = value; - stream[index + 3] = (byte) byteVal; - } else { - stream[index] = (byte) value; - stream[index + 1] = (byte) ((value & 0x0000ff00) >> 8); - stream[index + 2] = (byte) ((value & 0x00ff0000) >> 16); - stream[index + 3] = (byte) ( value >>> 24); - } - return; - } - - public Document getDomTree(String xmlFileName) - throws Exception, SAXException, ParserConfigurationException - { - javax.xml.parsers.DocumentBuilderFactory dbf = - javax.xml.parsers.DocumentBuilderFactory.newInstance(); - - /* Turn on namespace aware and validation */ - dbf.setNamespaceAware(true); - dbf.setValidating(true); - dbf.setAttribute(JAXP_SCHEMA_LANGUAGE,W3C_XML_SCHEMA); - - /* Checks that the document is well-formed */ - javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder(); - - myHandler errHandler= new myHandler(); - db.setErrorHandler(errHandler); - Document doc = db.parse(xmlFileName); - - /* Checks for validation errors */ - if (errHandler.isValid) - printDebug(" gDT:: Xml file: " + xmlFileName + " is valid"); - else - throw new Exception("Xml file: " + xmlFileName + " is NOT valid"); - - return doc; - } - - public void processDomTree( - Document doc, - Vector bagOfSsids, - Vector bagOfTypes, - Vector bagOfChwSsids, - Vector bagOfChwTypes, - Vector bagOfConflictSsids) - throws Exception, SAXException, ParserConfigurationException - { - boolean found; - - /* print the root Element */ - Element root = doc.getDocumentElement(); - printDebug ("\n pDT:: Document Element: Name = " + root.getNodeName() + ",Value = " + root.getNodeValue()); - - /* Go through the list of the root Element's Attributes */ - NamedNodeMap nnm = root.getAttributes(); - printDebug (" pDT:: # of Attributes: " + nnm.getLength()); - for (int i = 0; i < nnm.getLength(); i++) - { - Node n = nnm.item (i); - printDebug (" pDT:: Attribute: Name = " + n.getNodeName() + ", Value = " - + n.getNodeValue()); - } - - /* Retrieve the policy definition */ - NodeList elementList = root.getElementsByTagName ("url"); - String definitionFileName = elementList.item(0).getFirstChild().getNodeValue(); - - String definitionHash = null; - - /* Note that SecurityPolicySpec.xsd allows for 0 hash value! */ - elementList = root.getElementsByTagName ("hash"); - if (0 != elementList.getLength()) - definitionHash = elementList.item(0).getFirstChild().getNodeValue(); - - Document definitionDoc = pGetDomDefinition(definitionFileName,definitionHash); - pGetTypes(definitionDoc,bagOfTypes, bagOfChwTypes, bagOfConflictSsids); - - - /* Get VM security information */ - elementList = root.getElementsByTagName ("VM"); - printDebug ("\n pDT:: partition length of NodeList:" + elementList.getLength()); - /* Add default Ssid to Ste and Chw bags */ - SecurityLabel defEntry = new SecurityLabel(); - - defEntry.chwTypes = new Vector(); - defEntry.steTypes = new Vector(); - defEntry.chwIDs = new Vector(); - defEntry.ids = new Vector(); - - defEntry.steSsidPosition =0; - defEntry.chwSsidPosition =0; - bagOfChwSsids.add(defEntry); - bagOfSsids.add(defEntry); - - for (int x = 0; x < elementList.getLength(); x++) - { - found = false; - - Node node = elementList.item (x); - - if (node.getNodeType() == Node.ELEMENT_NODE) - { - printDebug (" pDT:: child: " + x + " is an element node" ); - Element e1 = (Element) node; - - /* Get id */ - NodeList elist = e1.getElementsByTagName ("id"); - String idStr = elist.item(0).getFirstChild().getNodeValue(); - printDebug (" pDT:: id:" + idStr); - - /* Get TE */ - Vector colorTypes = new Vector(); - pConflictEntries(e1, "TE", bagOfTypes, colorTypes); - - Enumeration e = bagOfSsids.elements(); - while (e.hasMoreElements()) - { - SecurityLabel elem = (SecurityLabel) e.nextElement(); - if ( elem.steTypes.size() == colorTypes.size() && elem.steTypes.containsAll(colorTypes)) - { - found = true; - elem.ids.add(idStr); - } - - } - if (!found && (0 < colorTypes.size())) - { - SecurityLabel entry = new SecurityLabel(); - entry.steTypes = colorTypes; - entry.ids = new Vector(); - entry.ids.add(idStr); - bagOfSsids.add(entry); - } - - /* Get Chinese wall type */ - Vector chwTypes = new Vector(); - pConflictEntries(e1, "ChWall", bagOfChwTypes, chwTypes); - - found = false; - e = bagOfChwSsids.elements(); - - while (e.hasMoreElements()) - { - SecurityLabel elem = (SecurityLabel) e.nextElement(); - if ( elem.chwTypes.size() == chwTypes.size() && elem.chwTypes.containsAll(chwTypes)) - { - found = true; - elem.chwIDs.add(idStr); - } - - } - - if (!found && (0 < chwTypes.size())) - { - SecurityLabel entry = new SecurityLabel(); - entry.chwTypes = chwTypes; - entry.chwIDs = new Vector(); - entry.chwIDs.add(idStr); - bagOfChwSsids.add(entry); - } - } - } - return; - } - - public Document pGetDomDefinition( - String definitionFileName, - String definitionHash) - throws Exception, SAXException, ParserConfigurationException - { - printDebug("\n pGDD:: definition file name: " + definitionFileName); - printDebug("\n pGDD:: definition file hash: " + definitionHash); - - Document doc = getDomTree(definitionFileName); - return doc; - } - - public void pGetTypes( - Document defDoc, - Vector bagOfTypes, - Vector bagOfChwTypes, - Vector bagOfConflictSsids) - throws Exception - { - - - if (null == defDoc) - throw new Exception(" pGT:: definition file DOM is null "); - - Element root = defDoc.getDocumentElement(); - - /* Get list of TE types */ - NodeList elementList = root.getElementsByTagName ("Types"); - printDebug ("\n pGT:: Types length of NodeList:" + elementList.getLength()); - Element e1 = (Element) elementList.item (0); - pGetEntries(e1,"TE",bagOfTypes); - - /* Get list of Chinese types */ - elementList = root.getElementsByTagName ("ChWallTypes"); - printDebug ("\n pGT:: ChwTypes length of NodeList:" + elementList.getLength()); - if (0 == elementList.getLength()) - { - printDebug ("\n pGT:: ChWallTypes has zero length: :" + elementList.getLength()); - } else { - e1 = (Element) elementList.item (0); - pGetEntries(e1,"ChWall",bagOfChwTypes); - } - printDebug (" pGT:: Total number of unique chw types: " + bagOfChwTypes.size()); - - /* Get Chinese type conflict sets */ - elementList = root.getElementsByTagName ("ConflictSet"); - printDebug ("\n pGT:: Conflict sets length of NodeList:" + elementList.getLength()); - for (int x = 0; x < elementList.getLength(); x++) - { - Vector conflictEntry = new Vector(); - e1 = (Element) elementList.item (x); - printDebug ("\n pGT:: Conflict sets : " + x); - - pConflictEntries(e1, "ChWall", bagOfChwTypes, conflictEntry); - - if (conflictEntry.size() > 0) - { - boolean found = false; - Enumeration e = bagOfConflictSsids.elements(); - - while (e.hasMoreElements()) - { - Vector elem = (Vector) e.nextElement(); - if (elem.size() == conflictEntry.size() && elem.containsAll(conflictEntry)) - { - found = true; - } - - } - if (!found) - { - bagOfConflictSsids.add(conflictEntry); - } - } - } - - } - - public void pGetEntries(Element doc, String tag, Vector typeBag) - throws Exception - { - - if (null == doc) - throw new Exception(" pGE:: Element doc is null"); - - if (null == typeBag) - throw new Exception(" pGE:: typeBag is null"); - - NodeList elist = doc.getElementsByTagName (tag); - for (int j = 0; j < elist.getLength(); j++) - { - Node knode = elist.item (j); - Node childNode = knode.getFirstChild(); - String value = childNode.getNodeValue(); - - printDebug (" pGT:: "+ tag +" type: " + value); - - /* Check if value is known */ - if (!typeBag.contains(value)) - typeBag.addElement(value); - } - } - - public void pConflictEntries(Element doc, String tag, Vector typeBag, Vector conflictEntry) - throws Exception - { - - if (null == doc) - throw new Exception(" pGE:: Element doc is null"); - - if (null == typeBag) - throw new Exception(" pGE:: typeBag is null"); - - if (null == conflictEntry) - throw new Exception(" pGE:: typeBag is null"); - - - NodeList elist = doc.getElementsByTagName (tag); - - for (int j = 0; j < elist.getLength(); j++) - { - Node knode = elist.item (j); - Node childNode = knode.getFirstChild(); - String value = childNode.getNodeValue(); - - printDebug (" pGE:: "+ tag +" type: " + value); - - /* Check if value is known */ - if (!typeBag.contains(value)) - throw new Exception(" pCE:: found undefined type set " + value); - - if (!conflictEntry.contains(value)) - conflictEntry.addElement(value); - - } - } - - public void processDomTreeVlanSlot( - Document doc, - Vector bagOfSsids, - Vector bagOfTypes) - throws Exception - { - boolean found; - - printDebug(" pDTVS::Size of bagOfSsids: "+ bagOfSsids.size()); - Element root = doc.getDocumentElement(); - - NodeList elementList = root.getElementsByTagName ("Vlan"); - printDebug("\n pDTVS:: Vlan length of NodeList:" + elementList.getLength()); - - for (int x = 0; x < elementList.getLength(); x++) - { - found = false; - - Node node = elementList.item (x); - - if (node.getNodeType() == Node.ELEMENT_NODE) - { - printDebug(" pDTVS:: child: " + x + " is an element node" ); - Element e1 = (Element) node; - - /* Get vid */ - NodeList elist = e1.getElementsByTagName ("vid"); - String idStr = elist.item(0).getFirstChild().getNodeValue(); - printDebug (" pDTVS:: vid:" + idStr); - - /* Get TE */ - elist = e1.getElementsByTagName ("TE"); - printDebug (" pDTVS:: Total ste types: " + elist.getLength()); - - Vector colorTypes = new Vector(); - for (int j = 0; j < elist.getLength(); j++) - { - Node knode = elist.item (j); - Node childNode = knode.getFirstChild(); - String value = childNode.getNodeValue(); - - printDebug (" pDT:: My color is: " + value); - if (!bagOfTypes.contains(value)) - { - throw new IOException("pDT:: Vlan: " + idStr+ " has unknown type : "+ value); - } - - if (!colorTypes.contains(value)) - colorTypes.addElement(value); - } - Enumeration e = bagOfSsids.elements(); - while (e.hasMoreElements()) - { - SecurityLabel elem = (SecurityLabel) e.nextElement(); - if ( elem.steTypes.size() == colorTypes.size() && elem.steTypes.containsAll(colorTypes)) - { - found = true; - if (null == elem.vlans) - elem.vlans = new Vector(); - elem.vlans.add(idStr); - } - - } - if (!found && (0 < colorTypes.size())) - { - SecurityLabel entry = new SecurityLabel(); - entry.steTypes = colorTypes; - entry.vlans = new Vector(); - entry.vlans.add(idStr); - bagOfSsids.add(entry); - } - - } - } - printDebug(" pDTVS::After slot Size of bagOfSsids: "+ bagOfSsids.size()); - - elementList = root.getElementsByTagName ("Slot"); - printDebug ("\n pDTVS:: Slot length of NodeList:" + elementList.getLength()); - - for (int x = 0; x < elementList.getLength(); x++) - { - found = false; - - Node node = elementList.item (x); - - if (node.getNodeType() == Node.ELEMENT_NODE) - { - printDebug(" pDT:: child: " + x + " is an element node" ); - Element e1 = (Element) node; - - - /* Get slot and bus */ - SlotInfo item = new SlotInfo(); - - NodeList elist = e1.getElementsByTagName ("bus"); - item.bus = elist.item(0).getFirstChild().getNodeValue(); - elist = e1.getElementsByTagName ("slot"); - item.slot = elist.item(0).getFirstChild().getNodeValue(); - printDebug (" pDT:: bus and slot:" + item.bus + " "+ item.slot); - - /* Get TE */ - elist = e1.getElementsByTagName ("TE"); - printDebug (" pDT:: Total ste types: " + elist.getLength()); - - Vector colorTypes = new Vector(); - for (int j = 0; j < elist.getLength(); j++) - { - Node knode = elist.item (j); - Node childNode = knode.getFirstChild(); - String value = childNode.getNodeValue(); - - printDebug (" pDT:: My color is: " + value); - if (!bagOfTypes.contains(value)) - { - throw new IOException("pDT:: bus: " + item.bus + " slot: "+ item.slot + " has unknown type : "+ value); - } - - if (!colorTypes.contains(value)) - colorTypes.addElement(value); - } - - Enumeration e = bagOfSsids.elements(); - while (e.hasMoreElements()) - { - SecurityLabel elem = (SecurityLabel) e.nextElement(); - if ( elem.steTypes.size() == colorTypes.size() && elem.steTypes.containsAll(colorTypes)) - { - found = true; - if (null == elem.slots) - elem.slots = new Vector(); - elem.slots.add(item); - - } - - } - - if (!found && (0 < colorTypes.size())) - { - SecurityLabel entry = new SecurityLabel(); - entry.steTypes = colorTypes; - entry.slots = new Vector(); - entry.slots.add(item); - bagOfSsids.add(entry); - } - - } - } - return; - } - - public static void main (String[] args) - { - String xmlFileName = null; /* policy file */ - String outputFileName = null; /* binary policy file */ - String xenSsidOutputFileName = null; /* outputfile ssid to named types */ - /* outputfile conflicts ssid to named types */ - String xenSsidConfOutputFileName = null; - - XmlToBin genObj = new XmlToBin(); - - policy_version active_policy = new policy_version(); - - if ((active_policy.ACM_POLICY_VERSION != ACM_POLICY_VERSION) || - (active_policy.ACM_CHWALL_VERSION != ACM_CHWALL_VERSION) || - (active_policy.ACM_STE_VERSION != ACM_STE_VERSION)) { - System.out.println("ACM policy versions differ."); - System.out.println("Please verify that data structures are correct"); - System.out.println("and then adjust the version numbers in XmlToBinInterface.java."); - return; - } - - - for (int i = 0 ; i < args.length ; i++) { - - if ( args[i].equals("-help")) { - printUsage(); - System.exit(1); - - } else if ( args[i].equals("-i")) { - i++; - if (i < args.length) { - xmlFileName = args[i]; - } else { - System.out.println("-i argument needs parameter"); - System.exit(1); - } - - } else if ( args[i].equals("-o")) { - i++; - if (i < args.length) { - outputFileName = args[i]; - } else { - System.out.println("-o argument needs parameter"); - System.exit(1); - } - - } else if ( args[i].equals("-xssid")) { - i++; - if (i < args.length) { - xenSsidOutputFileName = args[i]; - } else { - System.out.println("-xssid argument needs parameter"); - System.exit(1); - } - - } else if ( args[i].equals("-xssidconf")) { - i++; - if (i < args.length) { - xenSsidConfOutputFileName = args[i]; - } else { - System.out.println("-xssidconf argument needs parameter"); - System.exit(1); - } - } else if ( args[i].equals("-debug")) { /* turn on debug msg */ - genObj.setDebug(true); - } else { - System.out.println("bad command line argument: " + args[i]); - printUsage(); - System.exit(1); - } - - } - - if (xmlFileName == null) - { - System.out.println("Need to specify input file -i option"); - printUsage(); - System.exit(1); - } - - - try - { - /* Parse and validate */ - Document doc = genObj.getDomTree(xmlFileName); - - /* Vectors to hold sets of types */ - Vector bagOfSsids = new Vector(); - Vector bagOfTypes = new Vector(); - Vector bagOfChwSsids = new Vector(); - Vector bagOfChwTypes = new Vector(); - Vector bagOfConflictSsids = new Vector(); - - Vector vlanMapSsids = new Vector(); - Vector slotMapSsids = new Vector(); - - genObj.processDomTree(doc, bagOfSsids, bagOfTypes, bagOfChwSsids, bagOfChwTypes, bagOfConflictSsids); - - genObj.processDomTreeVlanSlot(doc, bagOfSsids, bagOfTypes); - - /* Get binary representation of policies */ - byte[] stePolicy = genObj.generateSteBuffer(bagOfSsids, bagOfTypes); - byte[] chwPolicy = genObj.generateChwBuffer(bagOfChwSsids, bagOfConflictSsids,bagOfChwTypes); - - byte[] binPolicy = null; - byte[] binaryPartionSsid = null; - byte[] binaryVlanSsid = null; - byte[] binarySlotSsid = null; - - /* Get binary representation of partition to ssid mapping */ - binaryPartionSsid = genObj.generatePartSsids(bagOfSsids,bagOfChwSsids); - - /* Get binary representation of vlan to ssid mapping */ - binaryVlanSsid = genObj.generateVlanSsids(bagOfSsids); - - /* Get binary representation of slot to ssid mapping */ - binarySlotSsid = genObj.generateSlotSsids(bagOfSsids); - - /* Generate binary representation: policy, partition, slot and vlan */ - binPolicy = genObj.GenBinaryPolicyBuffer(chwPolicy,stePolicy, binaryPartionSsid, binaryVlanSsid, binarySlotSsid); - - - /* Write binary policy into file */ - if (null != outputFileName) - { - genObj.writeBinPolicy(binPolicy, outputFileName); - } else { - System.out.println (" No binary policy generated, outputFileName: " + outputFileName); - } - - /* Print total number of types */ - System.out.println (" Total number of unique ste types: " + bagOfTypes.size()); - System.out.println (" Total number of Ssids : " + bagOfSsids.size()); - System.out.println (" Total number of unique chw types: " + bagOfChwTypes.size()); - System.out.println (" Total number of conflict ssids : " + bagOfConflictSsids.size()); - System.out.println (" Total number of chw Ssids : " + bagOfChwSsids.size()); - - if (null != xenSsidOutputFileName) - genObj.writeXenTypeFile(bagOfSsids, xenSsidOutputFileName, true); - - if (null != xenSsidConfOutputFileName) - genObj.writeXenTypeFile(bagOfChwSsids, xenSsidConfOutputFileName, false); - } - catch (Exception e) - { - e.printStackTrace(); - } - } -} diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/XmlToBinInterface.java --- a/tools/misc/policyprocessor/XmlToBinInterface.java Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,138 +0,0 @@ -/** - * (C) Copyright IBM Corp. 2005 - * - * $Id: XmlToBinInterface.java,v 1.3 2005/06/20 21:07:37 rvaldez Exp $ - * - * Author: Ray Valdez - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * XmlToBinInterface Class. - * <p> - * - * Defines constants used by XmToBin. - * - * <p> - * - * policy binary structures - * - * struct acm_policy_buffer { - * u32 policy_version; * ACM_POLICY_VERSION * - * u32 magic; - * u32 len; - * u32 primary_policy_code; - * u32 primary_buffer_offset; - * u32 secondary_policy_code; - * u32 secondary_buffer_offset; - * +u32 resource offset (not used yet in Xen) - * }; - * - * - * struct acm_ste_policy_buffer { - * u32 policy_version; * ACM_STE_VERSION * - * u32 policy_code; - * u32 ste_max_types; - * u32 ste_max_ssidrefs; - * u32 ste_ssid_offset; - * }; - * - * struct acm_chwall_policy_buffer { - * u32 policy_version; * ACM_CHWALL_VERSION * - * u32 policy_code; - * u32 chwall_max_types; - * u32 chwall_max_ssidrefs; - * u32 chwall_max_conflictsets; - * u32 chwall_ssid_offset; - * u32 chwall_conflict_sets_offset; - * u32 chwall_running_types_offset; - * u32 chwall_conflict_aggregate_offset; - * }; - * - * typedef struct { - * u16 partition_max; - * u16 partition_offset; - * u16 vlan_max; - * u16 vlan_offset; - * u16 slot_max; - * u16 slot_offset; - * } acm_resource_buffer_t; - * - * typedef struct { - * u16 id; - * u16 ssid_ste; - * u16 ssid_chwall; - * } acm_partition_entry_t; - * - * typedef struct { - * u16 vlan; - * u16 ssid_ste; - * } acm_vlan_entry_t; - * - * typedef struct { - * u16 bus; - * u16 slot; - * u16 ssid_ste; - * } acm_slot_entry_t; - * - * - * - */ -public interface XmlToBinInterface -{ - /* policy code (uint16) */ - final int policyCodeSize = 2; - - /* max_types (uint16) */ - final int maxTypesSize = 2; - - /* max_ssidrefs (uint16) */ - final int maxSsidrefSize = 2; - - /* ssid_offset (uint32) */ - final int ssidOffsetSize = 2; - - final short markSymbol = 0x0001; - - final int u32Size = 4; - final int u16Size = 2; - - /* num of bytes for acm_ste_policy_buffer_t */ - final int steHeaderSize = (5 * u32Size); - - /* byte for acm_chinese_wall_policy_buffer_t */ - final int chwHeaderSize = (9 * u32Size); - - final int primaryPolicyCodeSize = u32Size; - final int primaryBufferOffsetSize = u32Size ; - - final int secondaryPolicyCodeSz = u32Size; - final int secondaryBufferOffsetSz = u32Size; - final int resourceOffsetSz = u32Size; - - final short partitionBufferSz = (2 * u16Size); - final short partitionEntrySz = (3 * u16Size); - - final short slotBufferSz = (2 * u16Size); - final short slotEntrySz = (3 * u16Size); - - final short vlanBufferSz = (2 * u16Size); - final short vlanEntrySz = (2 * u16Size); - - final int binaryBufferHeaderSz = (8 * u32Size); /* 8th not used in Xen */ - - /* copied directly from acm.h */ - final int ACM_MAGIC = 0x0001debc; - final int ACM_NULL_POLICY = 0; - final int ACM_CHINESE_WALL_POLICY = 1; - final int ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2; - final int ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY = 3; - final int ACM_EMPTY_POLICY = 4; - - /* version for compatibility check */ - final int ACM_POLICY_VERSION = 1; - final int ACM_STE_VERSION = 1; - final int ACM_CHWALL_VERSION = 1; -} diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/c2j_include.c --- a/tools/misc/policyprocessor/c2j_include.c Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,57 +0,0 @@ -/**************************************************************** - * c2j_include.c - * - * Copyright (C) 2005 IBM Corporation - * - * Authors: - * Reiner Sailer <sailer@xxxxxxxxxxxxxx> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * This tool makes some constants from acm.h available to the - * java policyprocessor for version checking. - */ -#include <stdio.h> -#include <errno.h> -#include <stdlib.h> -#include <stdint.h> - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - -#include <xen/acm.h> - -char *filename = "policy_version.java"; - -int main(int argc, char **argv) -{ - - FILE *fd; - if ((fd = fopen(filename, "w")) <= 0) - { - printf("File %s not found.\n", filename); - exit(-ENOENT); - } - - fprintf(fd, "/*\n * This file was automatically generated\n"); - fprintf(fd, " * Do not change it manually!\n */\n"); - fprintf(fd, "public class policy_version {\n"); - fprintf(fd, " final int ACM_POLICY_VERSION = %x;\n", - ACM_POLICY_VERSION); - fprintf(fd, " final int ACM_CHWALL_VERSION = %x;\n", - ACM_CHWALL_VERSION); - fprintf(fd, " final int ACM_STE_VERSION = %x;\n", - ACM_STE_VERSION); - fprintf(fd, "}\n"); - fclose(fd); - return 0; -} diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/myHandler.java --- a/tools/misc/policyprocessor/myHandler.java Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,47 +0,0 @@ -/** - * (C) Copyright IBM Corp. 2005 - * - * $Id: myHandler.java,v 1.2 2005/06/17 20:00:04 rvaldez Exp $ - * - * Author: Ray Valdez - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * myHandler Class. - * - * <p> - * - * A dummy class used for detecting XML validating/parsing errors. - * - * <p> - * - * - */ -import org.xml.sax.helpers.*; -import org.xml.sax.SAXParseException; - -class myHandler extends DefaultHandler -{ - public boolean isValid = true; - - /* Notification of a recoverable error. */ - public void error(SAXParseException se) - { - isValid = false; - } - - /* Notification of a non-recoverable error. */ - public void fatalError(SAXParseException se) - { - isValid = false; - } - - /* Notification of a warning. */ - public void warning(SAXParseException se) - { - isValid = false; - } -} diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/readme.install --- a/tools/misc/policyprocessor/readme.install Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,33 +0,0 @@ -# Author: Ray Valdez, rvaldez@xxxxxxxxxx -# Version: 1.0 -# -# install readme -# -PREREQUISITES: - -Prior to installation of the policy processor tool (XmlToBin) you must have... - - 1. Java version 1.4.2 - 2. xmlParserAPIs.jar and xercesImpl.jar - -The above can be obtained from the Sun Developer Network web site at -http://java.sun.com/j2se/1.4.2/download.html. - -XmlParserAPIs and xercesImpl jars can be obtained from -http://www.apache.org/dist/xml/xerces-j (Xerces-J-bin.2.6.2.tar.gz, -for example). - -The tool has been tested with J2SE v1.4.2_08 JRE on Linux (32-bit -INTEL). - -INSTALLATION - -1. Set PATH to include $HOME_JAVA/bin and $HOME_JAVA/jre/bin - where $HOME_JAVA is your java installation directory - -2. Compile XmlToBin: - javac XmlToBin.java - -USAGE - - See readme.xen diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/readme.xen --- a/tools/misc/policyprocessor/readme.xen Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,65 +0,0 @@ -# Author: Ray Valdez, rvaldez@xxxxxxxxxx -# Version: 1.0 -# -# This readme describes the policy processor tool for sHype. -# - -Java program: - - java XmlToBin -i [file.xml] -o <file.bin> -xssid <SsidFile> -xssidconf <SsidConf> - - Command line options: - - -i inputFile: name of policyfile (.xml) - -o outputFile: name of binary policy file (Big Endian) - -xssid SsidFile: xen ssids to named types text file - -xssidconf SsidConf: xen conflict ssids to types text file - -debug turn on debug messages - -help help. This printout - -Where: - -file.xml is the (input) xml policy file to be parsed and validated. -The syntax for file.xml is defined in the SecurityPolicySpec.xsd file. -file.bin is the (output) binary policy file generated by XmlToBin. -This binary policy can be activated in sHype. The binary policy file -is laid out in network byte order (i.e., big endian). The SsidFile -file contains the mapping of type enforcement (TE) ssids to the "named -types". Similarly, the SsidConf file contains the mapping of Chinese -Wall (ChWall) ssids to conflict named types. The ssidFile and SsidConf -files are used by Xen. - -Xml Schema and policy: - -The SecurityPolicySpec.xsd defines the syntax of a policy file. It -declares the tags that are used by XmlToBin to generate the binary -policy file. The tags that XmlToBin keys on are TE, ChWall, id, vid, -etc. The xml files that describe a policy are simple. Semantic -checking of a policy is performed mostly by XmlToBin. A type, for -example, is a string. No fixed values are defined for types in Xml. - -A policy consists of two Xml files: definition and policy. The -definition Xml declares the types that are permitted in the policy -Xml. The policy Xml contains the assignment of labels to -subject/object (e.g., vm). This Xml file contains an explicit -reference to the definition Xml (e.g., <url>xen_sample_def.xml</url>). -The policy Xml is the one provided as a command line argument. - - -Files: - -*.java - policy processor source -xen_sample_policy.xml - sample xml policy file -xen_sample_def.xml - sample user defined types -SecurityPolicySpec.xsd - schema definition file - - -To generate the sample binary policy: - -export CLASSPATH=$XERCES_HOME/xercesImpl.jar:$XERCES_HOME/xmlParserAPIs.jar:. - -java XmlToBin -i xen_sample_policy.xml -o xen_sample_policy.bin - -where $XERCES_HOME is the installation directory of the Apache Xerces-J - - diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/xen_sample_def.xml --- a/tools/misc/policyprocessor/xen_sample_def.xml Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,46 +0,0 @@ -<?xml version="1.0"?> -<!-- Author: Ray Valdez, rvaldez@xxxxxxxxxx --> -<!-- example policy type definition --> -<SecurityPolicySpec -xmlns="http://www.ibm.com" -xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -xsi:schemaLocation="http://www.ibm.com SecurityPolicySpec.xsd"> - -<Definition> -<!-- an example of a simple type enforcement type definition --> - <Types> - <TE>LOCAL-management</TE> - <TE>R-Company-development</TE> - <TE>S-Company-order</TE> - <TE>T-Company-advertising</TE> - <TE>U-Company-computing</TE> - <!-- TE nondevelopment --> - </Types> - -<!-- an example of a chinese wall type definition along with conflict sets--> - <ChWallTypes> - <ChWall>Q-Company</ChWall> - <ChWall>R-Company</ChWall> - <ChWall>S-Company</ChWall> - <ChWall>T-Company</ChWall> - <ChWall>U-Company</ChWall> - <ChWall>V-Company</ChWall> - <ChWall>W-Company</ChWall> - <ChWall>X-Company</ChWall> - <ChWall>Y-Company</ChWall> - <ChWall>Z-Company</ChWall> - </ChWallTypes> - - <ConflictSet> - <ChWall>T-Company</ChWall> - <ChWall>S-Company</ChWall> - </ConflictSet> - - <ConflictSet> - <ChWall>R-Company</ChWall> - <ChWall>V-Company</ChWall> - <ChWall>W-Company</ChWall> - </ConflictSet> - -</Definition> -</SecurityPolicySpec> diff -r 99914b54f7bf -r 81576d3d1ca8 tools/misc/policyprocessor/xen_sample_policy.xml --- a/tools/misc/policyprocessor/xen_sample_policy.xml Thu Aug 18 18:40:02 2005 +++ /dev/null Fri Aug 19 18:19:28 2005 @@ -1,58 +0,0 @@ -<?xml version="1.0"?> -<!-- Author: Ray Valdez, rvaldez@xxxxxxxxxx --> -<!-- example xen policy file --> - -<SecurityPolicySpec -xmlns="http://www.ibm.com" -xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -xsi:schemaLocation="http://www.ibm.com SecurityPolicySpec.xsd"> -<Policy> - <PolicyHeader> - <Name>xen sample policy</Name> - <DateTime>2005-05-20T16:56:00</DateTime> - <Tag>foobar</Tag> - <TypeDefinition> - <url>xen_sample_def.xml</url> - <hash>abcdef123456abcdef</hash> - </TypeDefinition> - </PolicyHeader> - - <VM> - <id> 0 </id> - <TE>LOCAL-management</TE> - <TE>R-Company-development</TE> - <TE>S-Company-order</TE> - <TE>T-Company-advertising</TE> - <TE>U-Company-computing</TE> - <ChWall>Q-Company</ChWall> - </VM> - - <VM> - <id> 1 </id> - <TE>R-Company-development</TE> - <ChWall>R-Company</ChWall> - </VM> - - <VM> - <id> 2 </id> - <TE>S-Company-order</TE> - <ChWall>S-Company</ChWall> - - </VM> - - <VM> - <id> 3 </id> - <TE>T-Company-advertising</TE> - <ChWall>T-Company</ChWall> - </VM> - - - <VM> - <id> 4 </id> - <TE>U-Company-computing</TE> - <ChWall>U-Company</ChWall> - </VM> - - -</Policy> -</SecurityPolicySpec> _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |