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

[Xen-devel] [PATCH] arm: don't use atomic operations to gate non-boot CPUs



# HG changeset patch
# User Tim Deegan <tim@xxxxxxx>
# Date 1331820837 0
# Node ID 6f52e5de1b942432ffa6c3b8d194e5e2771c1957
# Parent  4da1453ed61c28a366162b49b2f59f62e070a799
arm: don't use atomic operations to gate non-boot CPUs.

Since the cache is not enabled that early, better not to rely on
load-linked/store-conditional.  Instead, have the boot CPU call the
other CPUs by their IDs, just like we do later for proper CPU bringup.

Signed-off-by: Tim Deegan <tim@xxxxxxx>

diff -r 4da1453ed61c -r 6f52e5de1b94 xen/arch/arm/head.S
--- a/xen/arch/arm/head.S       Thu Mar 15 11:47:27 2012 +0000
+++ b/xen/arch/arm/head.S       Thu Mar 15 14:13:57 2012 +0000
@@ -71,16 +71,13 @@ start:
        bics  r12, r0, #(0xff << 24) /* Mask out flags to get CPU ID */
        beq   boot_cpu               /* If we're CPU 0, boot now */
 
-       /* Non-boot CPUs wait here to be woken up one at a time.
-        * This is basically an open-coded spin-lock to serialize. */
-       ldr   r0, =boot_gate         /* VA of gate */
+       /* Non-boot CPUs wait here to be woken up one at a time. */
+1:     wfe
+       dsb
+       ldr   r0, =smp_up_cpu        /* VA of gate */
        add   r0, r0, r10            /* PA of gate */
-       mov   r1, #1                 /* (1 == locked) */
-1:     wfe
-       ldrex r2, [r0]               /* Linked read of current value */
-       teq   r2, #0                 /* (0 == unlocked) */
-       strexeq r2, r1, [r0]         /* Matching update -> locked */
-       teq   r2, #0                 /* (0 == succeeded) */
+       ldr   r1, [r0]               /* Which CPU is being booted? */
+       teq   r1, r12                /* Is it us? */
        bne   1b
 
 boot_cpu:
@@ -270,16 +267,7 @@ paging:
        teq   r12, #0
        beq   launch
 
-       /* Signal the next non-boot CPU to come and join us here */
-       ldr   r0, =boot_gate         /* VA of gate */
-       add   r0, r0, r10            /* PA of gate */
-       mov   r1, #0                 /* (0 == unlocked) */
-       str   r1, [r0]
-       dsb
-       isb
-       sev
-
-       /* Move on to the relocated pagetables */
+       /* Non-boot CPUs need to move on to the relocated pagetables */
        mov   r0, #0
        ldr   r4, =boot_httbr        /* VA of HTTBR value stashed by CPU 0 */
        add   r4, r4, r10            /* PA of it */
diff -r 4da1453ed61c -r 6f52e5de1b94 xen/arch/arm/setup.c
--- a/xen/arch/arm/setup.c      Thu Mar 15 11:47:27 2012 +0000
+++ b/xen/arch/arm/setup.c      Thu Mar 15 14:13:57 2012 +0000
@@ -38,11 +38,6 @@
 #include <asm/setup.h>
 #include "gic.h"
 
-/* Spinlock for serializing CPU bringup */
-unsigned long __initdata boot_gate = 1;
-/* Number of non-boot CPUs ready to enter C */
-unsigned long __initdata ready_cpus = 0;
-
 static __attribute_used__ void init_done(void)
 {
     free_init_memory();
@@ -152,8 +147,6 @@ void __init start_xen(unsigned long boot
     void *fdt;
     size_t fdt_size;
     int cpus, i;
-    paddr_t gate_pa;
-    unsigned long *gate;
 
     fdt = (void *)BOOT_MISC_VIRT_START
         + (atag_paddr & ((1 << SECOND_SHIFT) - 1));
@@ -169,25 +162,11 @@ void __init start_xen(unsigned long boot
     console_init_preirq();
 #endif
 
+    cpus = gic_init();
+    make_cpus_ready(cpus, boot_phys_offset);
+
     percpu_init_areas();
     set_processor_id(0); /* needed early, for smp_processor_id() */
-
-    cpus = gic_init();
-
-    printk("Waiting for %i other CPUs to be ready\n", cpus - 1);
-    /* Bring the other CPUs up to paging before the original
-     * copy of .text gets overwritten.  We need to use the unrelocated
-     * copy of boot_gate as that's the one the others can see. */ 
-    gate_pa = ((unsigned long) &boot_gate) + boot_phys_offset;
-    gate = map_domain_page(gate_pa >> PAGE_SHIFT) + (gate_pa & ~PAGE_MASK); 
-    *gate = 0;
-    unmap_domain_page(gate);
-    /* Now send an event to wake the first non-boot CPU */
-    asm volatile("dsb; isb; sev");
-    /* And wait for them all to be ready. */
-    while ( ready_cpus + 1 < cpus )
-        smp_rmb();
-
     __set_current((struct vcpu *)0xfffff000); /* debug sanity */
     idle_vcpu[0] = current;
 
diff -r 4da1453ed61c -r 6f52e5de1b94 xen/arch/arm/smpboot.c
--- a/xen/arch/arm/smpboot.c    Thu Mar 15 11:47:27 2012 +0000
+++ b/xen/arch/arm/smpboot.c    Thu Mar 15 14:13:57 2012 +0000
@@ -19,6 +19,7 @@
 #include <xen/cpu.h>
 #include <xen/cpumask.h>
 #include <xen/delay.h>
+#include <xen/domain_page.h>
 #include <xen/errno.h>
 #include <xen/init.h>
 #include <xen/mm.h>
@@ -41,11 +42,17 @@ static unsigned char __initdata cpu0_boo
 /* Pointer to the stack, used by head.S when entering C */
 unsigned char *init_stack = cpu0_boot_stack;
 
+/* Shared state for coordinating CPU bringup */
+unsigned long smp_up_cpu = 0;
+static bool_t cpu_is_dead = 0;
+
+/* Number of non-boot CPUs ready to enter C */
+unsigned long __initdata ready_cpus = 0;
+
 void __init
 smp_prepare_cpus (unsigned int max_cpus)
 {
     int i;
-    set_processor_id(0); /* needed early, for smp_processor_id() */
 
     cpumask_clear(&cpu_online_map);
     cpumask_set_cpu(0, &cpu_online_map);
@@ -56,9 +63,30 @@ smp_prepare_cpus (unsigned int max_cpus)
     cpumask_copy(&cpu_present_map, &cpu_possible_map);
 }
 
-/* Shared state for coordinating CPU bringup */
-unsigned long smp_up_cpu = 0;
-static bool_t cpu_is_dead = 0;
+void __init
+make_cpus_ready(unsigned int max_cpus, unsigned long boot_phys_offset)
+{
+    unsigned long *gate;
+    paddr_t gate_pa;
+    int i;
+
+    printk("Waiting for %i other CPUs to be ready\n", max_cpus - 1);
+    /* We use the unrelocated copy of smp_up_cpu as that's the one the
+     * others can see. */ 
+    gate_pa = ((paddr_t) (unsigned long) &smp_up_cpu) + boot_phys_offset;
+    gate = map_domain_page(gate_pa >> PAGE_SHIFT) + (gate_pa & ~PAGE_MASK); 
+    for ( i = 1; i < max_cpus; i++ )
+    {
+        /* Tell the next CPU to get ready */
+        /* TODO: handle boards where CPUIDs are not contiguous */
+        *gate = i;
+        asm volatile("dsb; isb; sev");
+        /* And wait for it to respond */
+        while ( ready_cpus < i )
+            smp_rmb();
+    }
+    unmap_domain_page(gate);
+}
 
 /* Boot the current CPU */
 void __cpuinit start_secondary(unsigned long boot_phys_offset,
diff -r 4da1453ed61c -r 6f52e5de1b94 xen/include/asm-arm/smp.h
--- a/xen/include/asm-arm/smp.h Thu Mar 15 11:47:27 2012 +0000
+++ b/xen/include/asm-arm/smp.h Thu Mar 15 14:13:57 2012 +0000
@@ -16,6 +16,12 @@ DECLARE_PER_CPU(cpumask_var_t, cpu_core_
 
 extern void stop_cpu(void);
 
+/* Bring the non-boot CPUs up to paging and ready to enter C.  
+ * Must be called after Xen is relocated but before the original copy of
+ * .text gets overwritten. */
+extern void
+make_cpus_ready(unsigned int max_cpus, unsigned long boot_phys_offset);
+
 #endif
 /*
  * Local variables:

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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