[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Cleanup CPU hotplug and save/restore. Next step is to



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 5a97ee0633e8e48c3d86fc007b8e0ea80a0581c9
# Parent  92c6021f23e4bb7fe1254f21d6a24d07d62f0e54
Cleanup CPU hotplug and save/restore. Next step is to
simplify SMP initial boot and then should be easy to merge
i386 and x86/64 smpboot.c.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 92c6021f23e4 -r 5a97ee0633e8 
linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c       Thu Oct 13 
14:26:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c       Thu Oct 13 
16:08:59 2005
@@ -112,44 +112,6 @@
        }
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-#include <asm/nmi.h>
-#ifdef CONFIG_SMP
-extern void smp_suspend(void);
-extern void smp_resume(void);
-#endif
-/* We don't actually take CPU down, just spin without interrupts. */
-static inline void play_dead(void)
-{
-       /* Death loop */
-       while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
-               HYPERVISOR_sched_op(SCHEDOP_yield, 0);
-
-       __flush_tlb_all();
-   /* 
-    * Restore IPI/IRQ mappings before marking online to prevent 
-    * race between pending interrupts and restoration of handler. 
-    */
-#ifdef CONFIG_SMP
-       local_irq_enable(); /* XXX Needed for smp_resume(). Clean me up. */
-       smp_resume();
-#endif
-       cpu_set(smp_processor_id(), cpu_online_map);
-}
-#else
-static inline void play_dead(void)
-{
-       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
  * done, so just try to conserve power and have a
@@ -158,7 +120,9 @@
  */
 void cpu_idle (void)
 {
+#if defined(CONFIG_HOTPLUG_CPU)
        int cpu = _smp_processor_id();
+#endif
 
        /* endless idle loop with no priority at all */
        while (1) {
@@ -168,23 +132,12 @@
                                __get_cpu_var(cpu_idle_state) = 0;
                        rmb();
 
+#if defined(CONFIG_HOTPLUG_CPU)
                        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
-                                  to take any locks.  In particular,
-                                  don't printk. */
-                               __get_cpu_var(cpu_state) = CPU_DEAD;
-                               /* Tell hypervisor to take vcpu down. */
                                HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL);
-#endif
-                               play_dead();
                                local_irq_enable();
                        }
+#endif
 
                        __get_cpu_var(irq_stat).idle_timestamp = jiffies;
                        xen_idle();
diff -r 92c6021f23e4 -r 5a97ee0633e8 
linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c       Thu Oct 13 
14:26:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c       Thu Oct 13 
16:08:59 2005
@@ -66,6 +66,9 @@
 #include <asm-xen/xen-public/vcpu.h>
 #include <asm-xen/xenbus.h>
 
+static void xen_smp_intr_init(unsigned int cpu);
+static void xen_smp_intr_exit(unsigned int cpu);
+
 /* Set if we find a B stepping CPU */
 static int __initdata smp_b_stepping;
 
@@ -352,9 +355,9 @@
 static void __init smp_callin(void)
 {
        int cpuid, phys_id;
+#if 0
        unsigned long timeout;
 
-#if 0
        /*
         * If waken up by an INIT in an 82489DX configuration
         * we may get here before an INIT-deassert IPI reaches
@@ -376,6 +379,7 @@
        }
        Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
 
+#if 0
        /*
         * STARTUP IPIs are fragile beasts as they might sometimes
         * trigger some glue motherboard logic. Complete APIC bus
@@ -403,7 +407,6 @@
                BUG();
        }
 
-#if 0
        /*
         * the boot CPU has finished the init stage and is spinning
         * on callin_map until we finish. We are free to set up this
@@ -448,8 +451,6 @@
 
 static int cpucount;
 
-extern void local_setup_timer(void);
-
 /*
  * Activate a secondary processor.
  */
@@ -464,8 +465,6 @@
        smp_callin();
        while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
                rep_nop();
-       local_setup_timer();
-       smp_intr_init();
        local_irq_enable();
        /*
         * low-memory mappings have been cleared, flush them from
@@ -1133,7 +1132,7 @@
                return;
        }
 
-       smp_intr_init();
+       xen_smp_intr_init(0);
 
 #if 0
        connect_bsp_APIC();
@@ -1340,29 +1339,6 @@
 
 subsys_initcall(setup_vcpu_hotplug_event);
 
-/* must be called with the cpucontrol mutex held */
-static int __devinit cpu_enable(unsigned int cpu)
-{
-#ifdef CONFIG_SMP_ALTERNATIVES
-       if (num_online_cpus() == 1)
-               prepare_for_smp();
-#endif
-
-       /* get the target out of its holding state */
-       per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
-       wmb();
-
-       /* wait for the processor to ack it. timeout? */
-       while (!cpu_online(cpu))
-               cpu_relax();
-
-       fixup_irqs(cpu_online_map);
-
-       /* counter the disable in fixup_irqs() */
-       local_irq_enable();
-       return 0;
-}
-
 int __cpu_disable(void)
 {
        cpumask_t map = cpu_online_map;
@@ -1385,27 +1361,22 @@
        /* It's now safe to remove this processor from the online map */
        cpu_clear(cpu, cpu_online_map);
 
+       return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+       while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
+               current->state = TASK_UNINTERRUPTIBLE;
+               schedule_timeout(HZ/10);
+       }
+
+       xen_smp_intr_exit(cpu);
+
 #ifdef CONFIG_SMP_ALTERNATIVES
        if (num_online_cpus() == 1)
                unprepare_for_smp();
 #endif
-
-       return 0;
-}
-
-void __cpu_die(unsigned int cpu)
-{
-       /* We don't do anything here: idle task is faking death itself. */
-       unsigned int i;
-
-       for (i = 0; i < 10; i++) {
-               /* They ack this in play_dead by setting CPU_DEAD */
-               if (per_cpu(cpu_state, cpu) == CPU_DEAD)
-                       return;
-               current->state = TASK_UNINTERRUPTIBLE;
-               schedule_timeout(HZ/10);
-       }
-       printk(KERN_ERR "CPU %u didn't die...\n", cpu);
 }
 
 #else /* ... !CONFIG_HOTPLUG_CPU */
@@ -1430,23 +1401,16 @@
                return -EIO;
        }
 
-#ifdef CONFIG_HOTPLUG_CPU
-#ifdef CONFIG_XEN
-       /* Tell hypervisor to bring vcpu up. */
+#ifdef CONFIG_SMP_ALTERNATIVES
+       if (num_online_cpus() == 1)
+               prepare_for_smp();
+#endif
+
+       xen_smp_intr_init(cpu);
+       cpu_set(cpu, smp_commenced_mask);
+       cpu_set(cpu, cpu_online_map);
        HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
-#endif
-       /* Already up, and in cpu_quiescent now? */
-       if (cpu_isset(cpu, smp_commenced_mask)) {
-               cpu_enable(cpu);
-               return 0;
-       }
-#endif
-
-       local_irq_enable();
-       /* Unleash the CPU! */
-       cpu_set(cpu, smp_commenced_mask);
-       while (!cpu_isset(cpu, cpu_online_map))
-               mb();
+
        return 0;
 }
 
@@ -1468,48 +1432,38 @@
 extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
 extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
 
-void smp_intr_init(void)
-{
-       int cpu = smp_processor_id();
-
+extern void local_setup_timer(unsigned int cpu);
+extern void local_teardown_timer(unsigned int cpu);
+
+static void xen_smp_intr_init(unsigned int cpu)
+{
        per_cpu(resched_irq, cpu) =
-               bind_ipi_to_irq(RESCHEDULE_VECTOR);
+               bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu);
        sprintf(resched_name[cpu], "resched%d", cpu);
        BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
                           SA_INTERRUPT, resched_name[cpu], NULL));
 
        per_cpu(callfunc_irq, cpu) =
-               bind_ipi_to_irq(CALL_FUNCTION_VECTOR);
+               bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu);
        sprintf(callfunc_name[cpu], "callfunc%d", cpu);
        BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
                           smp_call_function_interrupt,
                           SA_INTERRUPT, callfunc_name[cpu], NULL));
-}
-
-static void smp_intr_exit(void)
-{
-       int cpu = smp_processor_id();
+
+       if (cpu != 0)
+               local_setup_timer(cpu);
+}
+
+static void xen_smp_intr_exit(unsigned int cpu)
+{
+       if (cpu != 0)
+               local_teardown_timer(cpu);
 
        free_irq(per_cpu(resched_irq, cpu), NULL);
-       unbind_ipi_from_irq(RESCHEDULE_VECTOR);
+       unbind_ipi_from_irq(RESCHEDULE_VECTOR, cpu);
 
        free_irq(per_cpu(callfunc_irq, cpu), NULL);
-       unbind_ipi_from_irq(CALL_FUNCTION_VECTOR);
-}
-
-extern void local_setup_timer_irq(void);
-extern void local_teardown_timer_irq(void);
-
-void smp_suspend(void)
-{
-       local_teardown_timer_irq();
-       smp_intr_exit();
-}
-
-void smp_resume(void)
-{
-       smp_intr_init();
-       local_setup_timer();
+       unbind_ipi_from_irq(CALL_FUNCTION_VECTOR, cpu);
 }
 
 void vcpu_prepare(int vcpu)
@@ -1517,7 +1471,6 @@
        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);
 
@@ -1532,7 +1485,7 @@
        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.eip = (unsigned long)cpu_idle;
        ctxt.user_regs.esp = idle->thread.esp;
        ctxt.user_regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_IOPL_RING1;
 
@@ -1556,7 +1509,6 @@
        ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT;
 
        (void)HYPERVISOR_vcpu_op(VCPUOP_initialise, vcpu, &ctxt);
-       (void)HYPERVISOR_vcpu_op(VCPUOP_up, vcpu, NULL);
 }
 
 /*
diff -r 92c6021f23e4 -r 5a97ee0633e8 
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Thu Oct 13 14:26:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Thu Oct 13 16:08:59 2005
@@ -785,7 +785,7 @@
        rdtscll(vxtime.last_tsc);
 #endif
 
-       per_cpu(timer_irq, 0) = bind_virq_to_irq(VIRQ_TIMER);
+       per_cpu(timer_irq, 0) = bind_virq_to_irq(VIRQ_TIMER, 0);
        (void)setup_irq(per_cpu(timer_irq, 0), &irq_timer);
 }
 
@@ -852,21 +852,12 @@
 
 #ifdef CONFIG_SMP
 static char timer_name[NR_CPUS][15];
-void local_setup_timer_irq(void)
-{
-       int cpu = smp_processor_id();
-
-       if (cpu == 0)
-               return;
-       per_cpu(timer_irq, cpu) = bind_virq_to_irq(VIRQ_TIMER);
-       sprintf(timer_name[cpu], "timer%d", cpu);
-       BUG_ON(request_irq(per_cpu(timer_irq, cpu), timer_interrupt,
-                          SA_INTERRUPT, timer_name[cpu], NULL));
-}
-
-void local_setup_timer(void)
-{
-       int seq, cpu = smp_processor_id();
+
+void local_setup_timer(unsigned int cpu)
+{
+       int seq;
+
+       BUG_ON(cpu == 0);
 
        do {
                seq = read_seqbegin(&xtime_lock);
@@ -874,17 +865,17 @@
                        per_cpu(shadow_time, cpu).system_timestamp;
        } while (read_seqretry(&xtime_lock, seq));
 
-       local_setup_timer_irq();
-}
-
-void local_teardown_timer_irq(void)
-{
-       int cpu = smp_processor_id();
-
-       if (cpu == 0)
-               return;
+       per_cpu(timer_irq, cpu) = bind_virq_to_irq(VIRQ_TIMER, cpu);
+       sprintf(timer_name[cpu], "timer%d", cpu);
+       BUG_ON(request_irq(per_cpu(timer_irq, cpu), timer_interrupt,
+                          SA_INTERRUPT, timer_name[cpu], NULL));
+}
+
+void local_teardown_timer(unsigned int cpu)
+{
+       BUG_ON(cpu == 0);
        free_irq(per_cpu(timer_irq, cpu), NULL);
-       unbind_virq_from_irq(VIRQ_TIMER);
+       unbind_virq_from_irq(VIRQ_TIMER, cpu);
 }
 #endif
 
diff -r 92c6021f23e4 -r 5a97ee0633e8 
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Thu Oct 13 14:26:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Thu Oct 13 16:08:59 2005
@@ -178,11 +178,10 @@
        return irq;
 }
 
-int bind_virq_to_irq(int virq)
+int bind_virq_to_irq(int virq, int cpu)
 {
        evtchn_op_t op = { .cmd = EVTCHNOP_bind_virq };
        int evtchn, irq;
-       int cpu = smp_processor_id();
 
        spin_lock(&irq_mapping_update_lock);
 
@@ -209,10 +208,9 @@
 }
 EXPORT_SYMBOL(bind_virq_to_irq);
 
-void unbind_virq_from_irq(int virq)
+void unbind_virq_from_irq(int virq, int cpu)
 {
        evtchn_op_t op = { .cmd = EVTCHNOP_close };
-       int cpu    = smp_processor_id();
        int irq    = per_cpu(virq_to_irq, cpu)[virq];
        int evtchn = irq_to_evtchn[irq];
 
@@ -240,11 +238,10 @@
 }
 EXPORT_SYMBOL(unbind_virq_from_irq);
 
-int bind_ipi_to_irq(int ipi)
+int bind_ipi_to_irq(int ipi, int cpu)
 {
        evtchn_op_t op = { .cmd = EVTCHNOP_bind_ipi };
        int evtchn, irq;
-       int cpu = smp_processor_id();
 
        spin_lock(&irq_mapping_update_lock);
 
@@ -272,10 +269,9 @@
 }
 EXPORT_SYMBOL(bind_ipi_to_irq);
 
-void unbind_ipi_from_irq(int ipi)
+void unbind_ipi_from_irq(int ipi, int cpu)
 {
        evtchn_op_t op = { .cmd = EVTCHNOP_close };
-       int cpu    = smp_processor_id();
        int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
        int irq    = evtchn_to_irq[evtchn];
 
diff -r 92c6021f23e4 -r 5a97ee0633e8 
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     Thu Oct 13 
14:26:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c     Thu Oct 13 
16:08:59 2005
@@ -1224,13 +1224,13 @@
        int cpu = smp_processor_id();
 
        per_cpu(resched_irq, cpu) =
-               bind_ipi_to_irq(RESCHEDULE_VECTOR);
+               bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu);
        sprintf(resched_name[cpu], "resched%d", cpu);
        BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
                           SA_INTERRUPT, resched_name[cpu], NULL));
 
        per_cpu(callfunc_irq, cpu) =
-               bind_ipi_to_irq(CALL_FUNCTION_VECTOR);
+               bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu);
        sprintf(callfunc_name[cpu], "callfunc%d", cpu);
        BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
                           smp_call_function_interrupt,
@@ -1242,10 +1242,10 @@
        int cpu = smp_processor_id();
 
        free_irq(per_cpu(resched_irq, cpu), NULL);
-       unbind_ipi_from_irq(RESCHEDULE_VECTOR);
+       unbind_ipi_from_irq(RESCHEDULE_VECTOR, cpu);
 
        free_irq(per_cpu(callfunc_irq, cpu), NULL);
-       unbind_ipi_from_irq(CALL_FUNCTION_VECTOR);
+       unbind_ipi_from_irq(CALL_FUNCTION_VECTOR, cpu);
 }
 
 extern void local_setup_timer_irq(void);
diff -r 92c6021f23e4 -r 5a97ee0633e8 
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c        Thu Oct 13 
14:26:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c        Thu Oct 13 
16:08:59 2005
@@ -768,7 +768,7 @@
 #endif
 
        if (xen_start_info->flags & SIF_INITDOMAIN) {
-               xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
+               xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
                (void)request_irq(xencons_priv_irq,
                                  xencons_priv_interrupt, 0, "console", NULL);
        } else {
diff -r 92c6021f23e4 -r 5a97ee0633e8 
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Thu Oct 13 
14:26:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Thu Oct 13 
16:08:59 2005
@@ -817,7 +817,7 @@
 
        netif_xenbus_init();
 
-       (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG),
+       (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG, 0),
                          netif_be_dbg, SA_SHIRQ, 
                          "net-be-dbg", &netif_be_dbg);
 
diff -r 92c6021f23e4 -r 5a97ee0633e8 
linux-2.6-xen-sparse/include/asm-xen/evtchn.h
--- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h     Thu Oct 13 14:26:44 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h     Thu Oct 13 16:08:59 2005
@@ -44,12 +44,12 @@
  */
 
 /* Dynamically bind a VIRQ source to Linux IRQ space. */
-extern int  bind_virq_to_irq(int virq);
-extern void unbind_virq_from_irq(int virq);
+extern int  bind_virq_to_irq(int virq, int cpu);
+extern void unbind_virq_from_irq(int virq, int cpu);
 
 /* Dynamically bind an IPI source to Linux IRQ space. */
-extern int  bind_ipi_to_irq(int ipi);
-extern void unbind_ipi_from_irq(int ipi);
+extern int  bind_ipi_to_irq(int ipi, int cpu);
+extern void unbind_ipi_from_irq(int ipi, int cpu);
 
 /*
  * Dynamically bind an event-channel port to an IRQ-like callback handler.

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.