# 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
|