ia64/xen-unstable

changeset 6482:b3785cbb723b

Simplify and fix SMP irq and ipi teardown/setup on suspend/resume.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Mon Aug 29 17:40:47 2005 +0000 (2005-08-29)
parents 70be155e9e9c
children 834466f56fc3 a698bd49931b
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/kernel/evtchn.c linux-2.6-xen-sparse/arch/xen/kernel/reboot.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c	Mon Aug 29 17:15:56 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c	Mon Aug 29 17:40:47 2005 +0000
     1.3 @@ -135,6 +135,10 @@ static inline void play_dead(void)
     1.4   * low exit latency (ie sit in a loop waiting for
     1.5   * somebody to say that they'd like to reschedule)
     1.6   */
     1.7 +#ifdef CONFIG_SMP
     1.8 +extern void smp_suspend(void);
     1.9 +extern void smp_resume(void);
    1.10 +#endif
    1.11  void cpu_idle (void)
    1.12  {
    1.13  	int cpu = _smp_processor_id();
    1.14 @@ -149,6 +153,9 @@ void cpu_idle (void)
    1.15  
    1.16  			if (cpu_is_offline(cpu)) {
    1.17  				local_irq_disable();
    1.18 +#ifdef CONFIG_SMP
    1.19 +				smp_suspend();
    1.20 +#endif
    1.21  #if defined(CONFIG_XEN) && defined(CONFIG_HOTPLUG_CPU)
    1.22  				/* Ack it.  From this point on until
    1.23  				   we get woken up, we're not allowed
    1.24 @@ -159,6 +166,9 @@ void cpu_idle (void)
    1.25  				HYPERVISOR_vcpu_down(cpu);
    1.26  #endif
    1.27  				play_dead();
    1.28 +#ifdef CONFIG_SMP
    1.29 +				smp_resume();
    1.30 +#endif
    1.31  				local_irq_enable();
    1.32  			}
    1.33  
    1.34 @@ -789,10 +799,3 @@ unsigned long arch_align_stack(unsigned 
    1.35  		sp -= get_random_int() % 8192;
    1.36  	return sp & ~0xf;
    1.37  }
    1.38 -
    1.39 -
    1.40 -#ifndef CONFIG_X86_SMP
    1.41 -void _restore_vcpu(void)
    1.42 -{
    1.43 -}
    1.44 -#endif
     2.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Mon Aug 29 17:15:56 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Mon Aug 29 17:40:47 2005 +0000
     2.3 @@ -1601,32 +1601,71 @@ extern void local_teardown_timer_irq(voi
     2.4  
     2.5  void smp_suspend(void)
     2.6  {
     2.7 -	/* XXX todo: take down time and ipi's on all cpus */
     2.8  	local_teardown_timer_irq();
     2.9  	smp_intr_exit();
    2.10  }
    2.11  
    2.12  void smp_resume(void)
    2.13  {
    2.14 -	/* XXX todo: restore time and ipi's on all cpus */
    2.15  	smp_intr_init();
    2.16  	local_setup_timer_irq();
    2.17  }
    2.18  
    2.19 -DECLARE_PER_CPU(int, timer_irq);
    2.20 -
    2.21 -void _restore_vcpu(void)
    2.22 -{
    2.23 -	int cpu = smp_processor_id();
    2.24 -	extern atomic_t vcpus_rebooting;
    2.25 +static atomic_t vcpus_rebooting;
    2.26  
    2.27 -	/* We are the first thing the vcpu runs when it comes back,
    2.28 -	   and we are supposed to restore the IPIs and timer
    2.29 -	   interrupts etc.  When we return, the vcpu's idle loop will
    2.30 -	   start up again. */
    2.31 -	_bind_virq_to_irq(VIRQ_TIMER, cpu, per_cpu(timer_irq, cpu));
    2.32 -	_bind_virq_to_irq(VIRQ_DEBUG, cpu, per_cpu(ldebug_irq, cpu));
    2.33 -	_bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu, per_cpu(resched_irq, cpu) );
    2.34 -	_bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu, per_cpu(callfunc_irq, cpu) );
    2.35 +static void restore_vcpu_ready(void)
    2.36 +{
    2.37 +
    2.38  	atomic_dec(&vcpus_rebooting);
    2.39  }
    2.40 +
    2.41 +void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
    2.42 +{
    2.43 +	int r;
    2.44 +	int gdt_pages;
    2.45 +	r = HYPERVISOR_vcpu_pickle(vcpu, ctxt);
    2.46 +	if (r != 0)
    2.47 +		panic("pickling vcpu %d -> %d!\n", vcpu, r);
    2.48 +
    2.49 +	/* Translate from machine to physical addresses where necessary,
    2.50 +	   so that they can be translated to our new machine address space
    2.51 +	   after resume.  libxc is responsible for doing this to vcpu0,
    2.52 +	   but we do it to the others. */
    2.53 +	gdt_pages = (ctxt->gdt_ents + 511) / 512;
    2.54 +	ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]);
    2.55 +	for (r = 0; r < gdt_pages; r++)
    2.56 +		ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]);
    2.57 +}
    2.58 +
    2.59 +int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
    2.60 +{
    2.61 +	int r;
    2.62 +	int gdt_pages = (ctxt->gdt_ents + 511) / 512;
    2.63 +
    2.64 +	/* This is kind of a hack, and implicitly relies on the fact that
    2.65 +	   the vcpu stops in a place where all of the call clobbered
    2.66 +	   registers are already dead. */
    2.67 +	ctxt->user_regs.esp -= 4;
    2.68 +	((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip;
    2.69 +	ctxt->user_regs.eip = (unsigned long)restore_vcpu_ready;
    2.70 +
    2.71 +	/* De-canonicalise.  libxc handles this for vcpu 0, but we need
    2.72 +	   to do it for the other vcpus. */
    2.73 +	ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]);
    2.74 +	for (r = 0; r < gdt_pages; r++)
    2.75 +		ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]);
    2.76 +
    2.77 +	atomic_set(&vcpus_rebooting, 1);
    2.78 +	r = HYPERVISOR_boot_vcpu(vcpu, ctxt);
    2.79 +	if (r != 0) {
    2.80 +		printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r);
    2.81 +		return -1;
    2.82 +	}
    2.83 +
    2.84 +	/* Make sure we wait for the new vcpu to come up before trying to do
    2.85 +	   anything with it or starting the next one. */
    2.86 +	while (atomic_read(&vcpus_rebooting))
    2.87 +		barrier();
    2.88 +
    2.89 +	return 0;
    2.90 +}
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c	Mon Aug 29 17:15:56 2005 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c	Mon Aug 29 17:40:47 2005 +0000
     3.3 @@ -245,74 +245,6 @@ void unbind_virq_from_irq(int virq)
     3.4      spin_unlock(&irq_mapping_update_lock);
     3.5  }
     3.6  
     3.7 -/* This is only used when a vcpu from an xm save.  The ipi is expected
     3.8 -   to have been bound before we suspended, and so all of the xenolinux
     3.9 -   state is set up; we only need to restore the Xen side of things.
    3.10 -   The irq number has to be the same, but the evtchn number can
    3.11 -   change. */
    3.12 -void _bind_ipi_to_irq(int ipi, int vcpu, int irq)
    3.13 -{
    3.14 -    evtchn_op_t op;
    3.15 -    int evtchn;
    3.16 -
    3.17 -    spin_lock(&irq_mapping_update_lock);
    3.18 -
    3.19 -    op.cmd = EVTCHNOP_bind_ipi;
    3.20 -    if ( HYPERVISOR_event_channel_op(&op) != 0 )
    3.21 -	panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, vcpu);
    3.22 -    evtchn = op.u.bind_ipi.port;
    3.23 -
    3.24 -    printk("<0>IPI %d, old evtchn %d, evtchn %d.\n",
    3.25 -	   ipi, per_cpu(ipi_to_evtchn, vcpu)[ipi],
    3.26 -	   evtchn);
    3.27 -
    3.28 -    evtchn_to_irq[irq_to_evtchn[irq]] = -1;
    3.29 -    irq_to_evtchn[irq] = -1;
    3.30 -
    3.31 -    evtchn_to_irq[evtchn] = irq;
    3.32 -    irq_to_evtchn[irq]    = evtchn;
    3.33 -
    3.34 -    printk("<0>evtchn_to_irq[%d] = %d.\n", evtchn,
    3.35 -	   evtchn_to_irq[evtchn]);
    3.36 -    per_cpu(ipi_to_evtchn, vcpu)[ipi] = evtchn;
    3.37 -
    3.38 -    bind_evtchn_to_cpu(evtchn, vcpu);
    3.39 -
    3.40 -    spin_unlock(&irq_mapping_update_lock);
    3.41 -
    3.42 -    clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask);
    3.43 -    clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending);
    3.44 -}
    3.45 -
    3.46 -void _bind_virq_to_irq(int virq, int cpu, int irq)
    3.47 -{
    3.48 -    evtchn_op_t op;
    3.49 -    int evtchn;
    3.50 -
    3.51 -    spin_lock(&irq_mapping_update_lock);
    3.52 -
    3.53 -    op.cmd              = EVTCHNOP_bind_virq;
    3.54 -    op.u.bind_virq.virq = virq;
    3.55 -    if ( HYPERVISOR_event_channel_op(&op) != 0 )
    3.56 -            panic("Failed to bind virtual IRQ %d\n", virq);
    3.57 -    evtchn = op.u.bind_virq.port;
    3.58 -
    3.59 -    evtchn_to_irq[irq_to_evtchn[irq]] = -1;
    3.60 -    irq_to_evtchn[irq] = -1;
    3.61 -
    3.62 -    evtchn_to_irq[evtchn] = irq;
    3.63 -    irq_to_evtchn[irq]    = evtchn;
    3.64 -
    3.65 -    per_cpu(virq_to_irq, cpu)[virq] = irq;
    3.66 -
    3.67 -    bind_evtchn_to_cpu(evtchn, cpu);
    3.68 -
    3.69 -    spin_unlock(&irq_mapping_update_lock);
    3.70 -
    3.71 -    clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask);
    3.72 -    clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending);
    3.73 -}
    3.74 -
    3.75  int bind_ipi_to_irq(int ipi)
    3.76  {
    3.77      evtchn_op_t op;
     4.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Mon Aug 29 17:15:56 2005 +0000
     4.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Mon Aug 29 17:40:47 2005 +0000
     4.3 @@ -66,60 +66,6 @@ static int shutting_down = SHUTDOWN_INVA
     4.4  #endif
     4.5  
     4.6  #ifdef CONFIG_SMP
     4.7 -static void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
     4.8 -{
     4.9 -    int r;
    4.10 -    int gdt_pages;
    4.11 -    r = HYPERVISOR_vcpu_pickle(vcpu, ctxt);
    4.12 -    if (r != 0)
    4.13 -	panic("pickling vcpu %d -> %d!\n", vcpu, r);
    4.14 -
    4.15 -    /* Translate from machine to physical addresses where necessary,
    4.16 -       so that they can be translated to our new machine address space
    4.17 -       after resume.  libxc is responsible for doing this to vcpu0,
    4.18 -       but we do it to the others. */
    4.19 -    gdt_pages = (ctxt->gdt_ents + 511) / 512;
    4.20 -    ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]);
    4.21 -    for (r = 0; r < gdt_pages; r++)
    4.22 -	ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]);
    4.23 -}
    4.24 -
    4.25 -void _restore_vcpu(int cpu);
    4.26 -
    4.27 -atomic_t vcpus_rebooting;
    4.28 -
    4.29 -static int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
    4.30 -{
    4.31 -    int r;
    4.32 -    int gdt_pages = (ctxt->gdt_ents + 511) / 512;
    4.33 -
    4.34 -    /* This is kind of a hack, and implicitly relies on the fact that
    4.35 -       the vcpu stops in a place where all of the call clobbered
    4.36 -       registers are already dead. */
    4.37 -    ctxt->user_regs.esp -= 4;
    4.38 -    ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip;
    4.39 -    ctxt->user_regs.eip = (unsigned long)_restore_vcpu;
    4.40 -
    4.41 -    /* De-canonicalise.  libxc handles this for vcpu 0, but we need
    4.42 -       to do it for the other vcpus. */
    4.43 -    ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]);
    4.44 -    for (r = 0; r < gdt_pages; r++)
    4.45 -	ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]);
    4.46 -
    4.47 -    atomic_set(&vcpus_rebooting, 1);
    4.48 -    r = HYPERVISOR_boot_vcpu(vcpu, ctxt);
    4.49 -    if (r != 0) {
    4.50 -	printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r);
    4.51 -	return -1;
    4.52 -    }
    4.53 -
    4.54 -    /* Make sure we wait for the new vcpu to come up before trying to do
    4.55 -       anything with it or starting the next one. */
    4.56 -    while (atomic_read(&vcpus_rebooting))
    4.57 -	barrier();
    4.58 -
    4.59 -    return 0;
    4.60 -}
    4.61  #endif
    4.62  
    4.63  static int __do_suspend(void *ignore)
    4.64 @@ -139,18 +85,20 @@ static int __do_suspend(void *ignore)
    4.65      extern int gnttab_suspend(void);
    4.66      extern int gnttab_resume(void);
    4.67  
    4.68 -#ifdef CONFIG_SMP
    4.69 -    extern void smp_suspend(void);
    4.70 -    extern void smp_resume(void);
    4.71 -#endif
    4.72      extern void time_suspend(void);
    4.73      extern void time_resume(void);
    4.74      extern unsigned long max_pfn;
    4.75      extern unsigned int *pfn_to_mfn_frame_list;
    4.76  
    4.77  #ifdef CONFIG_SMP
    4.78 +    extern void smp_suspend(void);
    4.79 +    extern void smp_resume(void);
    4.80 +
    4.81      static vcpu_guest_context_t suspended_cpu_records[NR_CPUS];
    4.82      cpumask_t prev_online_cpus, prev_present_cpus;
    4.83 +
    4.84 +    void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
    4.85 +    int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
    4.86  #endif
    4.87  
    4.88      int err = 0;
     5.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c	Mon Aug 29 17:15:56 2005 +0000
     5.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c	Mon Aug 29 17:40:47 2005 +0000
     5.3 @@ -1277,21 +1277,23 @@ extern void local_teardown_timer_irq(voi
     5.4  
     5.5  void smp_suspend(void)
     5.6  {
     5.7 -	/* XXX todo: take down time and ipi's on all cpus */
     5.8  	local_teardown_timer_irq();
     5.9  	smp_intr_exit();
    5.10  }
    5.11  
    5.12  void smp_resume(void)
    5.13  {
    5.14 -	/* XXX todo: restore time and ipi's on all cpus */
    5.15  	smp_intr_init();
    5.16  	local_setup_timer_irq();
    5.17  }
    5.18  
    5.19 -void _restore_vcpu(void)
    5.20 +void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
    5.21  {
    5.22 -	/* XXX need to write this */
    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