ia64/xen-unstable

changeset 7167:bf6119a58655

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@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Oct 03 15:02:23 2005 +0100 (2005-10-03)
parents f22fba673196
children a9dce0ffc901
files linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c linux-2.6-xen-sparse/arch/xen/kernel/reboot.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c	Mon Oct 03 10:26:29 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c	Mon Oct 03 15:02:23 2005 +0100
     1.3 @@ -141,6 +141,13 @@ static inline void play_dead(void)
     1.4  }
     1.5  #endif /* CONFIG_HOTPLUG_CPU */
     1.6  
     1.7 +void cpu_restore(void)
     1.8 +{
     1.9 +	play_dead();
    1.10 +	local_irq_enable();
    1.11 +	cpu_idle();
    1.12 +}
    1.13 +
    1.14  /*
    1.15   * The idle thread. There's no useful work to be
    1.16   * done, so just try to conserve power and have a
     2.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Mon Oct 03 10:26:29 2005 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Mon Oct 03 15:02:23 2005 +0100
     2.3 @@ -802,7 +802,6 @@ static int __init do_boot_cpu(int apicid
     2.4  	extern void hypervisor_callback(void);
     2.5  	extern void failsafe_callback(void);
     2.6  	extern void smp_trap_init(trap_info_t *);
     2.7 -	int i;
     2.8  
     2.9  	cpu = ++cpucount;
    2.10  	/*
    2.11 @@ -853,12 +852,6 @@ static int __init do_boot_cpu(int apicid
    2.12  	/* FPU is set up to default initial state. */
    2.13  	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
    2.14  
    2.15 -	/* Virtual IDT is empty at start-of-day. */
    2.16 -	for ( i = 0; i < 256; i++ )
    2.17 -	{
    2.18 -		ctxt.trap_ctxt[i].vector = i;
    2.19 -		ctxt.trap_ctxt[i].cs     = FLAT_KERNEL_CS;
    2.20 -	}
    2.21  	smp_trap_init(ctxt.trap_ctxt);
    2.22  
    2.23  	/* No LDT. */
    2.24 @@ -1585,61 +1578,48 @@ void smp_resume(void)
    2.25  	local_setup_timer_irq();
    2.26  }
    2.27  
    2.28 -static atomic_t vcpus_rebooting;
    2.29 -
    2.30 -static void restore_vcpu_ready(void)
    2.31 -{
    2.32 -
    2.33 -	atomic_dec(&vcpus_rebooting);
    2.34 -}
    2.35 -
    2.36 -void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
    2.37 -{
    2.38 -	int r;
    2.39 -	int gdt_pages;
    2.40 -	r = HYPERVISOR_vcpu_pickle(vcpu, ctxt);
    2.41 -	if (r != 0)
    2.42 -		panic("pickling vcpu %d -> %d!\n", vcpu, r);
    2.43 -
    2.44 -	/* Translate from machine to physical addresses where necessary,
    2.45 -	   so that they can be translated to our new machine address space
    2.46 -	   after resume.  libxc is responsible for doing this to vcpu0,
    2.47 -	   but we do it to the others. */
    2.48 -	gdt_pages = (ctxt->gdt_ents + 511) / 512;
    2.49 -	ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]);
    2.50 -	for (r = 0; r < gdt_pages; r++)
    2.51 -		ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]);
    2.52 -}
    2.53 -
    2.54 -int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
    2.55 +void vcpu_prepare(int vcpu)
    2.56  {
    2.57 -	int r;
    2.58 -	int gdt_pages = (ctxt->gdt_ents + 511) / 512;
    2.59 +	extern void hypervisor_callback(void);
    2.60 +	extern void failsafe_callback(void);
    2.61 +	extern void smp_trap_init(trap_info_t *);
    2.62 +	extern void cpu_restore(void);
    2.63 +	vcpu_guest_context_t ctxt;
    2.64 +	struct task_struct *idle = idle_task(vcpu);
    2.65 +
    2.66 +	if (vcpu == 0)
    2.67 +		return;
    2.68  
    2.69 -	/* This is kind of a hack, and implicitly relies on the fact that
    2.70 -	   the vcpu stops in a place where all of the call clobbered
    2.71 -	   registers are already dead. */
    2.72 -	ctxt->user_regs.esp -= 4;
    2.73 -	((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip;
    2.74 -	ctxt->user_regs.eip = (unsigned long)restore_vcpu_ready;
    2.75 +	memset(&ctxt, 0, sizeof(ctxt));
    2.76 +
    2.77 +	ctxt.user_regs.ds = __USER_DS;
    2.78 +	ctxt.user_regs.es = __USER_DS;
    2.79 +	ctxt.user_regs.fs = 0;
    2.80 +	ctxt.user_regs.gs = 0;
    2.81 +	ctxt.user_regs.ss = __KERNEL_DS;
    2.82 +	ctxt.user_regs.cs = __KERNEL_CS;
    2.83 +	ctxt.user_regs.eip = (unsigned long)cpu_restore;
    2.84 +	ctxt.user_regs.esp = idle->thread.esp;
    2.85 +	ctxt.user_regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_IOPL_RING1;
    2.86  
    2.87 -	/* De-canonicalise.  libxc handles this for vcpu 0, but we need
    2.88 -	   to do it for the other vcpus. */
    2.89 -	ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]);
    2.90 -	for (r = 0; r < gdt_pages; r++)
    2.91 -		ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]);
    2.92 +	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
    2.93 +
    2.94 +	smp_trap_init(ctxt.trap_ctxt);
    2.95 +
    2.96 +	ctxt.ldt_ents = 0;
    2.97 +
    2.98 +	ctxt.gdt_frames[0] = virt_to_mfn(cpu_gdt_descr[vcpu].address);
    2.99 +	ctxt.gdt_ents      = cpu_gdt_descr[vcpu].size / 8;
   2.100  
   2.101 -	atomic_set(&vcpus_rebooting, 1);
   2.102 -	r = HYPERVISOR_boot_vcpu(vcpu, ctxt);
   2.103 -	if (r != 0) {
   2.104 -		printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r);
   2.105 -		return -1;
   2.106 -	}
   2.107 +	ctxt.kernel_ss = __KERNEL_DS;
   2.108 +	ctxt.kernel_sp = idle->thread.esp0;
   2.109  
   2.110 -	/* Make sure we wait for the new vcpu to come up before trying to do
   2.111 -	   anything with it or starting the next one. */
   2.112 -	while (atomic_read(&vcpus_rebooting))
   2.113 -		barrier();
   2.114 +	ctxt.event_callback_cs     = __KERNEL_CS;
   2.115 +	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
   2.116 +	ctxt.failsafe_callback_cs  = __KERNEL_CS;
   2.117 +	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
   2.118  
   2.119 -	return 0;
   2.120 +	ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT;
   2.121 +
   2.122 +	(void)HYPERVISOR_boot_vcpu(vcpu, &ctxt);
   2.123  }
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c	Mon Oct 03 10:26:29 2005 +0100
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c	Mon Oct 03 15:02:23 2005 +0100
     3.3 @@ -1012,6 +1012,12 @@ void __init trap_init(void)
     3.4  void smp_trap_init(trap_info_t *trap_ctxt)
     3.5  {
     3.6  	trap_info_t *t = trap_table;
     3.7 +	int i;
     3.8 +
     3.9 +	for (i = 0; i < 256; i++) {
    3.10 +		trap_ctxt[i].vector = i;
    3.11 +		trap_ctxt[i].cs     = FLAT_KERNEL_CS;
    3.12 +	}
    3.13  
    3.14  	for (t = trap_table; t->address; t++) {
    3.15  		trap_ctxt[t->vector].flags = t->flags;
     4.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Mon Oct 03 10:26:29 2005 +0100
     4.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Mon Oct 03 15:02:23 2005 +0100
     4.3 @@ -74,11 +74,8 @@ static int __do_suspend(void *ignore)
     4.4  	extern unsigned long *pfn_to_mfn_frame_list[];
     4.5  
     4.6  #ifdef CONFIG_SMP
     4.7 -	static vcpu_guest_context_t suspended_cpu_records[NR_CPUS];
     4.8 -	cpumask_t prev_online_cpus, prev_present_cpus;
     4.9 -
    4.10 -	void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
    4.11 -	int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
    4.12 +	cpumask_t prev_online_cpus;
    4.13 +	int vcpu_prepare(int vcpu);
    4.14  #endif
    4.15  
    4.16  	extern void xencons_resume(void);
    4.17 @@ -132,16 +129,6 @@ static int __do_suspend(void *ignore)
    4.18  
    4.19  	preempt_enable();
    4.20  
    4.21 -#ifdef CONFIG_SMP
    4.22 -	cpus_clear(prev_present_cpus);
    4.23 -	for_each_present_cpu(i) {
    4.24 -		if (i == 0)
    4.25 -			continue;
    4.26 -		save_vcpu_context(i, &suspended_cpu_records[i]);
    4.27 -		cpu_set(i, prev_present_cpus);
    4.28 -	}
    4.29 -#endif
    4.30 -
    4.31  	gnttab_suspend();
    4.32  
    4.33  #ifdef __i386__
    4.34 @@ -189,11 +176,6 @@ static int __do_suspend(void *ignore)
    4.35  
    4.36  	time_resume();
    4.37  
    4.38 -#ifdef CONFIG_SMP
    4.39 -	for_each_cpu_mask(i, prev_present_cpus)
    4.40 -		restore_vcpu_context(i, &suspended_cpu_records[i]);
    4.41 -#endif
    4.42 -
    4.43  	__sti();
    4.44  
    4.45  	xencons_resume();
    4.46 @@ -201,6 +183,9 @@ static int __do_suspend(void *ignore)
    4.47  	xenbus_resume();
    4.48  
    4.49  #ifdef CONFIG_SMP
    4.50 +	for_each_present_cpu(i)
    4.51 +		vcpu_prepare(i);
    4.52 +
    4.53   out_reenable_cpus:
    4.54  	for_each_cpu_mask(i, prev_online_cpus) {
    4.55  		j = cpu_up(i);
     5.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c	Mon Oct 03 10:26:29 2005 +0100
     5.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c	Mon Oct 03 15:02:23 2005 +0100
     5.3 @@ -742,12 +742,6 @@ static int __cpuinit do_boot_cpu(int cpu
     5.4  	/* FPU is set up to default initial state. */
     5.5  	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
     5.6  
     5.7 -	/* Virtual IDT is empty at start-of-day. */
     5.8 -	for ( i = 0; i < 256; i++ )
     5.9 -	{
    5.10 -		ctxt.trap_ctxt[i].vector = i;
    5.11 -		ctxt.trap_ctxt[i].cs     = FLAT_KERNEL_CS;
    5.12 -	}
    5.13  	smp_trap_init(ctxt.trap_ctxt);
    5.14  
    5.15  	/* No LDT. */
    5.16 @@ -1267,13 +1261,8 @@ void smp_resume(void)
    5.17  	local_setup_timer_irq();
    5.18  }
    5.19  
    5.20 -void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
    5.21 +void vcpu_prepare(int vcpu)
    5.22  {
    5.23  }
    5.24  
    5.25 -int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
    5.26 -{
    5.27 -	return 0;
    5.28 -}
    5.29 -
    5.30  #endif
     6.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c	Mon Oct 03 10:26:29 2005 +0100
     6.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c	Mon Oct 03 15:02:23 2005 +0100
     6.3 @@ -956,6 +956,12 @@ void __init trap_init(void)
     6.4  void smp_trap_init(trap_info_t *trap_ctxt)
     6.5  {
     6.6  	trap_info_t *t = trap_table;
     6.7 +	int i;
     6.8 +
     6.9 +	for (i = 0; i < 256; i++) {
    6.10 +		trap_ctxt[i].vector = i;
    6.11 +		trap_ctxt[i].cs     = FLAT_KERNEL_CS;
    6.12 +	}
    6.13  
    6.14  	for (t = trap_table; t->address; t++) {
    6.15  		trap_ctxt[t->vector].flags = t->flags;