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

[Xen-devel] [PATCH 6 of 9] arm: Boot secondary CPUs into C



# HG changeset patch
# User Tim Deegan <tim@xxxxxxx>
# Date 1331300346 0
# Node ID 1b26b83318b378a6e41916e230e27030ee4539e0
# Parent  469d9fc8e755b8bd0de386c8cd505229ecdf061f
arm: Boot secondary CPUs into C

Secondary CPUs come up directly onto the stack of the appropriate idle
vcpu; the boot CPU starts on a statically allocated stack and switches
over to the idle vcpu's one once the idle domain has been built.

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

diff -r 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/gic.c
--- a/xen/arch/arm/gic.c        Fri Mar 09 13:39:06 2012 +0000
+++ b/xen/arch/arm/gic.c        Fri Mar 09 13:39:06 2012 +0000
@@ -245,7 +245,6 @@ static void __cpuinit gic_hyp_init(void)
 
     vtr = GICH[GICH_VTR];
     nr_lrs  = (vtr & GICH_VTR_NRLRGS) + 1;
-    printk("GICH: %d list registers available\n", nr_lrs);
 
     GICH[GICH_HCR] = GICH_HCR_EN;
     GICH[GICH_MISR] = GICH_MISR_EOI;
@@ -278,6 +277,15 @@ int __init gic_init(void)
     return gic.cpus;
 }
 
+/* Set up the per-CPU parts of the GIC for a secondary CPU */
+void __cpuinit gic_init_secondary_cpu(void)
+{
+    spin_lock(&gic.lock);
+    gic_cpu_init();
+    gic_hyp_init();
+    spin_unlock(&gic.lock);
+}
+
 void gic_route_irqs(void)
 {
     /* XXX should get these from DT */
diff -r 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/gic.h
--- a/xen/arch/arm/gic.h        Fri Mar 09 13:39:06 2012 +0000
+++ b/xen/arch/arm/gic.h        Fri Mar 09 13:39:06 2012 +0000
@@ -140,6 +140,8 @@ extern int gic_route_irq_to_guest(struct
 extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq);
 /* Bring up the interrupt controller, and report # cpus attached */
 extern int gic_init(void);
+/* Bring up a secondary CPU's per-CPU GIC interface */
+extern void gic_init_secondary_cpu(void);
 /* setup the gic virtual interface for a guest */
 extern void gicv_setup(struct domain *d);
 #endif
diff -r 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/head.S
--- a/xen/arch/arm/head.S       Fri Mar 09 13:39:06 2012 +0000
+++ b/xen/arch/arm/head.S       Fri Mar 09 13:39:06 2012 +0000
@@ -307,17 +307,23 @@ 1:        ldrex r1, [r0]               /*      
         * and brought up the memory allocator, non-boot CPUs can get their
         * own stacks and enter C. */
 1:     wfe
-       b 1b
+       dsb
+       ldr   r0, =smp_up_cpu
+       ldr   r1, [r0]               /* Which CPU is being booted? */
+       teq   r1, r12                /* Is it us? */
+       bne   1b
 
 launch:        
-       ldr   sp, =init_stack        /* Supply a stack */
+       ldr   r0, =init_stack        /* Find the boot-time stack */
+       ldr   sp, [r0]
        add   sp, #STACK_SIZE        /* (which grows down from the top). */
        sub   sp, #CPUINFO_sizeof    /* Make room for CPU save record */
        mov   r0, r10                /* Marshal args: - phys_offset */
        mov   r1, r7                 /*               - machine type */
        mov   r2, r8                 /*               - ATAG address */
-       mov   r3, r12                /*               - CPU ID */
-       b     start_xen              /* and disappear into the land of C */
+       movs  r3, r12                /*               - CPU ID */
+       beq   start_xen              /* and disappear into the land of C */
+       b     start_secondary        /* (to the appropriate entry point) */
 
 /* Fail-stop
  * r0: string explaining why */
diff -r 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/setup.c
--- a/xen/arch/arm/setup.c      Fri Mar 09 13:39:06 2012 +0000
+++ b/xen/arch/arm/setup.c      Fri Mar 09 13:39:06 2012 +0000
@@ -38,9 +38,6 @@
 #include <asm/setup.h>
 #include "gic.h"
 
-/* Xen stack for bringing up the first CPU. */
-unsigned char __initdata init_stack[STACK_SIZE] 
__attribute__((__aligned__(STACK_SIZE)));
-
 extern const char __init_begin[], __init_end[], __bss_start[];
 
 /* Spinlock for serializing CPU bringup */
@@ -179,6 +176,8 @@ void __init start_xen(unsigned long boot
     console_init_preirq();
 #endif
 
+    percpu_init_areas();
+
     cpus = gic_init();
 
     printk("Waiting for %i other CPUs to be ready\n", cpus - 1);
@@ -197,7 +196,6 @@ void __init start_xen(unsigned long boot
 
     __set_current((struct vcpu *)0xfffff000); /* debug sanity */
     idle_vcpu[0] = current;
-    set_processor_id(0); /* needed early, for smp_processor_id() */
 
     smp_prepare_cpus(cpus);
 
@@ -284,7 +282,11 @@ void __init start_xen(unsigned long boot
 
     domain_unpause_by_systemcontroller(dom0);
 
-    reset_stack_and_jump(init_done);
+    /* Switch on to the dynamically allocated stack for the idle vcpu
+     * since the static one we're running on is about to be freed. */
+    memcpy(idle_vcpu[0]->arch.cpu_info, get_cpu_info(), 
+           sizeof(struct cpu_info));
+    switch_stack_and_jump(idle_vcpu[0]->arch.cpu_info, init_done);
 }
 
 void arch_get_xen_caps(xen_capabilities_info_t *info)
diff -r 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/smpboot.c
--- a/xen/arch/arm/smpboot.c    Fri Mar 09 13:39:06 2012 +0000
+++ b/xen/arch/arm/smpboot.c    Fri Mar 09 13:39:06 2012 +0000
@@ -16,10 +16,15 @@
  * GNU General Public License for more details.
  */
 
+#include <xen/cpu.h>
 #include <xen/cpumask.h>
+#include <xen/errno.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/sched.h>
 #include <xen/smp.h>
-#include <xen/init.h>
-#include <xen/errno.h>
+#include <xen/softirq.h>
+#include "gic.h"
 
 cpumask_t cpu_online_map;
 EXPORT_SYMBOL(cpu_online_map);
@@ -28,6 +33,13 @@ EXPORT_SYMBOL(cpu_online_map);
 cpumask_t cpu_possible_map;
 EXPORT_SYMBOL(cpu_possible_map);
 
+/* Xen stack for bringing up the first CPU. */
+static unsigned char __initdata cpu0_boot_stack[STACK_SIZE]
+       __attribute__((__aligned__(STACK_SIZE)));
+
+/* Pointer to the stack, used by head.S when entering C */
+unsigned char *init_stack = cpu0_boot_stack;
+
 void __init
 smp_prepare_cpus (unsigned int max_cpus)
 {
@@ -43,11 +55,43 @@ smp_prepare_cpus (unsigned int max_cpus)
     cpumask_copy(&cpu_present_map, &cpu_possible_map);
 }
 
-/* Bring up a non-boot CPU */
-int __cpu_up(unsigned int cpu)
+/* Shared state for coordinating CPU bringup */
+unsigned long smp_up_cpu = 0;
+
+/* Boot the current CPU */
+void __cpuinit start_secondary(unsigned long boot_phys_offset,
+                               unsigned long arm_type,
+                               unsigned long atag_paddr,
+                               unsigned long cpuid)
 {
-    /* Not yet... */
-    return -ENODEV;
+    memset(get_cpu_info(), 0, sizeof (struct cpu_info));
+
+    /* TODO: handle boards where CPUIDs are not contiguous */
+    set_processor_id(cpuid);
+
+    /* Setup Hyp vector base */
+    WRITE_CP32((uint32_t) hyp_traps_vector, HVBAR);
+
+    dprintk(XENLOG_DEBUG, "CPU %li awake.\n", cpuid);
+
+    gic_init_secondary_cpu();
+
+    set_current(idle_vcpu[cpuid]);
+    this_cpu(curr_vcpu) = current;
+
+    /* Run local notifiers */
+    notify_cpu_starting(cpuid);
+    wmb();
+
+    /* Now report this CPU is up */
+    cpumask_set_cpu(cpuid, &cpu_online_map);
+    wmb();
+
+    local_irq_enable();
+
+    dprintk(XENLOG_DEBUG, "CPU %li booted.\n", cpuid);
+
+    startup_cpu_idle_loop();
 }
 
 /* Shut down the current CPU */
@@ -57,6 +101,26 @@ void __cpu_disable(void)
     BUG();
 }
 
+/* Bring up a remote CPU */
+int __cpu_up(unsigned int cpu)
+{
+    /* Tell the remote CPU which stack to boot on. */
+    init_stack = idle_vcpu[cpu]->arch.stack;
+
+    /* Unblock the CPU.  It should be waiting in the loop in head.S
+     * for an event to arrive when smp_up_cpu matches its cpuid. */
+    smp_up_cpu = cpu;
+    asm volatile("dsb; isb; sev");
+
+    while ( !cpu_online(cpu) )
+    {
+        cpu_relax();
+        process_pending_softirqs();
+    }
+
+    return 0;
+}
+
 /* Wait for a remote CPU to die */
 void __cpu_die(unsigned int cpu)
 {
diff -r 469d9fc8e755 -r 1b26b83318b3 xen/include/asm-arm/current.h
--- a/xen/include/asm-arm/current.h     Fri Mar 09 13:39:06 2012 +0000
+++ b/xen/include/asm-arm/current.h     Fri Mar 09 13:39:06 2012 +0000
@@ -47,10 +47,10 @@ static inline struct cpu_info *get_cpu_i
 
 #define guest_cpu_user_regs() (&get_cpu_info()->guest_cpu_user_regs)
 
-#define reset_stack_and_jump(__fn)              \
-    __asm__ __volatile__ (                      \
-        "mov sp,%0; b "STR(__fn)      \
-        : : "r" (guest_cpu_user_regs()) : "memory" )
+#define switch_stack_and_jump(stack, fn)                                \
+    asm volatile ("mov sp,%0; b " STR(fn) : : "r" (stack) : "memory" )
+
+#define reset_stack_and_jump(fn) switch_stack_and_jump(get_cpu_info(), fn)
 
 #endif
 

_______________________________________________
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®.