WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86: Streamline the CPU early boot proces

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: Streamline the CPU early boot process.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 19 May 2010 07:45:17 -0700
Delivery-date: Wed, 19 May 2010 07:46:05 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1274280123 -3600
# Node ID 163ac18c8c25d0ead826658a23107a54366f9dea
# Parent  287a7069503d25a6d30983d690253fd5a88a20be
x86: Streamline the CPU early boot process.

Mainly this involves getting rid of a bunch of cpumasks and replacing
with a single 'cpu_state' enumeration to track progress and allow
master-slave handshaking.

Cleaning this stuff up is a prerequisite for safely handling slave
failure (e.g., out of memory, invalid slave CPU capabilities,
...). This will get fixed up in a future patch.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/cpu/mtrr/main.c                    |    6 -
 xen/arch/x86/domain.c                           |    9 -
 xen/arch/x86/nmi.c                              |    7 -
 xen/arch/x86/smpboot.c                          |  125 +++++++-----------------
 xen/include/asm-x86/mach-default/mach_wakecpu.h |   11 --
 xen/include/asm-x86/smp.h                       |   12 --
 6 files changed, 44 insertions(+), 126 deletions(-)

diff -r 287a7069503d -r 163ac18c8c25 xen/arch/x86/cpu/mtrr/main.c
--- a/xen/arch/x86/cpu/mtrr/main.c      Wed May 19 14:18:56 2010 +0100
+++ b/xen/arch/x86/cpu/mtrr/main.c      Wed May 19 15:42:03 2010 +0100
@@ -236,7 +236,7 @@ static void set_mtrr(unsigned int reg, u
        data.smp_base = base;
        data.smp_size = size;
        data.smp_type = type;
-       atomic_set(&data.count, num_booting_cpus() - 1);
+       atomic_set(&data.count, num_online_cpus() - 1);
        /* make sure data.count is visible before unleashing other CPUs */
        smp_wmb();
        atomic_set(&data.gate,0);
@@ -251,7 +251,7 @@ static void set_mtrr(unsigned int reg, u
                cpu_relax();
 
        /* ok, reset count and toggle gate */
-       atomic_set(&data.count, num_booting_cpus() - 1);
+       atomic_set(&data.count, num_online_cpus() - 1);
        smp_wmb();
        atomic_set(&data.gate,1);
 
@@ -274,7 +274,7 @@ static void set_mtrr(unsigned int reg, u
        while(atomic_read(&data.count))
                cpu_relax();
 
-       atomic_set(&data.count, num_booting_cpus() - 1);
+       atomic_set(&data.count, num_online_cpus() - 1);
        smp_wmb();
        atomic_set(&data.gate,0);
 
diff -r 287a7069503d -r 163ac18c8c25 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Wed May 19 14:18:56 2010 +0100
+++ b/xen/arch/x86/domain.c     Wed May 19 15:42:03 2010 +0100
@@ -98,15 +98,10 @@ static void default_dead_idle(void)
 
 static void play_dead(void)
 {
-    /* This must be done before dead CPU ack */
     cpu_exit_clear(smp_processor_id());
+    mb();
+    local_irq_disable();
     wbinvd();
-    mb();
-    /* Ack it */
-    __get_cpu_var(cpu_state) = CPU_DEAD;
-
-    /* With physical CPU hotplug, we should halt the cpu. */
-    local_irq_disable();
     (*dead_idle)();
 }
 
diff -r 287a7069503d -r 163ac18c8c25 xen/arch/x86/nmi.c
--- a/xen/arch/x86/nmi.c        Wed May 19 14:18:56 2010 +0100
+++ b/xen/arch/x86/nmi.c        Wed May 19 15:42:03 2010 +0100
@@ -105,16 +105,13 @@ int __init check_nmi_watchdog (void)
 
     printk("Testing NMI watchdog --- ");
 
-    for ( cpu = 0; cpu < NR_CPUS; cpu++ ) 
+    for_each_online_cpu ( cpu )
         prev_nmi_count[cpu] = nmi_count(cpu);
     local_irq_enable();
     mdelay((10*1000)/nmi_hz); /* wait 10 ticks */
 
-    for ( cpu = 0; cpu < NR_CPUS; cpu++ ) 
+    for_each_online_cpu ( cpu )
     {
-        if ( !cpu_isset(cpu, cpu_callin_map) && 
-             !cpu_isset(cpu, cpu_online_map) )
-            continue;
         if ( nmi_count(cpu) - prev_nmi_count[cpu] <= 5 )
             printk("CPU#%d stuck. ", cpu);
         else
diff -r 287a7069503d -r 163ac18c8c25 xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Wed May 19 14:18:56 2010 +0100
+++ b/xen/arch/x86/smpboot.c    Wed May 19 15:42:03 2010 +0100
@@ -65,17 +65,20 @@ cpumask_t cpu_online_map __read_mostly;
 cpumask_t cpu_online_map __read_mostly;
 EXPORT_SYMBOL(cpu_online_map);
 
-cpumask_t cpu_callin_map;
-cpumask_t cpu_callout_map;
-static cpumask_t smp_commenced_mask;
-
 struct cpuinfo_x86 cpu_data[NR_CPUS];
 
 u32 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = -1U };
 
 static void map_cpu_to_logical_apicid(void);
 
-DEFINE_PER_CPU(int, cpu_state);
+enum cpu_state {
+    CPU_STATE_DEAD = 0, /* slave -> master: I am completely dead */
+    CPU_STATE_INIT,     /* master -> slave: Early bringup phase 1 */
+    CPU_STATE_CALLOUT,  /* master -> slave: Early bringup phase 2 */
+    CPU_STATE_CALLIN,   /* slave -> master: Completed phase 2 */
+    CPU_STATE_ONLINE    /* master -> slave: Go fully online now. */
+} cpu_state;
+#define set_cpu_state(state) do { mb(); cpu_state = (state); } while (0)
 
 void *stack_base[NR_CPUS];
 
@@ -128,75 +131,38 @@ static void smp_store_cpu_info(int id)
     ;
 }
 
-static atomic_t init_deasserted;
-
 void smp_callin(void)
 {
-    int cpuid, phys_id, i;
-
-    /*
-     * If waken up by an INIT in an 82489DX configuration
-     * we may get here before an INIT-deassert IPI reaches
-     * our local APIC.  We have to wait for the IPI or we'll
-     * lock up on an APIC access.
-     */
-    wait_for_init_deassert(&init_deasserted);
-
+    int i;
+
+    /* Wait 2s total for startup. */
+    Dprintk("Waiting for CALLOUT.\n");
+    for ( i = 0; cpu_state != CPU_STATE_CALLOUT; i++ )
+    {
+        BUG_ON(i >= 200);
+        cpu_relax();
+        mdelay(10);
+    }
+
+    /*
+     * The boot CPU has finished the init stage and is spinning on cpu_state
+     * update until we finish. We are free to set up this CPU: first the APIC.
+     */
+    Dprintk("CALLIN, before setup_local_APIC().\n");
     if ( x2apic_enabled )
         enable_x2apic();
-
-    /*
-     * (This works even if the APIC is not enabled.)
-     */
-    phys_id = get_apic_id();
-    cpuid = smp_processor_id();
-    if ( cpu_isset(cpuid, cpu_callin_map) )
-    {
-        printk("huh, phys CPU#%d, CPU#%d already present??\n",
-               phys_id, cpuid);
-        BUG();
-    }
-    Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
-
-    /*
-     * STARTUP IPIs are fragile beasts as they might sometimes
-     * trigger some glue motherboard logic. Complete APIC bus
-     * silence for 1 second, this overestimates the time the
-     * boot CPU is spending to send the up to 2 STARTUP IPIs
-     * by a factor of two. This should be enough.
-     */
-
-    /* Wait 2s total for startup. */
-    for ( i = 0; (i < 200) && !cpu_isset(cpuid, cpu_callout_map); i++ )
-    {
-        cpu_relax();
-        mdelay(10);
-    }
-
-    if ( !cpu_isset(cpuid, cpu_callout_map) )
-    {
-        printk("BUG: CPU%d started up but did not get a callout!\n",
-               cpuid);
-        BUG();
-    }
-
-    /*
-     * the boot CPU has finished the init stage and is spinning
-     * on callin_map until we finish. We are free to set up this
-     * CPU, first the APIC. (this is probably redundant on most
-     * boards)
-     */
-
-    Dprintk("CALLIN, before setup_local_APIC().\n");
-    smp_callin_clear_local_apic();
     setup_local_APIC();
     map_cpu_to_logical_apicid();
 
     /* Save our processor parameters. */
-    smp_store_cpu_info(cpuid);
+    smp_store_cpu_info(smp_processor_id());
 
     /* Allow the master to continue. */
-    cpu_set(cpuid, cpu_callin_map);
+    set_cpu_state(CPU_STATE_CALLIN);
+
+    /* And wait for our final Ack. */
+    while ( cpu_state != CPU_STATE_ONLINE )
+        cpu_relax();
 }
 
 static int booting_cpu;
@@ -316,8 +282,6 @@ void start_secondary(void *unused)
     cpu_init();
 
     smp_callin();
-    while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
-        cpu_relax();
 
     /*
      * At this point, boot CPU has fully initialised the IDT. It is
@@ -347,8 +311,6 @@ void start_secondary(void *unused)
     __setup_vector_irq(smp_processor_id());
     cpu_set(smp_processor_id(), cpu_online_map);
     unlock_vector_lock();
-
-    per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 
     init_percpu_time();
 
@@ -469,8 +431,6 @@ static int wakeup_secondary_cpu(int phys
             send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
     } while ( send_status && (timeout++ < 1000) );
 
-    atomic_set(&init_deasserted, 1);
-
     /*
      * Should we send STARTUP IPIs ?
      *
@@ -570,7 +530,7 @@ static int do_boot_cpu(int apicid, int c
 
     /* This grunge runs the startup process for the targeted processor. */
 
-    atomic_set(&init_deasserted, 0);
+    set_cpu_state(CPU_STATE_INIT);
 
     Dprintk("Setting warm reset code and vector.\n");
 
@@ -582,19 +542,18 @@ static int do_boot_cpu(int apicid, int c
     if ( !boot_error )
     {
         /* Allow AP to start initializing. */
-        Dprintk("Before Callout %d.\n", cpu);
-        cpu_set(cpu, cpu_callout_map);
+        set_cpu_state(CPU_STATE_CALLOUT);
         Dprintk("After Callout %d.\n", cpu);
 
         /* Wait 5s total for a response. */
         for ( timeout = 0; timeout < 50000; timeout++ )
         {
-            if ( cpu_isset(cpu, cpu_callin_map) )
+            if ( cpu_state == CPU_STATE_CALLIN )
                 break; /* It has booted */
             udelay(100);
         }
 
-        if ( cpu_isset(cpu, cpu_callin_map) )
+        if ( cpu_state == CPU_STATE_CALLIN )
         {
             /* number CPUs logically, starting from 1 (BSP is 0) */
             Dprintk("OK.\n");
@@ -630,12 +589,8 @@ void cpu_exit_clear(unsigned int cpu)
 void cpu_exit_clear(unsigned int cpu)
 {
     cpu_uninit(cpu);
-
-    cpu_clear(cpu, cpu_callout_map);
-    cpu_clear(cpu, cpu_callin_map);
-
-    cpu_clear(cpu, smp_commenced_mask);
     unmap_cpu_to_logical_apicid(cpu);
+    set_cpu_state(CPU_STATE_DEAD);
 }
 
 static void cpu_smpboot_free(unsigned int cpu)
@@ -828,12 +783,8 @@ void __init smp_prepare_cpus(unsigned in
 
 void __init smp_prepare_boot_cpu(void)
 {
-    cpu_set(smp_processor_id(), smp_commenced_mask);
-    cpu_set(smp_processor_id(), cpu_callin_map);
     cpu_set(smp_processor_id(), cpu_online_map);
-    cpu_set(smp_processor_id(), cpu_callout_map);
     cpu_set(smp_processor_id(), cpu_present_map);
-    per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 }
 
 static void
@@ -888,7 +839,7 @@ void __cpu_die(unsigned int cpu)
     /* We don't do anything here: idle task is faking death itself. */
     unsigned int i = 0;
 
-    while ( per_cpu(cpu_state, cpu) != CPU_DEAD )
+    while ( cpu_state != CPU_STATE_DEAD )
     {
         mdelay(100);
         cpu_relax();
@@ -957,15 +908,13 @@ int __cpu_up(unsigned int cpu)
 {
     int apicid, ret;
 
-    BUG_ON(cpu_isset(cpu, cpu_callin_map));
-
     if ( (apicid = x86_cpu_to_apicid[cpu]) == BAD_APICID )
         return -ENODEV;
 
     if ( (ret = do_boot_cpu(apicid, cpu)) != 0 )
         return ret;
 
-    cpu_set(cpu, smp_commenced_mask);
+    set_cpu_state(CPU_STATE_ONLINE);
     while ( !cpu_isset(cpu, cpu_online_map) )
     {
         cpu_relax();
diff -r 287a7069503d -r 163ac18c8c25 
xen/include/asm-x86/mach-default/mach_wakecpu.h
--- a/xen/include/asm-x86/mach-default/mach_wakecpu.h   Wed May 19 14:18:56 
2010 +0100
+++ b/xen/include/asm-x86/mach-default/mach_wakecpu.h   Wed May 19 15:42:03 
2010 +0100
@@ -13,17 +13,6 @@
 
 #define boot_cpu_apicid boot_cpu_physical_apicid
 
-static inline void wait_for_init_deassert(atomic_t *deassert)
-{
-       while (!atomic_read(deassert));
-       return;
-}
-
-/* Nothing to do for most platforms, since cleared by the INIT cycle */
-static inline void smp_callin_clear_local_apic(void)
-{
-}
-
 #if APIC_DEBUG
  #define inquire_remote_apic(apicid) __inquire_remote_apic(apicid)
 #else
diff -r 287a7069503d -r 163ac18c8c25 xen/include/asm-x86/smp.h
--- a/xen/include/asm-x86/smp.h Wed May 19 14:18:56 2010 +0100
+++ b/xen/include/asm-x86/smp.h Wed May 19 15:42:03 2010 +0100
@@ -52,9 +52,6 @@ extern u32 cpu_2_logical_apicid[];
 
 #define cpu_physical_id(cpu)   x86_cpu_to_apicid[cpu]
 
-/* State of each CPU. */
-DECLARE_PER_CPU(int, cpu_state);
-
 #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
 extern void cpu_exit_clear(unsigned int cpu);
 extern void cpu_uninit(unsigned int cpu);
@@ -66,15 +63,6 @@ int cpu_add(uint32_t apic_id, uint32_t a
  * so this is correct in the x86 case.
  */
 #define raw_smp_processor_id() (get_processor_id())
-
-extern cpumask_t cpu_callout_map;
-extern cpumask_t cpu_callin_map;
-
-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
-static inline int num_booting_cpus(void)
-{
-       return cpus_weight(cpu_callout_map);
-}
 
 #ifdef CONFIG_X86_LOCAL_APIC
 

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86: Streamline the CPU early boot process., Xen patchbot-unstable <=