[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Merge.
# HG changeset patch # User jrb44@xxxxxxxxxxxxxxxxxx # Node ID abfc9808adb939fc3091a629ee0db423dacff16d # Parent d79ab87e27b8f88621234f7fb5bfeb24a8d33a89 # Parent 96cc6aa196b6e079488fabcc2eef32c38f7ff890 Merge. diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Tue Oct 4 13:22:30 2005 @@ -49,6 +49,7 @@ #include <asm/irq.h> #include <asm/desc.h> #include <asm-xen/xen-public/physdev.h> +#include <asm-xen/xen-public/vcpu.h> #ifdef CONFIG_MATH_EMULATION #include <asm/math_emu.h> #endif @@ -140,6 +141,13 @@ BUG(); } #endif /* CONFIG_HOTPLUG_CPU */ + +void cpu_restore(void) +{ + play_dead(); + local_irq_enable(); + cpu_idle(); +} /* * The idle thread. There's no useful work to be @@ -171,7 +179,7 @@ don't printk. */ __get_cpu_var(cpu_state) = CPU_DEAD; /* Tell hypervisor to take vcpu down. */ - HYPERVISOR_vcpu_down(cpu); + HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL); #endif play_dead(); local_irq_enable(); diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Tue Oct 4 13:22:30 2005 @@ -365,6 +365,7 @@ /* Raw start-of-day parameters from the hypervisor. */ start_info_t *xen_start_info; +EXPORT_SYMBOL(xen_start_info); static void __init limit_regions(unsigned long long size) { diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Tue Oct 4 13:22:30 2005 @@ -63,6 +63,7 @@ #include <smpboot_hooks.h> #include <asm-xen/evtchn.h> +#include <asm-xen/xen-public/vcpu.h> /* Set if we find a B stepping CPU */ static int __initdata smp_b_stepping; @@ -802,7 +803,6 @@ extern void hypervisor_callback(void); extern void failsafe_callback(void); extern void smp_trap_init(trap_info_t *); - int i; cpu = ++cpucount; /* @@ -853,12 +853,6 @@ /* FPU is set up to default initial state. */ memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt)); - /* Virtual IDT is empty at start-of-day. */ - for ( i = 0; i < 256; i++ ) - { - ctxt.trap_ctxt[i].vector = i; - ctxt.trap_ctxt[i].cs = FLAT_KERNEL_CS; - } smp_trap_init(ctxt.trap_ctxt); /* No LDT. */ @@ -889,11 +883,13 @@ ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT; - boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt); + boot_error = HYPERVISOR_vcpu_op(VCPUOP_create, cpu, &ctxt); if (boot_error) printk("boot error: %ld\n", boot_error); if (!boot_error) { + HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); + /* * allow APs to start initializing. */ @@ -1506,7 +1502,7 @@ #ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_XEN /* Tell hypervisor to bring vcpu up. */ - HYPERVISOR_vcpu_up(cpu); + HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); #endif /* Already up, and in cpu_quiescent now? */ if (cpu_isset(cpu, smp_commenced_mask)) { @@ -1585,61 +1581,49 @@ local_setup_timer_irq(); } -static atomic_t vcpus_rebooting; - -static void restore_vcpu_ready(void) -{ - - atomic_dec(&vcpus_rebooting); -} - -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]); -} - -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_ready; - - /* 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; -} +void vcpu_prepare(int vcpu) +{ + extern void hypervisor_callback(void); + extern void failsafe_callback(void); + extern void smp_trap_init(trap_info_t *); + extern void cpu_restore(void); + vcpu_guest_context_t ctxt; + struct task_struct *idle = idle_task(vcpu); + + if (vcpu == 0) + return; + + memset(&ctxt, 0, sizeof(ctxt)); + + ctxt.user_regs.ds = __USER_DS; + ctxt.user_regs.es = __USER_DS; + ctxt.user_regs.fs = 0; + ctxt.user_regs.gs = 0; + ctxt.user_regs.ss = __KERNEL_DS; + ctxt.user_regs.cs = __KERNEL_CS; + ctxt.user_regs.eip = (unsigned long)cpu_restore; + ctxt.user_regs.esp = idle->thread.esp; + ctxt.user_regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_IOPL_RING1; + + memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt)); + + smp_trap_init(ctxt.trap_ctxt); + + ctxt.ldt_ents = 0; + + ctxt.gdt_frames[0] = virt_to_mfn(cpu_gdt_descr[vcpu].address); + ctxt.gdt_ents = cpu_gdt_descr[vcpu].size / 8; + + ctxt.kernel_ss = __KERNEL_DS; + ctxt.kernel_sp = idle->thread.esp0; + + ctxt.event_callback_cs = __KERNEL_CS; + ctxt.event_callback_eip = (unsigned long)hypervisor_callback; + ctxt.failsafe_callback_cs = __KERNEL_CS; + ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback; + + ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT; + + (void)HYPERVISOR_vcpu_op(VCPUOP_create, vcpu, &ctxt); + (void)HYPERVISOR_vcpu_op(VCPUOP_up, vcpu, NULL); +} diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Tue Oct 4 13:22:30 2005 @@ -1012,6 +1012,12 @@ void smp_trap_init(trap_info_t *trap_ctxt) { trap_info_t *t = trap_table; + int i; + + for (i = 0; i < 256; i++) { + trap_ctxt[i].vector = i; + trap_ctxt[i].cs = FLAT_KERNEL_CS; + } for (t = trap_table; t->address; t++) { trap_ctxt[t->vector].flags = t->flags; diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Tue Oct 4 13:22:30 2005 @@ -52,24 +52,30 @@ pgprot_t prot, domid_t domid) { - int i; + int i, rc; unsigned long start_address; -#define MAX_DIRECTMAP_MMU_QUEUE 130 - mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *v = u, *w = u; + mmu_update_t *u, *v, *w; + + u = v = w = (mmu_update_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); + if (u == NULL) + return -ENOMEM; start_address = address; flush_cache_all(); for (i = 0; i < size; i += PAGE_SIZE) { - if ((v - u) == MAX_DIRECTMAP_MMU_QUEUE) { + if ((v - u) == (PAGE_SIZE / sizeof(mmu_update_t))) { /* Fill in the PTE pointers. */ - generic_page_range(mm, start_address, - address - start_address, - direct_remap_area_pte_fn, &w); + rc = generic_page_range(mm, start_address, + address - start_address, + direct_remap_area_pte_fn, &w); + if (rc) + goto out; w = u; + rc = -EFAULT; if (HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0) - return -EFAULT; + goto out; v = u; start_address = address; } @@ -89,13 +95,19 @@ /* get the ptep's filled in */ generic_page_range(mm, start_address, address - start_address, direct_remap_area_pte_fn, &w); + rc = -EFAULT; if (unlikely(HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0)) - return -EFAULT; - } - + goto out; + } + + rc = 0; + + out: flush_tlb_all(); - return 0; + free_page((unsigned long)u); + + return rc; } int direct_remap_pfn_range(struct vm_area_struct *vma, diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Tue Oct 4 13:22:30 2005 @@ -629,6 +629,7 @@ if (VALID_EVTCHN(evtchn)) notify_remote_via_evtchn(evtchn); } +EXPORT_SYMBOL(notify_remote_via_irq); void irq_resume(void) { diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/arch/xen/kernel/reboot.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Tue Oct 4 13:22:30 2005 @@ -74,11 +74,8 @@ extern unsigned long *pfn_to_mfn_frame_list[]; #ifdef CONFIG_SMP - static vcpu_guest_context_t suspended_cpu_records[NR_CPUS]; - cpumask_t prev_online_cpus, prev_present_cpus; - - void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); - int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); + cpumask_t prev_online_cpus; + int vcpu_prepare(int vcpu); #endif extern void xencons_resume(void); @@ -132,16 +129,6 @@ preempt_enable(); -#ifdef CONFIG_SMP - 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); - } -#endif - gnttab_suspend(); #ifdef __i386__ @@ -189,18 +176,16 @@ time_resume(); + __sti(); + + xencons_resume(); + + xenbus_resume(); + #ifdef CONFIG_SMP - for_each_cpu_mask(i, prev_present_cpus) - restore_vcpu_context(i, &suspended_cpu_records[i]); -#endif - - __sti(); - - xencons_resume(); - - xenbus_resume(); - -#ifdef CONFIG_SMP + for_each_present_cpu(i) + vcpu_prepare(i); + out_reenable_cpus: for_each_cpu_mask(i, prev_online_cpus) { j = cpu_up(i); diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile Tue Oct 4 13:22:30 2005 @@ -51,7 +51,7 @@ cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../../i386/kernel/cpuid.o topology-y += ../../../i386/mach-default/topology.o #swiotlb-$(CONFIG_SWIOTLB) += ../../../ia64/lib/swiotlb.o -microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../../i386/kernel/microcode.o +microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o intel_cacheinfo-y += ../../../i386/kernel/cpu/intel_cacheinfo.o quirks-y += ../../i386/kernel/quirks.o diff -r d79ab87e27b8 -r abfc9808adb9 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 Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Tue Oct 4 13:22:30 2005 @@ -86,6 +86,7 @@ /* Raw start-of-day parameters from the hypervisor. */ start_info_t *xen_start_info; +EXPORT_SYMBOL(xen_start_info); #endif /* diff -r d79ab87e27b8 -r abfc9808adb9 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 Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Tue Oct 4 13:22:30 2005 @@ -62,8 +62,8 @@ #include <asm/nmi.h> #ifdef CONFIG_XEN #include <asm/arch_hooks.h> - #include <asm-xen/evtchn.h> +#include <asm-xen/xen-public/vcpu.h> #endif /* Change for real CPU hotplug. Note other files need to be fixed @@ -742,12 +742,6 @@ /* FPU is set up to default initial state. */ memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt)); - /* Virtual IDT is empty at start-of-day. */ - for ( i = 0; i < 256; i++ ) - { - ctxt.trap_ctxt[i].vector = i; - ctxt.trap_ctxt[i].cs = FLAT_KERNEL_CS; - } smp_trap_init(ctxt.trap_ctxt); /* No LDT. */ @@ -777,11 +771,13 @@ ctxt.ctrlreg[3] = virt_to_mfn(init_level4_pgt) << PAGE_SHIFT; - boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt); + boot_error = HYPERVISOR_vcpu_op(VCPUOP_create, cpu, &ctxt); if (boot_error) printk("boot error: %ld\n", boot_error); if (!boot_error) { + HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); + /* * allow APs to start initializing. */ @@ -1267,13 +1263,8 @@ local_setup_timer_irq(); } -void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) -{ -} - -int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) -{ - return 0; -} - -#endif +void vcpu_prepare(int vcpu) +{ +} + +#endif diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c Tue Oct 4 13:22:30 2005 @@ -956,6 +956,12 @@ void smp_trap_init(trap_info_t *trap_ctxt) { trap_info_t *t = trap_table; + int i; + + for (i = 0; i < 256; i++) { + trap_ctxt[i].vector = i; + trap_ctxt[i].cs = FLAT_KERNEL_CS; + } for (t = trap_table; t->address; t++) { trap_ctxt[t->vector].flags = t->flags; diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c Tue Oct 4 13:22:30 2005 @@ -30,7 +30,8 @@ enum { TPM_MINOR = 224, /* officially assigned */ - TPM_BUFSIZE = 2048, + TPM_MIN_BUFSIZE = 2048, + TPM_MAX_BUFSIZE = 65536, TPM_NUM_DEVICES = 256, TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int)) }; @@ -63,7 +64,7 @@ down(&chip->buffer_mutex); atomic_set(&chip->data_pending, 0); - memset(chip->data_buffer, 0, TPM_BUFSIZE); + memset(chip->data_buffer, 0, chip->vendor->buffersize); up(&chip->buffer_mutex); } @@ -458,7 +459,8 @@ spin_unlock(&driver_lock); - chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); + chip->data_buffer = kmalloc(chip->vendor->buffersize * sizeof(u8), + GFP_KERNEL); if (chip->data_buffer == NULL) { chip->num_opens--; put_device(chip->dev); @@ -507,8 +509,8 @@ down(&chip->buffer_mutex); - if (in_size > TPM_BUFSIZE) - in_size = TPM_BUFSIZE; + if (in_size > chip->vendor->buffersize) + in_size = chip->vendor->buffersize; if (copy_from_user (chip->data_buffer, (void __user *) buf, in_size)) { @@ -517,7 +519,9 @@ } /* atomic tpm command send and result receive */ - out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); + out_size = tpm_transmit(chip, + chip->data_buffer, + chip->vendor->buffersize); atomic_set(&chip->data_pending, out_size); up(&chip->buffer_mutex); @@ -667,6 +671,12 @@ chip->vendor = entry; + if (entry->buffersize < TPM_MIN_BUFSIZE) { + entry->buffersize = TPM_MIN_BUFSIZE; + } else if (entry->buffersize > TPM_MAX_BUFSIZE) { + entry->buffersize = TPM_MAX_BUFSIZE; + } + chip->dev_num = -1; for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++) diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h Tue Oct 4 13:22:30 2005 @@ -62,6 +62,7 @@ u8 req_complete_val; u8 req_canceled; u16 base; /* TPM base address */ + u32 buffersize; /* The device's requested buffersize */ int (*recv) (struct tpm_chip *, u8 *, size_t); int (*send) (struct tpm_chip *, u8 *, size_t); diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Tue Oct 4 13:22:30 2005 @@ -445,6 +445,7 @@ .base = 0, .attr = TPM_DEVICE_ATTRS, .miscdev.fops = &tpm_xen_ops, + .buffersize = 64 * 1024, }; static struct device tpm_device = { @@ -476,6 +477,8 @@ tpm_fe_unregister_receiver(); return rc; } + + tpm_xen.buffersize = tpmfe.max_tx_size; if ((rc = tpm_register_hardware_nopci(&tpm_device, &tpm_xen)) < 0) { device_unregister(&tpm_device); diff -r d79ab87e27b8 -r abfc9808adb9 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 Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Tue Oct 4 13:22:30 2005 @@ -316,26 +316,10 @@ } static inline int -HYPERVISOR_boot_vcpu( - unsigned long vcpu, vcpu_guest_context_t *ctxt) -{ - return _hypercall2(int, boot_vcpu, vcpu, ctxt); -} - -static inline int -HYPERVISOR_vcpu_up( - int vcpu) -{ - return _hypercall2(int, sched_op, SCHEDOP_vcpu_up | - (vcpu << SCHEDOP_vcpushift), 0); -} - -static inline int -HYPERVISOR_vcpu_pickle( - int vcpu, vcpu_guest_context_t *ctxt) -{ - return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle | - (vcpu << SCHEDOP_vcpushift), ctxt); +HYPERVISOR_vcpu_op( + int cmd, int vcpuid, void *extra_args) +{ + return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); } static inline int @@ -354,24 +338,6 @@ SCHEDOP_reasonshift)), "2" (srec) : "memory", "ecx"); - return ret; -} - -static inline int -HYPERVISOR_vcpu_down( - int vcpu) -{ - 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", "ecx", "edx" ); return ret; } diff -r d79ab87e27b8 -r abfc9808adb9 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 Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h Tue Oct 4 13:22:30 2005 @@ -412,17 +412,6 @@ ptep_set_access_flags(__vma, __address, __ptep, __entry, 1); \ } while (0) -#define __HAVE_ARCH_PTEP_ESTABLISH_NEW -#define ptep_establish_new(__vma, __address, __ptep, __entry) \ -do { \ - if (likely((__vma)->vm_mm == current->mm)) { \ - BUG_ON(HYPERVISOR_update_va_mapping((__address), \ - __entry, 0)); \ - } else { \ - xen_l1_entry_update((__ptep), (__entry)); \ - } \ -} while (0) - #ifndef CONFIG_XEN_SHADOW_MODE void make_lowmem_page_readonly(void *va); void make_lowmem_page_writable(void *va); diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/include/asm-xen/asm-ia64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-ia64/hypercall.h Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-ia64/hypercall.h Tue Oct 4 13:22:30 2005 @@ -601,24 +601,6 @@ return 1; } -static inline int -HYPERVISOR_boot_vcpu( - unsigned long vcpu, vcpu_guest_context_t *ctxt) -{ -#if 0 - int ret; - unsigned long ign1, ign2; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2) - : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt) - : "memory"); - - return ret; -#endif - return 1; -} #endif #endif /* __HYPERCALL_H__ */ diff -r d79ab87e27b8 -r abfc9808adb9 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 Mon Oct 3 15:40:27 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Tue Oct 4 13:22:30 2005 @@ -302,26 +302,10 @@ } static inline int -HYPERVISOR_boot_vcpu( - unsigned long vcpu, vcpu_guest_context_t *ctxt) -{ - return _hypercall2(int, boot_vcpu, vcpu, ctxt); -} - -static inline int -HYPERVISOR_vcpu_up( - int vcpu) -{ - return _hypercall2(int, sched_op, SCHEDOP_vcpu_up | - (vcpu << SCHEDOP_vcpushift), 0); -} - -static inline int -HYPERVISOR_vcpu_pickle( - int vcpu, vcpu_guest_context_t *ctxt) -{ - return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle | - (vcpu << SCHEDOP_vcpushift), ctxt); +HYPERVISOR_vcpu_op( + int cmd, int vcpuid, void *extra_args) +{ + return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); } static inline int diff -r d79ab87e27b8 -r abfc9808adb9 tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Mon Oct 3 15:40:27 2005 +++ b/tools/python/xen/xend/XendCheckpoint.py Tue Oct 4 13:22:30 2005 @@ -1,4 +1,5 @@ # Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx> +# Copyright (C) 2005 XenSource Ltd # This file is subject to the terms and conditions of the GNU General # Public License. See the file "COPYING" in the main directory of @@ -15,7 +16,6 @@ import xen.lowlevel.xc -import XendDomainInfo from xen.xend.xenstore.xsutil import IntroduceDomain from XendError import XendError @@ -42,58 +42,75 @@ raise XendError(errmsg) return buf -def save(xd, fd, dominfo, live): +def save(fd, dominfo, live): write_exact(fd, SIGNATURE, "could not write guest state file: signature") config = sxp.to_string(dominfo.sxpr()) - write_exact(fd, pack("!i", len(config)), - "could not write guest state file: config len") - write_exact(fd, config, "could not write guest state file: config") - - # xc_save takes three customization parameters: maxit, max_f, and flags - # the last controls whether or not save is 'live', while the first two - # further customize behaviour when 'live' save is enabled. Passing "0" - # simply uses the defaults compiled into libxenguest; see the comments - # and/or code in xc_linux_save() for more information. - cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd), - str(dominfo.getDomid()), "0", "0", str(int(live)) ] - log.info("[xc_save] " + join(cmd)) - child = xPopen3(cmd, True, -1, [fd, xc.handle()]) + + domain_name = dominfo.getName() + + if live: + dominfo.setName('migrating-' + domain_name) + + try: + write_exact(fd, pack("!i", len(config)), + "could not write guest state file: config len") + write_exact(fd, config, "could not write guest state file: config") + + # xc_save takes three customization parameters: maxit, max_f, and + # flags the last controls whether or not save is 'live', while the + # first two further customize behaviour when 'live' save is + # enabled. Passing "0" simply uses the defaults compiled into + # libxenguest; see the comments and/or code in xc_linux_save() for + # more information. + cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd), + str(dominfo.getDomid()), "0", "0", str(int(live)) ] + log.info("[xc_save] " + join(cmd)) + child = xPopen3(cmd, True, -1, [fd, xc.handle()]) - lasterr = "" - p = select.poll() - p.register(child.fromchild.fileno()) - p.register(child.childerr.fileno()) - while True: - r = p.poll() - for (fd, event) in r: - if not event & select.POLLIN: - continue - if fd == child.childerr.fileno(): - l = child.childerr.readline() - log.error(l.rstrip()) - lasterr = l.rstrip() - if fd == child.fromchild.fileno(): - l = child.fromchild.readline() - if l.rstrip() == "suspend": - log.info("suspending %d" % dominfo.getDomid()) - xd.domain_shutdown(dominfo.getDomid(), reason='suspend') - dominfo.state_wait(XendDomainInfo.STATE_VM_SUSPENDED) - log.info("suspend %d done" % dominfo.getDomid()) - child.tochild.write("done\n") - child.tochild.flush() - if filter(lambda (fd, event): event & select.POLLHUP, r): - break - - if child.wait() >> 8 == 127: - lasterr = "popen %s failed" % PATH_XC_SAVE - if child.wait() != 0: - raise XendError("xc_save failed: %s" % lasterr) - - dominfo.destroy() - return None - -def restore(fd): + lasterr = "" + p = select.poll() + p.register(child.fromchild.fileno()) + p.register(child.childerr.fileno()) + while True: + r = p.poll() + for (fd, event) in r: + if not event & select.POLLIN: + continue + if fd == child.childerr.fileno(): + l = child.childerr.readline() + log.error(l.rstrip()) + lasterr = l.rstrip() + if fd == child.fromchild.fileno(): + l = child.fromchild.readline() + if l.rstrip() == "suspend": + log.info("suspending %d", dominfo.getDomid()) + dominfo.shutdown('suspend') + dominfo.waitForShutdown() + log.info("suspend %d done", dominfo.getDomid()) + child.tochild.write("done\n") + child.tochild.flush() + if filter(lambda (fd, event): event & select.POLLHUP, r): + break + + if child.wait() >> 8 == 127: + lasterr = "popen %s failed" % PATH_XC_SAVE + if child.wait() != 0: + raise XendError("xc_save failed: %s" % lasterr) + + dominfo.destroyDomain() + except Exception, exn: + log.exception("Save failed on domain %s (%d).", domain_name, + dominfo.getDomid()) + try: + if live: + dominfo.setName(domain_name) + except: + log.exception("Failed to reset the migrating domain's name") + raise Exception, exn + + +def restore(xd, fd): signature = read_exact(fd, len(SIGNATURE), "not a valid guest state file: signature read") if signature != SIGNATURE: @@ -112,71 +129,72 @@ raise XendError("not a valid guest state file: config parse") vmconfig = p.get_val() - dominfo = XendDomainInfo.restore(vmconfig) - - l = read_exact(fd, sizeof_unsigned_long, - "not a valid guest state file: pfn count read") - nr_pfns = unpack("=L", l)[0] # XXX endianess - if nr_pfns > 1024*1024: # XXX - raise XendError( - "not a valid guest state file: pfn count out of range") - - if dominfo.store_channel: + + dominfo = xd.restore_(vmconfig) + + assert dominfo.store_channel + assert dominfo.console_channel + + try: + l = read_exact(fd, sizeof_unsigned_long, + "not a valid guest state file: pfn count read") + nr_pfns = unpack("=L", l)[0] # XXX endianess + if nr_pfns > 1024*1024: # XXX + raise XendError( + "not a valid guest state file: pfn count out of range") + store_evtchn = dominfo.store_channel.port2 - else: - store_evtchn = 0 - - if dominfo.console_channel: console_evtchn = dominfo.console_channel.port2 - else: - console_evtchn = 0 - - cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd), - str(dominfo.getDomid()), str(nr_pfns), - str(store_evtchn), str(console_evtchn)] - log.info("[xc_restore] " + join(cmd)) - child = xPopen3(cmd, True, -1, [fd, xc.handle()]) - child.tochild.close() - - lasterr = "" - p = select.poll() - p.register(child.fromchild.fileno()) - p.register(child.childerr.fileno()) - while True: - r = p.poll() - for (fd, event) in r: - if not event & select.POLLIN: - continue - if fd == child.childerr.fileno(): - l = child.childerr.readline() - log.error(l.rstrip()) - lasterr = l.rstrip() - if fd == child.fromchild.fileno(): - l = child.fromchild.readline() - while l: - log.info(l.rstrip()) - m = re.match(r"^(store-mfn) (\d+)\n$", l) - if m: - if dominfo.store_channel: + + cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd), + str(dominfo.getDomid()), str(nr_pfns), + str(store_evtchn), str(console_evtchn)] + log.info("[xc_restore] " + join(cmd)) + child = xPopen3(cmd, True, -1, [fd, xc.handle()]) + child.tochild.close() + + lasterr = "" + p = select.poll() + p.register(child.fromchild.fileno()) + p.register(child.childerr.fileno()) + while True: + r = p.poll() + for (fd, event) in r: + if not event & select.POLLIN: + continue + if fd == child.childerr.fileno(): + l = child.childerr.readline() + log.error(l.rstrip()) + lasterr = l.rstrip() + if fd == child.fromchild.fileno(): + l = child.fromchild.readline() + while l: + log.info(l.rstrip()) + m = re.match(r"^(store-mfn) (\d+)\n$", l) + if m: store_mfn = int(m.group(2)) dominfo.setStoreRef(store_mfn) IntroduceDomain(dominfo.getDomid(), store_mfn, dominfo.store_channel.port1, dominfo.getDomainPath()) - m = re.match(r"^(console-mfn) (\d+)\n$", l) - if m: - dominfo.setConsoleRef(int(m.group(2))) - try: - l = child.fromchild.readline() - except: - l = None - if filter(lambda (fd, event): event & select.POLLHUP, r): - break - - if child.wait() >> 8 == 127: - lasterr = "popen %s failed" % PATH_XC_RESTORE - if child.wait() != 0: - raise XendError("xc_restore failed: %s" % lasterr) - - return dominfo + m = re.match(r"^(console-mfn) (\d+)\n$", l) + if m: + dominfo.setConsoleRef(int(m.group(2))) + try: + l = child.fromchild.readline() + except: + l = None + if filter(lambda (fd, event): event & select.POLLHUP, r): + break + + if child.wait() >> 8 == 127: + lasterr = "popen %s failed" % PATH_XC_RESTORE + if child.wait() != 0: + raise XendError("xc_restore failed: %s" % lasterr) + + return dominfo + except: + log.exception("Restore failed") + dominfo.destroy() + raise diff -r d79ab87e27b8 -r abfc9808adb9 tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Mon Oct 3 15:40:27 2005 +++ b/tools/python/xen/xend/XendDomain.py Tue Oct 4 13:22:30 2005 @@ -22,14 +22,16 @@ Needs to be persistent for one uptime. """ import os +import string import threading import xen.lowlevel.xc + +import XendDomainInfo from xen.xend import sxp from xen.xend import XendRoot from xen.xend import XendCheckpoint -from xen.xend.XendDomainInfo import XendDomainInfo from xen.xend import EventServer from xen.xend.XendError import XendError from xen.xend.XendLogging import log @@ -45,20 +47,9 @@ PRIV_DOMAIN = 0 -class XendDomainDict(dict): - def get_by_name(self, name): - try: - return filter(lambda d: d.getName() == name, self.values())[0] - except IndexError, err: - return None - class XendDomain: """Index of all domains. Singleton. """ - - """Dict of domain info indexed by domain id.""" - domains = None - ## public: @@ -68,19 +59,30 @@ # to import XendDomain from XendDomainInfo causes unbounded recursion. # So we stuff the XendDomain instance (self) into xroot's components. xroot.add_component("xen.xend.XendDomain", self) - self.domains = XendDomainDict() - self.refresh_lock = threading.Condition() + self.domains = {} + self.domains_lock = threading.Condition() self.watchReleaseDomain() - self.refresh() - self.dom0_setup() + + self.domains_lock.acquire() + try: + self.refresh() + self.dom0_setup() + finally: + self.domains_lock.release() + def list(self): """Get list of domain objects. @return: domain objects """ - self.refresh() - return self.domains.values() + self.domains_lock.acquire() + try: + self.refresh() + return self.domains.values() + finally: + self.domains_lock.release() + def list_sorted(self): """Get list of domain objects, sorted by name. @@ -103,7 +105,12 @@ ## private: def onReleaseDomain(self): - self.refresh() + self.domains_lock.acquire() + try: + self.refresh() + finally: + self.domains_lock.release() + def watchReleaseDomain(self): from xen.xend.xenstore.xswatch import xswatch @@ -133,16 +140,8 @@ return dominfo - def recreate_domain(self, xeninfo): - """Refresh initial domain info from db.""" - - dominfo = XendDomainInfo.recreate(xeninfo) - self._add_domain(dominfo) - return dominfo - - def dom0_setup(self): - dom0 = self.domain_lookup(PRIV_DOMAIN) + dom0 = self.domains[PRIV_DOMAIN] dom0.dom0_enforce_vcpus() @@ -179,50 +178,33 @@ def refresh(self): """Refresh domain list from Xen. """ - self.refresh_lock.acquire() - try: - doms = self.xen_domains() - for d in self.domains.values(): - info = doms.get(d.getDomid()) - if info: - d.update(info) - else: - self._delete_domain(d.getDomid()) - for d in doms: - if d not in self.domains and not doms[d]['dying']: - try: - self.recreate_domain(doms[d]) - except: - if d == PRIV_DOMAIN: - log.exception( - "Failed to recreate information for domain " - "%d. Doing nothing except crossing my " - "fingers.", d) - else: - log.exception( - "Failed to recreate information for domain " - "%d. Destroying it in the hope of " - "recovery.", d) - try: - xc.domain_destroy(dom = d) - except: - log.exception('Destruction of %d failed.', d) - finally: - self.refresh_lock.release() - - - def update_domain(self, id): - """Update information for a single domain. - - @param id: domain id - """ - dominfo = self.xen_domain(id) - if dominfo: - d = self.domains.get(id) - if d: - d.update(dominfo) - else: - self._delete_domain(id) + doms = self.xen_domains() + for d in self.domains.values(): + info = doms.get(d.getDomid()) + if info: + d.update(info) + else: + self._delete_domain(d.getDomid()) + for d in doms: + if d not in self.domains and not doms[d]['dying']: + try: + dominfo = XendDomainInfo.recreate(doms[d]) + self._add_domain(dominfo) + except: + if d == PRIV_DOMAIN: + log.exception( + "Failed to recreate information for domain " + "%d. Doing nothing except crossing my " + "fingers.", d) + else: + log.exception( + "Failed to recreate information for domain " + "%d. Destroying it in the hope of " + "recovery.", d) + try: + xc.domain_destroy(dom = d) + except: + log.exception('Destruction of %d failed.', d) ## public: @@ -233,9 +215,14 @@ @param config: configuration @return: domain """ - dominfo = XendDomainInfo.create(config) - self._add_domain(dominfo) - return dominfo + self.domains_lock.acquire() + try: + dominfo = XendDomainInfo.create(config) + self._add_domain(dominfo) + return dominfo + finally: + self.domains_lock.release() + def domain_configure(self, config): """Configure an existing domain. @@ -252,39 +239,110 @@ """ try: - fd = os.open(src, os.O_RDONLY) - dominfo = XendCheckpoint.restore(fd) - self._add_domain(dominfo) - return dominfo + return self.domain_restore_fd(os.open(src, os.O_RDONLY)) except OSError, ex: raise XendError("can't read guest state file %s: %s" % (src, ex[1])) - def domain_get(self, id): - """Get up-to-date info about a domain. - - @param id: domain id - @return: domain object (or None) - """ - self.update_domain(id) - return self.domains.get(id) + def domain_restore_fd(self, fd): + """Restore a domain from the given file descriptor.""" + + try: + XendCheckpoint.restore(self, fd) + except Exception, ex: + log.exception("Restore failed") + raise + + + def restore_(self, config): + """Create a domain as part of the restore process. This is called + only from {@link XendCheckpoint}. + + A restore request comes into XendDomain through {@link + #domain_restore} or {@link #domain_restore_fd}. That request is + forwarded immediately to XendCheckpoint which, when it is ready, will + call this method. It is necessary to come through here rather than go + directly to {@link XendDomainInfo.restore} because we need to + serialise the domain creation process, but cannot lock + domain_restore_fd as a whole, otherwise we will deadlock waiting for + the old domain to die. + """ + self.domains_lock.acquire() + try: + dominfo = XendDomainInfo.restore(config) + self._add_domain(dominfo) + return dominfo + finally: + self.domains_lock.release() def domain_lookup(self, id): - self.refresh() - return self.domains.get(id) - - def domain_lookup_by_name(self, name): - self.refresh() - dominfo = self.domains.get_by_name(name) - if not dominfo: - try: - id = int(name) - dominfo = self.domain_lookup(id) - except ValueError: - pass - return dominfo - + self.domains_lock.acquire() + try: + self.refresh() + return self.domains.get(id) + finally: + self.domains_lock.release() + + + def domain_lookup_nr(self, id): + self.domains_lock.acquire() + try: + return self.domains.get(id) + finally: + self.domains_lock.release() + + + def domain_lookup_by_name_or_id(self, name): + self.domains_lock.acquire() + try: + self.refresh() + return self.domain_lookup_by_name_or_id_nr(name) + finally: + self.domains_lock.release() + + + def domain_lookup_by_name_or_id_nr(self, name): + self.domains_lock.acquire() + try: + dominfo = self.domain_lookup_by_name_nr(name) + + if dominfo: + return dominfo + else: + try: + return self.domains.get(int(name)) + except ValueError: + return None + finally: + self.domains_lock.release() + + + def domain_lookup_by_name_nr(self, name): + self.domains_lock.acquire() + try: + matching = filter(lambda d: d.getName() == name, + self.domains.values()) + n = len(matching) + if n == 1: + return matching[0] + elif n > 1: + raise XendError( + 'Name uniqueness has been violated for name %s' % name) + else: + return None + finally: + self.domains_lock.release() + + + def privilegedDomain(self): + self.domains_lock.acquire() + try: + return self.domains[PRIV_DOMAIN] + finally: + self.domains_lock.release() + + def domain_unpause(self, id): """Unpause domain execution. @@ -312,32 +370,22 @@ raise XendError(str(ex)) - def domain_shutdown(self, domid, reason='poweroff'): + def domain_shutdown(self, domid, reason = 'poweroff'): """Shutdown domain (nicely). - - poweroff: restart according to exit code and restart mode - - reboot: restart on exit - - halt: do not restart - - Returns immediately. - - @param id: domain id - @param reason: shutdown type: poweroff, reboot, suspend, halt - """ - self.callInfo(domid, XendDomainInfo.shutdown, reason) + + @param reason: shutdown reason: poweroff, reboot, suspend, halt + """ + self.callInfo(domid, XendDomainInfo.XendDomainInfo.shutdown, reason) def domain_sysrq(self, domid, key): """Send a SysRq to the specified domain.""" - return self.callInfo(domid, XendDomainInfo.send_sysrq, key) - - - def domain_destroy(self, domid, reason='halt'): - """Terminate domain immediately. - - halt: cancel any restart for the domain - - reboot schedule a restart for the domain - - @param domid: domain id - """ + return self.callInfo(domid, XendDomainInfo.XendDomainInfo.send_sysrq, + key) + + + def domain_destroy(self, domid): + """Terminate domain immediately.""" if domid == PRIV_DOMAIN: raise XendError("Cannot destroy privileged domain %i" % domid) @@ -364,19 +412,8 @@ port = xroot.get_xend_relocation_port() sock = relocate.setupRelocation(dst, port) - # temporarily rename domain for localhost migration - if dst == "localhost": - dominfo.setName("tmp-" + dominfo.getName()) - - try: - XendCheckpoint.save(self, sock.fileno(), dominfo, live) - except: - if dst == "localhost": - dominfo.setName( - string.replace(dominfo.getName(), "tmp-", "", 1)) - raise + XendCheckpoint.save(sock.fileno(), dominfo, live) - return None def domain_save(self, id, dst): """Start saving a domain to file. @@ -391,7 +428,7 @@ fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) # For now we don't support 'live checkpoint' - return XendCheckpoint.save(self, fd, dominfo, False) + return XendCheckpoint.save(fd, dominfo, False) except OSError, ex: raise XendError("can't write guest state file %s: %s" % @@ -456,32 +493,39 @@ def domain_device_create(self, domid, devconfig): """Create a new device for the specified domain. """ - return self.callInfo(domid, XendDomainInfo.device_create, devconfig) + return self.callInfo(domid, + XendDomainInfo.XendDomainInfo.device_create, + devconfig) def domain_device_configure(self, domid, devconfig, devid): """Configure an existing device in the specified domain. @return: updated device configuration """ - return self.callInfo(domid, XendDomainInfo.device_configure, + return self.callInfo(domid, + XendDomainInfo.XendDomainInfo.device_configure, devconfig, devid) def domain_device_refresh(self, domid, devtype, devid): """Refresh a device.""" - return self.callInfo(domid, XendDomainInfo.device_refresh, devtype, - devid) + return self.callInfo(domid, + XendDomainInfo.XendDomainInfo.device_refresh, + devtype, devid) def domain_device_destroy(self, domid, devtype, devid): """Destroy a device.""" - return self.callInfo(domid, XendDomainInfo.destroyDevice, devtype, - devid) + return self.callInfo(domid, + XendDomainInfo.XendDomainInfo.destroyDevice, + devtype, devid) def domain_devtype_ls(self, domid, devtype): """Get list of device sxprs for the specified domain.""" - return self.callInfo(domid, XendDomainInfo.getDeviceSxprs, devtype) + return self.callInfo(domid, + XendDomainInfo.XendDomainInfo.getDeviceSxprs, + devtype) def domain_vif_limit_set(self, id, vif, credit, period): @@ -525,7 +569,8 @@ @param mem: memory target (in MiB) """ - self.callInfo(domid, XendDomainInfo.setMemoryTarget, mem << 10) + self.callInfo(domid, XendDomainInfo.XendDomainInfo.setMemoryTarget, + mem << 10) def domain_vcpu_hotplug(self, domid, vcpu, state): @@ -534,12 +579,13 @@ @param vcpu: target VCPU in domain @param state: which state VCPU will become """ - self.callInfo(domid, XendDomainInfo.vcpu_hotplug, vcpu, state) + self.callInfo(domid, XendDomainInfo.XendDomainInfo.vcpu_hotplug, vcpu, + state) def domain_dumpcore(self, domid): """Save a core dump for a crashed domain.""" - self.callInfo(domid, XendDomainInfo.dumpCore) + self.callInfo(domid, XendDomainInfo.XendDomainInfo.dumpCore) ## private: diff -r d79ab87e27b8 -r abfc9808adb9 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Mon Oct 3 15:40:27 2005 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Oct 4 13:22:30 2005 @@ -59,12 +59,16 @@ """Shutdown code for crash.""" DOMAIN_CRASH = 3 +"""Shutdown code for halt.""" +DOMAIN_HALT = 4 + """Map shutdown codes to strings.""" shutdown_reasons = { DOMAIN_POWEROFF: "poweroff", DOMAIN_REBOOT : "reboot", DOMAIN_SUSPEND : "suspend", DOMAIN_CRASH : "crash", + DOMAIN_HALT : "halt" } restart_modes = [ @@ -76,7 +80,6 @@ STATE_VM_OK = "ok" STATE_VM_TERMINATED = "terminated" -STATE_VM_SUSPENDED = "suspended" """Flag for a block device backend domain.""" SIF_BLK_BE_DOMAIN = (1<<4) @@ -116,6 +119,68 @@ ] +def create(config): + """Create a VM from a configuration. + + @param config configuration + @raise: VmError for invalid configuration + """ + + log.debug("XendDomainInfo.create(%s)", config) + + vm = XendDomainInfo(getUuid(), parseConfig(config)) + vm.construct() + vm.refreshShutdown() + return vm + + +def recreate(xeninfo): + """Create the VM object for an existing domain. The domain must not + be dying, as the paths in the store should already have been removed, + and asking us to recreate them causes problems.""" + + log.debug("XendDomainInfo.recreate(%s)", xeninfo) + + assert not xeninfo['dying'] + + domid = xeninfo['dom'] + try: + dompath = GetDomainPath(domid) + if not dompath: + raise XendError( + 'No domain path in store for existing domain %d' % domid) + vmpath = xstransact.Read(dompath, "vm") + if not vmpath: + raise XendError( + 'No vm path in store for existing domain %d' % domid) + uuid = xstransact.Read(vmpath, "uuid") + if not uuid: + raise XendError( + 'No vm/uuid path in store for existing domain %d' % domid) + + log.info("Recreating domain %d, UUID %s.", domid, uuid) + + vm = XendDomainInfo(uuid, xeninfo, domid, True) + + except Exception, exn: + log.warn(str(exn)) + + uuid = getUuid() + + log.info("Recreating domain %d with new UUID %s.", domid, uuid) + + vm = XendDomainInfo(uuid, xeninfo, domid, True) + vm.storeVmDetails() + vm.storeDomDetails() + + vm.create_channel() + if domid == 0: + vm.initStoreConnection() + + vm.refreshShutdown(xeninfo) + return vm + + def restore(config): """Create a domain and a VM object to do a restore. @@ -130,7 +195,7 @@ except TypeError, exn: raise VmError('Invalid ssidref in config: %s' % exn) - vm = XendDomainInfo(uuid, XendDomainInfo.parseConfig(config), + vm = XendDomainInfo(uuid, parseConfig(config), xc.domain_create(ssidref = ssidref)) vm.storeVmDetails() vm.configure() @@ -139,10 +204,87 @@ return vm -def domain_exists(name): +def parseConfig(config): + def get_cfg(name, conv = None): + val = sxp.child_value(config, name) + + if conv and not val is None: + try: + return conv(val) + except TypeError, exn: + raise VmError( + 'Invalid setting %s = %s in configuration: %s' % + (name, val, str(exn))) + else: + return val + + + log.debug("parseConfig: config is %s" % str(config)) + + result = {} + + for e in ROUNDTRIPPING_CONFIG_ENTRIES: + result[e[0]] = get_cfg(e[0], e[1]) + + result['memory'] = get_cfg('memory', int) + result['mem_kb'] = get_cfg('mem_kb', int) + result['maxmem'] = get_cfg('maxmem', int) + result['maxmem_kb'] = get_cfg('maxmem_kb', int) + result['cpu'] = get_cfg('cpu', int) + result['image'] = get_cfg('image') + + try: + if result['image']: + result['vcpus'] = int(sxp.child_value(result['image'], + 'vcpus', 1)) + else: + result['vcpus'] = 1 + except TypeError, exn: + raise VmError( + 'Invalid configuration setting: vcpus = %s: %s' % + (sxp.child_value(result['image'], 'vcpus', 1), str(exn))) + + result['backend'] = [] + for c in sxp.children(config, 'backend'): + result['backend'].append(sxp.name(sxp.child0(c))) + + result['device'] = [] + for d in sxp.children(config, 'device'): + c = sxp.child0(d) + result['device'].append((sxp.name(c), c)) + + # Configuration option "restart" is deprecated. Parse it, but + # let on_xyz override it if they are present. + restart = get_cfg('restart') + if restart: + def handle_restart(event, val): + if not event in result: + result[event] = val + + if restart == "onreboot": + handle_restart('on_poweroff', 'destroy') + handle_restart('on_reboot', 'restart') + handle_restart('on_crash', 'destroy') + elif restart == "always": + handle_restart('on_poweroff', 'restart') + handle_restart('on_reboot', 'restart') + handle_restart('on_crash', 'restart') + elif restart == "never": + handle_restart('on_poweroff', 'destroy') + handle_restart('on_reboot', 'destroy') + handle_restart('on_crash', 'destroy') + else: + log.warn("Ignoring malformed and deprecated config option " + "restart = %s", restart) + + log.debug("parseConfig: result is %s" % str(result)) + return result + + +def domain_by_name(name): # See comment in XendDomain constructor. xd = get_component('xen.xend.XendDomain') - return xd.domain_lookup_by_name(name) + return xd.domain_lookup_by_name_nr(name) def shutdown_reason(code): """Get a shutdown reason from a code. @@ -177,152 +319,6 @@ MINIMUM_RESTART_TIME = 20 - def create(cls, config): - """Create a VM from a configuration. - - @param config configuration - @raise: VmError for invalid configuration - """ - - log.debug("XendDomainInfo.create(%s)", config) - - vm = cls(getUuid(), cls.parseConfig(config)) - vm.construct() - vm.refreshShutdown() - return vm - - create = classmethod(create) - - - def recreate(cls, xeninfo): - """Create the VM object for an existing domain. The domain must not - be dying, as the paths in the store should already have been removed, - and asking us to recreate them causes problems.""" - - log.debug("XendDomainInfo.recreate(%s)", xeninfo) - - assert not xeninfo['dying'] - - domid = xeninfo['dom'] - try: - dompath = GetDomainPath(domid) - if not dompath: - raise XendError( - 'No domain path in store for existing domain %d' % domid) - vmpath = xstransact.Read(dompath, "vm") - if not vmpath: - raise XendError( - 'No vm path in store for existing domain %d' % domid) - uuid = xstransact.Read(vmpath, "uuid") - if not uuid: - raise XendError( - 'No vm/uuid path in store for existing domain %d' % domid) - - log.info("Recreating domain %d, UUID %s.", domid, uuid) - - vm = cls(uuid, xeninfo, domid, True) - - except Exception, exn: - log.warn(str(exn)) - - uuid = getUuid() - - log.info("Recreating domain %d with new UUID %s.", domid, uuid) - - vm = cls(uuid, xeninfo, domid, True) - vm.storeVmDetails() - vm.storeDomDetails() - - vm.create_channel() - if domid == 0: - vm.initStoreConnection() - - vm.refreshShutdown(xeninfo) - return vm - - recreate = classmethod(recreate) - - - def parseConfig(cls, config): - def get_cfg(name, conv = None): - val = sxp.child_value(config, name) - - if conv and not val is None: - try: - return conv(val) - except TypeError, exn: - raise VmError( - 'Invalid setting %s = %s in configuration: %s' % - (name, val, str(exn))) - else: - return val - - - log.debug("parseConfig: config is %s" % str(config)) - - result = {} - - for e in ROUNDTRIPPING_CONFIG_ENTRIES: - result[e[0]] = get_cfg(e[0], e[1]) - - result['memory'] = get_cfg('memory', int) - result['mem_kb'] = get_cfg('mem_kb', int) - result['maxmem'] = get_cfg('maxmem', int) - result['maxmem_kb'] = get_cfg('maxmem_kb', int) - result['cpu'] = get_cfg('cpu', int) - result['image'] = get_cfg('image') - - try: - if result['image']: - result['vcpus'] = int(sxp.child_value(result['image'], - 'vcpus', 1)) - else: - result['vcpus'] = 1 - except TypeError, exn: - raise VmError( - 'Invalid configuration setting: vcpus = %s: %s' % - (sxp.child_value(result['image'], 'vcpus', 1), str(exn))) - - result['backend'] = [] - for c in sxp.children(config, 'backend'): - result['backend'].append(sxp.name(sxp.child0(c))) - - result['device'] = [] - for d in sxp.children(config, 'device'): - c = sxp.child0(d) - result['device'].append((sxp.name(c), c)) - - # Configuration option "restart" is deprecated. Parse it, but - # let on_xyz override it if they are present. - restart = get_cfg('restart') - if restart: - def handle_restart(event, val): - if not event in result: - result[event] = val - - if restart == "onreboot": - handle_restart('on_poweroff', 'destroy') - handle_restart('on_reboot', 'restart') - handle_restart('on_crash', 'destroy') - elif restart == "always": - handle_restart('on_poweroff', 'restart') - handle_restart('on_reboot', 'restart') - handle_restart('on_crash', 'restart') - elif restart == "never": - handle_restart('on_poweroff', 'destroy') - handle_restart('on_reboot', 'destroy') - handle_restart('on_crash', 'destroy') - else: - log.warn("Ignoring malformed and deprecated config option " - "restart = %s", restart) - - log.debug("parseConfig: result is %s" % str(result)) - return result - - - parseConfig = classmethod(parseConfig) - - def __init__(self, uuid, info, domid = None, augment = False): self.uuid = uuid @@ -627,21 +623,22 @@ # The domain no longer exists. This will occur if we have # scheduled a timer to check for shutdown timeouts and the # shutdown succeeded. It will also occur if someone - # destroys a domain beneath us. We clean up, just in - # case. + # destroys a domain beneath us. We clean up the domain, + # just in case, but we can't clean up the VM, because that + # VM may have migrated to a different domain on this + # machine. self.cleanupDomain() - self.cleanupVm() return if xeninfo['dying']: # Dying means that a domain has been destroyed, but has not - # yet been cleaned up by Xen. This could persist indefinitely - # if, for example, another domain has some of its pages - # mapped. We might like to diagnose this problem in the - # future, but for now all we do is make sure that it's not - # us holding the pages, by calling the cleanup methods. + # yet been cleaned up by Xen. This state could persist + # indefinitely if, for example, another domain has some of its + # pages mapped. We might like to diagnose this problem in the + # future, but for now all we do is make sure that it's not us + # holding the pages, by calling cleanupDomain. We can't + # clean up the VM, as above. self.cleanupDomain() - self.cleanupVm() return elif xeninfo['crashed']: @@ -654,10 +651,11 @@ restart_reason = 'crash' elif xeninfo['shutdown']: - if self.readDom('xend/shutdown'): + if self.readDom('xend/shutdown_completed'): # We've seen this shutdown already, but we are preserving # the domain for debugging. Leave it alone. - pass + return + else: reason = shutdown_reason(xeninfo['shutdown_reason']) @@ -667,7 +665,7 @@ self.clearRestart() if reason == 'suspend': - self.state_set(STATE_VM_SUSPENDED) + self.state_set(STATE_VM_TERMINATED) # Don't destroy the domain. XendCheckpoint will do # this once it has finished. elif reason in ['poweroff', 'reboot']: @@ -704,7 +702,7 @@ if not reason in shutdown_reasons.values(): raise XendError('invalid reason:' + reason) self.storeDom("control/shutdown", reason) - if not reason == 'suspend': + if reason != 'suspend': self.storeDom('xend/shutdown_start_time', time.time()) @@ -721,11 +719,6 @@ "restart" : self.restart, "preserve" : self.preserve, "rename-restart" : self.renameRestart}[self.info['on_' + reason]]() - - - def preserve(self): - log.info("Preserving dead domain %s (%d).", self.info['name'], - self.domid) def renameRestart(self): @@ -817,9 +810,9 @@ ## public: - def state_wait(self, state): + def waitForShutdown(self): self.state_updated.acquire() - while self.state != state: + while self.state == STATE_VM_OK: self.state_updated.wait() self.state_updated.release() @@ -953,10 +946,8 @@ if c in '_-.:/+': continue if c in string.ascii_letters: continue raise VmError('invalid vm name') - dominfo = domain_exists(name) - # When creating or rebooting, a domain with my name should not exist. - # When restoring, a domain with my name will exist, but it should have - # my domain id. + + dominfo = domain_by_name(name) if not dominfo: return if dominfo.is_terminated(): @@ -1059,7 +1050,6 @@ """Cleanup domain resources; release devices. Idempotent. Nothrow guarantee.""" - self.state_set(STATE_VM_TERMINATED) self.release_devices() self.closeStoreChannel() self.closeConsoleChannel() @@ -1092,14 +1082,22 @@ log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid)) + self.cleanupVm() + self.destroyDomain() + + + def destroyDomain(self): + log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid)) + self.cleanupDomain() - self.cleanupVm() try: if self.domid is not None: xc.domain_destroy(dom=self.domid) except Exception: log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.") + + self.state_set(STATE_VM_TERMINATED) ## private: @@ -1248,14 +1246,18 @@ try: if rename: - self.preserveShutdownDomain() + self.preserveForRestart() else: - self.cleanupDomain() self.destroy() try: xd = get_component('xen.xend.XendDomain') - xd.domain_unpause(xd.domain_create(config).getDomid()) + new_dom = xd.domain_create(config) + try: + xc.domain_unpause(new_dom.getDomid()) + except: + new_dom.destroy() + raise except Exception, exn: log.exception('Failed to restart domain %d.', self.domid) finally: @@ -1265,7 +1267,7 @@ # self.exportToDB() - def preserveShutdownDomain(self): + def preserveForRestart(self): """Preserve a domain that has been shut down, by giving it a new UUID, cloning the VM details, and giving it a new name. This allows us to keep this domain for debugging, but restart a new one in its place @@ -1281,8 +1283,14 @@ self.uuid = new_uuid self.vmpath = VMROOT + new_uuid self.storeVmDetails() - self.storeDom('vm', self.vmpath) - self.storeDom('xend/shutdown', 'True') + self.preserve() + + + def preserve(self): + log.info("Preserving dead domain %s (%d).", self.info['name'], + self.domid) + self.storeDom('xend/shutdown_completed', 'True') + self.set_state(STATE_VM_TERMINATED) def generateShutdownName(self): diff -r d79ab87e27b8 -r abfc9808adb9 tools/python/xen/xend/server/DevController.py --- a/tools/python/xen/xend/server/DevController.py Mon Oct 3 15:40:27 2005 +++ b/tools/python/xen/xend/server/DevController.py Tue Oct 4 13:22:30 2005 @@ -189,8 +189,17 @@ """ import xen.xend.XendDomain - backdom = xen.xend.XendDomain.instance().domain_lookup_by_name( - sxp.child_value(config, 'backend', '0')) + xd = xen.xend.XendDomain.instance() + + backdom_name = sxp.child_value(config, 'backend') + if backdom_name: + backdom = xd.domain_lookup_by_name_or_id_nr(backdom_name) + else: + backdom = xd.privilegedDomain() + + if not backdom: + raise VmError("Cannot configure device for unknown backend %s" % + backdom_name) frontpath = self.frontendPath(devid) backpath = self.backendPath(backdom, devid) @@ -221,7 +230,7 @@ return "%s/backend/%s/%s/%d" % (backdom.getDomainPath(), self.deviceClass, - self.vm.getUuid(), devid) + self.vm.getDomid(), devid) def frontendPath(self, devid): diff -r d79ab87e27b8 -r abfc9808adb9 tools/python/xen/xend/server/SrvDomainDir.py --- a/tools/python/xen/xend/server/SrvDomainDir.py Mon Oct 3 15:40:27 2005 +++ b/tools/python/xen/xend/server/SrvDomainDir.py Tue Oct 4 13:22:30 2005 @@ -38,7 +38,7 @@ self.xd = XendDomain.instance() def domain(self, x): - dom = self.xd.domain_lookup_by_name(x) + dom = self.xd.domain_lookup_by_name_or_id(x) if not dom: raise XendError('No such domain ' + str(x)) return SrvDomain(dom) diff -r d79ab87e27b8 -r abfc9808adb9 tools/python/xen/xend/server/relocate.py --- a/tools/python/xen/xend/server/relocate.py Mon Oct 3 15:40:27 2005 +++ b/tools/python/xen/xend/server/relocate.py Tue Oct 4 13:22:30 2005 @@ -28,7 +28,6 @@ from xen.xend.XendError import XendError from xen.xend import XendRoot from xen.xend.XendLogging import log -from xen.xend import XendCheckpoint eserver = EventServer.instance() @@ -120,7 +119,8 @@ if self.transport: self.send_reply(["ready", name]) self.transport.sock.setblocking(1) - XendCheckpoint.restore(self.transport.sock.fileno()) + xd = xroot.get_component("xen.xend.XendDomain") + xd.domain_restore_fd(self.transport.sock.fileno()) self.transport.sock.setblocking(0) else: log.error(name + ": no transport") diff -r d79ab87e27b8 -r abfc9808adb9 xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Mon Oct 3 15:40:27 2005 +++ b/xen/arch/x86/x86_32/entry.S Tue Oct 4 13:22:30 2005 @@ -808,7 +808,7 @@ .long do_vm_assist .long do_update_va_mapping_otherdomain .long do_switch_vm86 - .long do_boot_vcpu + .long do_vcpu_op .long do_ni_hypercall /* 25 */ .long do_mmuext_op .long do_acm_op /* 27 */ @@ -841,7 +841,7 @@ .byte 2 /* do_vm_assist */ .byte 5 /* do_update_va_mapping_otherdomain */ .byte 0 /* do_switch_vm86 */ - .byte 2 /* do_boot_vcpu */ + .byte 3 /* do_vcpu_op */ .byte 0 /* do_ni_hypercall */ /* 25 */ .byte 4 /* do_mmuext_op */ .byte 1 /* do_acm_op */ diff -r d79ab87e27b8 -r abfc9808adb9 xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Mon Oct 3 15:40:27 2005 +++ b/xen/arch/x86/x86_64/entry.S Tue Oct 4 13:22:30 2005 @@ -629,7 +629,7 @@ .quad do_vm_assist .quad do_update_va_mapping_otherdomain .quad do_switch_to_user - .quad do_boot_vcpu + .quad do_vcpu_op .quad do_set_segment_base /* 25 */ .quad do_mmuext_op .quad do_acm_op @@ -662,7 +662,7 @@ .byte 2 /* do_vm_assist */ .byte 4 /* do_update_va_mapping_otherdomain */ .byte 0 /* do_switch_to_user */ - .byte 2 /* do_boot_vcpu */ + .byte 3 /* do_vcpu_op */ .byte 2 /* do_set_segment_base */ /* 25 */ .byte 4 /* do_mmuext_op */ .byte 1 /* do_acm_op */ diff -r d79ab87e27b8 -r abfc9808adb9 xen/common/domain.c --- a/xen/common/domain.c Mon Oct 3 15:40:27 2005 +++ b/xen/common/domain.c Tue Oct 4 13:22:30 2005 @@ -18,6 +18,7 @@ #include <xen/domain_page.h> #include <asm/debugger.h> #include <public/dom0_ops.h> +#include <public/vcpu.h> /* Both these structures are protected by the domlist_lock. */ rwlock_t domlist_lock = RW_LOCK_UNLOCKED; @@ -366,37 +367,17 @@ return rc; } -/* - * final_setup_guest is used for final setup and launching of domains other - * than domain 0. ie. the domains that are being built by the userspace dom0 - * domain builder. - */ -long do_boot_vcpu(unsigned long vcpu, struct vcpu_guest_context *ctxt) -{ - struct domain *d = current->domain; - struct vcpu *v; - int rc = 0; - struct vcpu_guest_context *c; - - if ( (vcpu >= MAX_VIRT_CPUS) || (d->vcpu[vcpu] != NULL) ) - return -EINVAL; - - if ( alloc_vcpu_struct(d, vcpu) == NULL ) +int boot_vcpu(struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt) +{ + struct vcpu *v; + int rc; + + ASSERT(d->vcpu[vcpuid] == NULL); + + if ( alloc_vcpu_struct(d, vcpuid) == NULL ) return -ENOMEM; - if ( (c = xmalloc(struct vcpu_guest_context)) == NULL ) - { - rc = -ENOMEM; - goto out; - } - - if ( copy_from_user(c, ctxt, sizeof(*c)) ) - { - rc = -EFAULT; - goto out; - } - - v = d->vcpu[vcpu]; + v = d->vcpu[vcpuid]; atomic_set(&v->pausecnt, 0); v->cpumap = CPUMAP_RUNANYWHERE; @@ -405,22 +386,73 @@ arch_do_boot_vcpu(v); - if ( (rc = arch_set_info_guest(v, c)) != 0 ) + if ( (rc = arch_set_info_guest(v, ctxt)) != 0 ) goto out; sched_add_domain(v); - /* domain_unpause_by_systemcontroller */ - if ( test_and_clear_bit(_VCPUF_ctrl_pause, &v->vcpu_flags) ) - vcpu_wake(v); - - xfree(c); + set_bit(_VCPUF_down, &v->vcpu_flags); + clear_bit(_VCPUF_ctrl_pause, &v->vcpu_flags); + return 0; out: - xfree(c); - arch_free_vcpu_struct(d->vcpu[vcpu]); - d->vcpu[vcpu] = NULL; + arch_free_vcpu_struct(d->vcpu[vcpuid]); + d->vcpu[vcpuid] = NULL; + return rc; +} + +long do_vcpu_op(int cmd, int vcpuid, void *arg) +{ + struct domain *d = current->domain; + struct vcpu *v; + struct vcpu_guest_context *ctxt; + long rc = 0; + + if ( (vcpuid < 0) || (vcpuid >= MAX_VIRT_CPUS) ) + return -EINVAL; + + if ( ((v = d->vcpu[vcpuid]) == NULL) && (cmd != VCPUOP_create) ) + return -ENOENT; + + switch ( cmd ) + { + case VCPUOP_create: + if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL ) + { + rc = -ENOMEM; + break; + } + + if ( copy_from_user(ctxt, arg, sizeof(*ctxt)) ) + { + xfree(ctxt); + rc = -EFAULT; + break; + } + + LOCK_BIGLOCK(d); + rc = (d->vcpu[vcpuid] == NULL) ? boot_vcpu(d, vcpuid, ctxt) : -EEXIST; + UNLOCK_BIGLOCK(d); + + xfree(ctxt); + break; + + case VCPUOP_up: + if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) ) + vcpu_wake(v); + break; + + case VCPUOP_down: + if ( !test_and_set_bit(_VCPUF_down, &v->vcpu_flags) ) + vcpu_sleep_nosync(v); + break; + + case VCPUOP_is_up: + rc = !test_bit(_VCPUF_down, &v->vcpu_flags); + break; + } + return rc; } diff -r d79ab87e27b8 -r abfc9808adb9 xen/common/sched_sedf.c --- a/xen/common/sched_sedf.c Mon Oct 3 15:40:27 2005 +++ b/xen/common/sched_sedf.c Tue Oct 4 13:22:30 2005 @@ -500,9 +500,15 @@ curinf->vcpu->domain->domain_id, curinf->vcpu->vcpu_id); __del_from_queue(curinf->vcpu); - + /*move them to their next period*/ curinf->deadl_abs += curinf->period; + /*ensure that the start of the next period is in the future*/ + if (unlikely(PERIOD_BEGIN(curinf) < now)) { + curinf->deadl_abs += + (DIV_UP(now - PERIOD_BEGIN(curinf), + curinf->period)) * curinf->period; + } /*and put them back into the queue*/ __add_to_waitqueue_sort(curinf->vcpu); continue; @@ -645,7 +651,7 @@ s_time_t end_xt, struct list_head *extraq[], int cpu) { struct task_slice ret; struct sedf_vcpu_info *runinf; - + ASSERT(end_xt > now); /* Enough time left to use for extratime? */ if (end_xt - now < EXTRA_QUANTUM) goto return_idle; diff -r d79ab87e27b8 -r abfc9808adb9 xen/common/schedule.c --- a/xen/common/schedule.c Mon Oct 3 15:40:27 2005 +++ b/xen/common/schedule.c Tue Oct 4 13:22:30 2005 @@ -270,69 +270,6 @@ return 0; } -/* Mark target vcpu as non-runnable so it is not scheduled */ -static long do_vcpu_down(int vcpu) -{ - struct vcpu *target; - - if ( vcpu > MAX_VIRT_CPUS ) - return -EINVAL; - - target = current->domain->vcpu[vcpu]; - if ( target == NULL ) - return -ESRCH; - set_bit(_VCPUF_down, &target->vcpu_flags); - - return 0; -} - -/* Mark target vcpu as runnable and wake it */ -static long do_vcpu_up(int vcpu) -{ - struct vcpu *target; - - if (vcpu > MAX_VIRT_CPUS) - return -EINVAL; - - target = current->domain->vcpu[vcpu]; - if ( target == NULL ) - return -ESRCH; - clear_bit(_VCPUF_down, &target->vcpu_flags); - /* wake vcpu */ - vcpu_wake(target); - - 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, unsigned long arg) { long ret = 0; @@ -359,21 +296,6 @@ domain_shutdown((u8)(op >> SCHEDOP_reasonshift)); break; } - case SCHEDOP_vcpu_down: - { - ret = do_vcpu_down((int)(op >> SCHEDOP_vcpushift)); - break; - } - 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; - } default: ret = -ENOSYS; @@ -395,8 +317,8 @@ return 0; } -/** sched_id - fetch ID of current scheduler */ -int sched_id() +/* sched_id - fetch ID of current scheduler */ +int sched_id(void) { return ops.sched_id; } diff -r d79ab87e27b8 -r abfc9808adb9 xen/include/public/xen.h --- a/xen/include/public/xen.h Mon Oct 3 15:40:27 2005 +++ b/xen/include/public/xen.h Tue Oct 4 13:22:30 2005 @@ -55,7 +55,7 @@ #define __HYPERVISOR_update_va_mapping_otherdomain 22 #define __HYPERVISOR_switch_vm86 23 /* x86/32 only */ #define __HYPERVISOR_switch_to_user 23 /* x86/64 only */ -#define __HYPERVISOR_boot_vcpu 24 +#define __HYPERVISOR_vcpu_op 24 #define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ #define __HYPERVISOR_mmuext_op 26 #define __HYPERVISOR_acm_op 27 @@ -201,12 +201,8 @@ #define SCHEDOP_yield 0 /* Give up the CPU voluntarily. */ #define SCHEDOP_block 1 /* Block until an event is received. */ #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) */ /* * Reason codes for SCHEDOP_shutdown. These may be interpreted by control diff -r d79ab87e27b8 -r abfc9808adb9 xen/include/public/vcpu.h --- /dev/null Mon Oct 3 15:40:27 2005 +++ b/xen/include/public/vcpu.h Tue Oct 4 13:22:30 2005 @@ -0,0 +1,55 @@ +/****************************************************************************** + * vcpu.h + * + * VCPU creation and hotplug. + * + * Copyright (c) 2005, Keir Fraser <keir@xxxxxxxxxxxxx> + */ + +#ifndef __XEN_PUBLIC_VCPU_H__ +#define __XEN_PUBLIC_VCPU_H__ + +/* + * Prototype for this hypercall is: + * int vcpu_op(int cmd, int vcpuid, void *extra_args) + * @cmd == VCPUOP_??? (VCPU operation). + * @vcpuid == VCPU to operate on. + * @extra_args == Operation-specific extra arguments (NULL if none). + */ + +/* + * Create a new VCPU. This must be called before a VCPU can be referred to + * in any other hypercall (e.g., to bind event channels). The new VCPU + * will not run until it is brought up by VCPUOP_up. + * + * @extra_arg == pointer to vcpu_guest_context structure containing initial + * state for the new VCPU. + */ +#define VCPUOP_create 0 + +/* + * Bring up a newly-created or previously brought-down VCPU. This makes the + * VCPU runnable. + */ +#define VCPUOP_up 1 + +/* + * Bring down a VCPU (i.e., make it non-runnable). + * There are a few caveats that callers should observe: + * 1. This operation may return, and VCPU_is_up may return false, before the + * VCPU stops running (i.e., the command is asynchronous). It is a good + * idea to ensure that the VCPU has entered a non-critical loop before + * bringing it down. Alternatively, this operation is guaranteed + * synchronous if invoked by the VCPU itself. + * 2. After a VCPU is created, there is currently no way to drop all its + * references to domain memory. Even a VCPU that is down still holds + * memory references via its pagetable base pointer and GDT. It is good + * practise to move a VCPU onto an 'idle' or default page table, LDT and + * GDT before bringing it down. + */ +#define VCPUOP_down 2 + +/* Returns 1 if the given VCPU is up. */ +#define VCPUOP_is_up 3 + +#endif /* __XEN_PUBLIC_VCPU_H__ */ diff -r d79ab87e27b8 -r abfc9808adb9 linux-2.6-xen-sparse/include/asm-generic/pgtable.h --- a/linux-2.6-xen-sparse/include/asm-generic/pgtable.h Mon Oct 3 15:40:27 2005 +++ /dev/null Tue Oct 4 13:22:30 2005 @@ -1,221 +0,0 @@ -#ifndef _ASM_GENERIC_PGTABLE_H -#define _ASM_GENERIC_PGTABLE_H - -#ifndef __HAVE_ARCH_PTEP_ESTABLISH -/* - * Establish a new mapping: - * - flush the old one - * - update the page tables - * - inform the TLB about the new one - * - * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock. - * - * Note: the old pte is known to not be writable, so we don't need to - * worry about dirty bits etc getting lost. - */ -#ifndef __HAVE_ARCH_SET_PTE_ATOMIC -#define ptep_establish(__vma, __address, __ptep, __entry) \ -do { \ - set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \ - flush_tlb_page(__vma, __address); \ -} while (0) -#else /* __HAVE_ARCH_SET_PTE_ATOMIC */ -#define ptep_establish(__vma, __address, __ptep, __entry) \ -do { \ - set_pte_atomic(__ptep, __entry); \ - flush_tlb_page(__vma, __address); \ -} while (0) -#endif /* __HAVE_ARCH_SET_PTE_ATOMIC */ -#endif - -#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS -/* - * Largely same as above, but only sets the access flags (dirty, - * accessed, and writable). Furthermore, we know it always gets set - * to a "more permissive" setting, which allows most architectures - * to optimize this. - */ -#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ -do { \ - set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \ - flush_tlb_page(__vma, __address); \ -} while (0) -#endif - -#ifndef __HAVE_ARCH_PTEP_ESTABLISH_NEW -/* - * Establish a mapping where none previously existed - */ -#define ptep_establish_new(__vma, __address, __ptep, __entry) \ -do { \ - set_pte(__ptep, __entry); \ -} while (0) -#endif - -#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG -#define ptep_test_and_clear_young(__vma, __address, __ptep) \ -({ \ - pte_t __pte = *(__ptep); \ - int r = 1; \ - if (!pte_young(__pte)) \ - r = 0; \ - else \ - set_pte_at((__vma)->vm_mm, (__address), \ - (__ptep), pte_mkold(__pte)); \ - r; \ -}) -#endif - -#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH -#define ptep_clear_flush_young(__vma, __address, __ptep) \ -({ \ - int __young; \ - __young = ptep_test_and_clear_young(__vma, __address, __ptep); \ - if (__young) \ - flush_tlb_page(__vma, __address); \ - __young; \ -}) -#endif - -#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY -#define ptep_test_and_clear_dirty(__vma, __address, __ptep) \ -({ \ - pte_t __pte = *__ptep; \ - int r = 1; \ - if (!pte_dirty(__pte)) \ - r = 0; \ - else \ - set_pte_at((__vma)->vm_mm, (__address), (__ptep), \ - pte_mkclean(__pte)); \ - r; \ -}) -#endif - -#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH -#define ptep_clear_flush_dirty(__vma, __address, __ptep) \ -({ \ - int __dirty; \ - __dirty = ptep_test_and_clear_dirty(__vma, __address, __ptep); \ - if (__dirty) \ - flush_tlb_page(__vma, __address); \ - __dirty; \ -}) -#endif - -#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR -#define ptep_get_and_clear(__mm, __address, __ptep) \ -({ \ - pte_t __pte = *(__ptep); \ - pte_clear((__mm), (__address), (__ptep)); \ - __pte; \ -}) -#endif - -#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH -#define ptep_clear_flush(__vma, __address, __ptep) \ -({ \ - pte_t __pte; \ - __pte = ptep_get_and_clear((__vma)->vm_mm, __address, __ptep); \ - flush_tlb_page(__vma, __address); \ - __pte; \ -}) -#endif - -#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT -static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep) -{ - pte_t old_pte = *ptep; - set_pte_at(mm, address, ptep, pte_wrprotect(old_pte)); -} -#endif - -#ifndef __HAVE_ARCH_PTE_SAME -#define pte_same(A,B) (pte_val(A) == pte_val(B)) -#endif - -#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY -#define page_test_and_clear_dirty(page) (0) -#endif - -#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG -#define page_test_and_clear_young(page) (0) -#endif - -#ifndef __HAVE_ARCH_PGD_OFFSET_GATE -#define pgd_offset_gate(mm, addr) pgd_offset(mm, addr) -#endif - -#ifndef __HAVE_ARCH_LAZY_MMU_PROT_UPDATE -#define lazy_mmu_prot_update(pte) do { } while (0) -#endif - -/* - * When walking page tables, get the address of the next boundary, - * or the end address of the range if that comes earlier. Although no - * vma end wraps to 0, rounded up __boundary may wrap to 0 throughout. - */ - -#define pgd_addr_end(addr, end) \ -({ unsigned long __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \ - (__boundary - 1 < (end) - 1)? __boundary: (end); \ -}) - -#ifndef pud_addr_end -#define pud_addr_end(addr, end) \ -({ unsigned long __boundary = ((addr) + PUD_SIZE) & PUD_MASK; \ - (__boundary - 1 < (end) - 1)? __boundary: (end); \ -}) -#endif - -#ifndef pmd_addr_end -#define pmd_addr_end(addr, end) \ -({ unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \ - (__boundary - 1 < (end) - 1)? __boundary: (end); \ -}) -#endif - -#ifndef __ASSEMBLY__ -/* - * When walking page tables, we usually want to skip any p?d_none entries; - * and any p?d_bad entries - reporting the error before resetting to none. - * Do the tests inline, but report and clear the bad entry in mm/memory.c. - */ -void pgd_clear_bad(pgd_t *); -void pud_clear_bad(pud_t *); -void pmd_clear_bad(pmd_t *); - -static inline int pgd_none_or_clear_bad(pgd_t *pgd) -{ - if (pgd_none(*pgd)) - return 1; - if (unlikely(pgd_bad(*pgd))) { - pgd_clear_bad(pgd); - return 1; - } - return 0; -} - -static inline int pud_none_or_clear_bad(pud_t *pud) -{ - if (pud_none(*pud)) - return 1; - if (unlikely(pud_bad(*pud))) { - pud_clear_bad(pud); - return 1; - } - return 0; -} - -static inline int pmd_none_or_clear_bad(pmd_t *pmd) -{ - if (pmd_none(*pmd)) - return 1; - if (unlikely(pmd_bad(*pmd))) { - pmd_clear_bad(pmd); - return 1; - } - return 0; -} -#endif /* !__ASSEMBLY__ */ - -#endif /* _ASM_GENERIC_PGTABLE_H */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |