# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID bf6119a5865514ba9dcfecb23e505049437e9c2c
# Parent f22fba6731968547f2826e78005c8466e4f14847
Do not pickle vcpu state on save/restore. We can construct
suitable initial state for each vcpu during restore, without
need for pickle/unpickle.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r f22fba673196 -r bf6119a58655
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
09:26:29 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Mon Oct 3
14:02:23 2005
@@ -141,6 +141,13 @@
}
#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
* done, so just try to conserve power and have a
diff -r f22fba673196 -r bf6119a58655
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
09:26:29 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Mon Oct 3
14:02:23 2005
@@ -802,7 +802,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 +852,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. */
@@ -1585,61 +1578,48 @@
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_boot_vcpu(vcpu, &ctxt);
+}
diff -r f22fba673196 -r bf6119a58655
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 09:26:29 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Mon Oct 3 14:02:23 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 f22fba673196 -r bf6119a58655
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Mon Oct 3 09:26:29 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Mon Oct 3 14:02:23 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 f22fba673196 -r bf6119a58655
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
09:26:29 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Mon Oct 3
14:02:23 2005
@@ -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. */
@@ -1267,13 +1261,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 f22fba673196 -r bf6119a58655
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
09:26:29 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c Mon Oct 3
14:02:23 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;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|