# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID b3785cbb723b8b355c1282232de0bd1cfbfb3556
# Parent 70be155e9e9cb5534c3e6d55aee3a4fbb28bf105
Simplify and fix SMP irq and ipi teardown/setup on suspend/resume.
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
diff -r 70be155e9e9c -r b3785cbb723b
linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Mon Aug 29
17:15:56 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Mon Aug 29
17:40:47 2005
@@ -135,6 +135,10 @@
* low exit latency (ie sit in a loop waiting for
* somebody to say that they'd like to reschedule)
*/
+#ifdef CONFIG_SMP
+extern void smp_suspend(void);
+extern void smp_resume(void);
+#endif
void cpu_idle (void)
{
int cpu = _smp_processor_id();
@@ -149,6 +153,9 @@
if (cpu_is_offline(cpu)) {
local_irq_disable();
+#ifdef CONFIG_SMP
+ smp_suspend();
+#endif
#if defined(CONFIG_XEN) && defined(CONFIG_HOTPLUG_CPU)
/* Ack it. From this point on until
we get woken up, we're not allowed
@@ -159,6 +166,9 @@
HYPERVISOR_vcpu_down(cpu);
#endif
play_dead();
+#ifdef CONFIG_SMP
+ smp_resume();
+#endif
local_irq_enable();
}
@@ -789,10 +799,3 @@
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
-
-
-#ifndef CONFIG_X86_SMP
-void _restore_vcpu(void)
-{
-}
-#endif
diff -r 70be155e9e9c -r b3785cbb723b
linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Mon Aug 29
17:15:56 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Mon Aug 29
17:40:47 2005
@@ -1601,32 +1601,71 @@
void smp_suspend(void)
{
- /* XXX todo: take down time and ipi's on all cpus */
local_teardown_timer_irq();
smp_intr_exit();
}
void smp_resume(void)
{
- /* XXX todo: restore time and ipi's on all cpus */
smp_intr_init();
local_setup_timer_irq();
}
-DECLARE_PER_CPU(int, timer_irq);
-
-void _restore_vcpu(void)
-{
- int cpu = smp_processor_id();
- extern atomic_t vcpus_rebooting;
-
- /* We are the first thing the vcpu runs when it comes back,
- and we are supposed to restore the IPIs and timer
- interrupts etc. When we return, the vcpu's idle loop will
- start up again. */
- _bind_virq_to_irq(VIRQ_TIMER, cpu, per_cpu(timer_irq, cpu));
- _bind_virq_to_irq(VIRQ_DEBUG, cpu, per_cpu(ldebug_irq, cpu));
- _bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu, per_cpu(resched_irq, cpu) );
- _bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu, per_cpu(callfunc_irq, cpu)
);
+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;
+}
diff -r 70be155e9e9c -r b3785cbb723b
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Mon Aug 29 17:15:56 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Mon Aug 29 17:40:47 2005
@@ -245,74 +245,6 @@
spin_unlock(&irq_mapping_update_lock);
}
-/* This is only used when a vcpu from an xm save. The ipi is expected
- to have been bound before we suspended, and so all of the xenolinux
- state is set up; we only need to restore the Xen side of things.
- The irq number has to be the same, but the evtchn number can
- change. */
-void _bind_ipi_to_irq(int ipi, int vcpu, int irq)
-{
- evtchn_op_t op;
- int evtchn;
-
- spin_lock(&irq_mapping_update_lock);
-
- op.cmd = EVTCHNOP_bind_ipi;
- if ( HYPERVISOR_event_channel_op(&op) != 0 )
- panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, vcpu);
- evtchn = op.u.bind_ipi.port;
-
- printk("<0>IPI %d, old evtchn %d, evtchn %d.\n",
- ipi, per_cpu(ipi_to_evtchn, vcpu)[ipi],
- evtchn);
-
- evtchn_to_irq[irq_to_evtchn[irq]] = -1;
- irq_to_evtchn[irq] = -1;
-
- evtchn_to_irq[evtchn] = irq;
- irq_to_evtchn[irq] = evtchn;
-
- printk("<0>evtchn_to_irq[%d] = %d.\n", evtchn,
- evtchn_to_irq[evtchn]);
- per_cpu(ipi_to_evtchn, vcpu)[ipi] = evtchn;
-
- bind_evtchn_to_cpu(evtchn, vcpu);
-
- spin_unlock(&irq_mapping_update_lock);
-
- clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask);
- clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending);
-}
-
-void _bind_virq_to_irq(int virq, int cpu, int irq)
-{
- evtchn_op_t op;
- int evtchn;
-
- spin_lock(&irq_mapping_update_lock);
-
- op.cmd = EVTCHNOP_bind_virq;
- op.u.bind_virq.virq = virq;
- if ( HYPERVISOR_event_channel_op(&op) != 0 )
- panic("Failed to bind virtual IRQ %d\n", virq);
- evtchn = op.u.bind_virq.port;
-
- evtchn_to_irq[irq_to_evtchn[irq]] = -1;
- irq_to_evtchn[irq] = -1;
-
- evtchn_to_irq[evtchn] = irq;
- irq_to_evtchn[irq] = evtchn;
-
- per_cpu(virq_to_irq, cpu)[virq] = irq;
-
- bind_evtchn_to_cpu(evtchn, cpu);
-
- spin_unlock(&irq_mapping_update_lock);
-
- clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask);
- clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending);
-}
-
int bind_ipi_to_irq(int ipi)
{
evtchn_op_t op;
diff -r 70be155e9e9c -r b3785cbb723b
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Mon Aug 29 17:15:56 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Mon Aug 29 17:40:47 2005
@@ -66,60 +66,6 @@
#endif
#ifdef CONFIG_SMP
-static 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]);
-}
-
-void _restore_vcpu(int cpu);
-
-atomic_t vcpus_rebooting;
-
-static 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;
-
- /* 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;
-}
#endif
static int __do_suspend(void *ignore)
@@ -139,18 +85,20 @@
extern int gnttab_suspend(void);
extern int gnttab_resume(void);
-#ifdef CONFIG_SMP
- extern void smp_suspend(void);
- extern void smp_resume(void);
-#endif
extern void time_suspend(void);
extern void time_resume(void);
extern unsigned long max_pfn;
extern unsigned int *pfn_to_mfn_frame_list;
#ifdef CONFIG_SMP
+ extern void smp_suspend(void);
+ extern void smp_resume(void);
+
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);
#endif
int err = 0;
diff -r 70be155e9e9c -r b3785cbb723b
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 Aug 29
17:15:56 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Mon Aug 29
17:40:47 2005
@@ -1277,21 +1277,23 @@
void smp_suspend(void)
{
- /* XXX todo: take down time and ipi's on all cpus */
local_teardown_timer_irq();
smp_intr_exit();
}
void smp_resume(void)
{
- /* XXX todo: restore time and ipi's on all cpus */
smp_intr_init();
local_setup_timer_irq();
}
-void _restore_vcpu(void)
-{
- /* XXX need to write this */
-}
-
-#endif
+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
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|