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-ppc-devel

[XenPPC] [PATCH/RFC] Run C code that inits HID registers from secondary

This patch gets things to the point that each secondary processor can
call the same C routine that the primary processor did to invalidate the
segment table and initialize the HID registers.  It prints the following
and boots up to nfsroot on a JS21 blade:

 (XEN) CPU #1 is waiting for a stack ...
 (XEN) CPU #1: Hello World!
 (XEN) CPU #1: stack is here: 000000000376c000
 (XEN) CPU #1: hid0: 0x0051118180000000
 (XEN) CPU #2 is waiting for a stack ...
 (XEN) CPU #2: Hello World!
 (XEN) CPU #2: stack is here: 0000000000070000
 (XEN) CPU #2: hid0: 0x0051118180000000
 (XEN) CPU #3 is waiting for a stack ...
 (XEN) CPU #3: Hello World!
 (XEN) CPU #3: stack is here: 000000000006c000
 (XEN) CPU #3: hid0: 0x0051118180000000

The logic needs a lot of cleanup, but right now I am worrying about
whether we need one idle domain per processor.  We surely can't do this
from more than one processor ...

 set_current(idle_domain->vcpu[0]);
 idle_vcpu[0] = current;

Any comments would be appreciated.

---

 arch/powerpc/boot_of.c              |   70 ++++++++++++++++++++++++++++++++----
 arch/powerpc/of-devtree.h           |    7 +++
 arch/powerpc/powerpc64/exceptions.S |   38 +++++++++++++++++++
 arch/powerpc/powerpc64/ppc970.c     |    7 ++-
 arch/powerpc/setup.c                |   35 +++++++++++++++++-
 include/asm-powerpc/config.h        |    2 -
 include/asm-powerpc/processor.h     |    2 -
 7 files changed, 149 insertions(+), 12 deletions(-)

diff -r bb510c274af8 xen/arch/powerpc/boot_of.c
--- a/xen/arch/powerpc/boot_of.c        Fri Aug 11 13:30:48 2006 -0400
+++ b/xen/arch/powerpc/boot_of.c        Fri Aug 11 21:58:19 2006 -0400
@@ -30,6 +30,9 @@
 #include <asm/io.h>
 #include "exceptions.h"
 #include "of-devtree.h"
+
+/* Secondary processors index into this by their processor id.  */
+volatile struct per_cpu __per_cpu_init[NR_CPUS];
 
 static ulong of_vec;
 static ulong of_msr;
@@ -926,8 +929,8 @@ static void boot_of_module(ulong r3, ulo
 
 static int __init boot_of_cpus(void)
 {
-    int cpus;
-    int cpu;
+    int i, cpus;
+    int cpu, bootcpu;
     int result;
     u32 cpu_clock[2];
 
@@ -952,10 +955,53 @@ static int __init boot_of_cpus(void)
     cpu_khz /= 1000;
     of_printf("OF: clock-frequency = %ld KHz\n", cpu_khz);
 
-    /* FIXME: should not depend on the boot CPU bring the first child */
-    cpu = of_getpeer(cpu);
-    while (cpu > 0) {
-        of_start_cpu(cpu, (ulong)spin_start, 0);
+    /* Look up which CPU we are running on right now.  */
+    result = of_getprop(bof_chosen, "cpu", &bootcpu, sizeof (bootcpu));
+    if (result == OF_FAILURE)
+        of_panic("Failed to look up boot cpu\n");
+
+    for (i = 0, cpu = of_getpeer(cpu); i < NR_CPUS && cpu > 0; i++) {
+        unsigned int cpuid, ping, pong;
+        unsigned long now, then, timeout;
+
+        if (cpu == bootcpu) {
+            of_printf("skipping boot cpu!\n");
+            continue;
+        }
+
+        result = of_getprop(cpu, "reg", &cpuid, sizeof(cpuid));
+        if (result == OF_FAILURE)
+            of_panic("cpuid lookup failed\n");
+
+        of_printf("spinning up secondary processor #%d: ", cpuid);
+
+        __per_cpu_init[cpuid].sp = 0x0;
+        __per_cpu_init[cpuid].id = ~0x0;
+        ping = __per_cpu_init[cpuid].id;
+        pong = __per_cpu_init[cpuid].id;
+        of_printf("ping = 0x%x: ", ping);
+
+        mb();
+        result = of_start_cpu(cpu, (ulong)spin_start, cpuid);
+        if (result == OF_FAILURE)
+            of_panic("start cpu failed\n");
+
+        /* We will give the secondary processor five seconds to reply.  */
+        then = mftb();
+        timeout = then + (5 * timebase_freq);
+
+        do {
+            now = mftb();
+            if (now >= timeout) {
+                of_printf("BROKEN: ");
+                break;
+            }
+
+            mb();
+            pong = __per_cpu_init[cpuid].id;
+        } while (pong == ping);
+        of_printf("pong = 0x%x\n", pong);
+
         cpu = of_getpeer(cpu);
     }
     return 1;
@@ -1003,9 +1049,21 @@ multiboot_info_t __init *boot_of_init(
     boot_of_rtas();
 
     /* end of OF */
+    of_printf("Quiescing Open Firmware ...\n");
     of_call("quiesce", 0, 0, NULL);
 
     return &mbi;
+}
+
+int secondary_cpu_init(int cpuid);
+
+int secondary_cpu_init(int cpuid)
+{
+    printk("CPU #%d: Hello World!\n", cpuid);
+
+    cpu_initialize(cpuid);
+
+    return 0;
 }
 
 /*
diff -r bb510c274af8 xen/arch/powerpc/of-devtree.h
--- a/xen/arch/powerpc/of-devtree.h     Fri Aug 11 13:30:48 2006 -0400
+++ b/xen/arch/powerpc/of-devtree.h     Fri Aug 11 19:55:51 2006 -0400
@@ -23,6 +23,13 @@
 
 #include <xen/types.h>
 #include <public/xen.h>
+
+/* Data structure used by secondary processors to discover their stack.  */
+struct per_cpu {
+    int id;
+    void *sp;
+    void *toc;
+};
 
 enum {
     OF_FAILURE = -1,
diff -r bb510c274af8 xen/arch/powerpc/powerpc64/exceptions.S
--- a/xen/arch/powerpc/powerpc64/exceptions.S   Fri Aug 11 13:30:48 2006 -0400
+++ b/xen/arch/powerpc/powerpc64/exceptions.S   Fri Aug 11 21:11:00 2006 -0400
@@ -514,6 +514,44 @@ _GLOBAL(sleep)
     mtmsrd r3
     blr
 
+/* Get these from asm-offsets, talk to Jimi about int->long alignment hole.  */
+#define ID_OFFSET    0
+#define SP_OFFSET    8
+#define TC_OFFSET    16
+#define PER_CPU_SIZE 24
+       
+/* Firmware is told to spin up secondary processors at this address.  We
+ * only need a function entry point instead of a descriptor since this is
+ * never called from C code.
+ */
     .globl spin_start
 spin_start:
+    /* Our physical cpu number is passed in r3, so index into array.  */
+    muli r5, r3, PER_CPU_SIZE
+    LOADADDR(r27, __per_cpu_init)
+    add r27, r27, r5
+    stw r3, ID_OFFSET(r27)
+    sync
+    /* At some point these should go in different cache lines.  */
+1:  ld r6, SP_OFFSET(r27)
+    cmpldi r6, 0
+    beq 1b
+    /* The primary cpu has an allocator now and wants our attention.  */
+    li r6, 0x0
+    std r6, SP_OFFSET(r27)
+    sync
+    /* Wait for the primary cpu to give us our stack address.  */      
+2:  ld r6, SP_OFFSET(r27)
+    cmpldi r6, 0
+    beq 2b
+    /* The primary cpu has allocated a stack for us, so rock and roll.  */
+    mr r1, r6
+    ld r2, TC_OFFSET(r27)
+    LOADADDR(r8, .secondary_cpu_init)
+    mtctr r8
+    bctrl
+    /* For now, the primary processor is waiting for us to return from C.  */
+    li r3, 0
+    std r3, SP_OFFSET(r27)
+    sync
     b .
diff -r bb510c274af8 xen/arch/powerpc/powerpc64/ppc970.c
--- a/xen/arch/powerpc/powerpc64/ppc970.c       Fri Aug 11 13:30:48 2006 -0400
+++ b/xen/arch/powerpc/powerpc64/ppc970.c       Fri Aug 11 21:56:15 2006 -0400
@@ -37,10 +37,11 @@ unsigned int cpu_rma_order(void)
     return 14; /* 1<<14<<PAGE_SIZE = 64M */
 }
 
-void cpu_initialize(void)
+void cpu_initialize(int cpuid)
 {
     ulong stack;
 
+    /* This is SMP safe because the compiler must use r13 for it.  */
     parea = xmalloc(struct processor_area);
     ASSERT(parea != NULL);
 
@@ -48,7 +49,7 @@ void cpu_initialize(void)
 
     ASSERT(stack != 0);
     parea->hyp_stack_base = (void *)(stack + STACK_SIZE);
-    printk("stack is here: %p\n", parea->hyp_stack_base);
+    printk("CPU #%d: stack is here: %p\n", cpuid, parea->hyp_stack_base);
 
     mthsprg0((ulong)parea); /* now ready for exceptions */
 
@@ -78,7 +79,7 @@ void cpu_initialize(void)
     s |= 1UL << (63-3);     /* ser-gp */
     hid0.word |= s;
 #endif
-    printk("hid0: 0x%016lx\n", hid0.word);
+    printk("CPU #%d: hid0: 0x%016lx\n", cpuid, hid0.word);
     mthid0(hid0.word);
 
     union hid1 hid1;
diff -r bb510c274af8 xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c  Fri Aug 11 13:30:48 2006 -0400
+++ b/xen/arch/powerpc/setup.c  Fri Aug 11 21:55:40 2006 -0400
@@ -75,6 +75,8 @@ extern void idle_loop(void);
 /* move us to a header file */
 extern void initialize_keytable(void);
 
+extern volatile struct per_cpu __per_cpu_init[];
+
 int is_kernel_text(unsigned long addr)
 {
     if (addr >= (unsigned long) &_start &&
@@ -314,7 +316,7 @@ static void __init __start_xen(multiboot
 
     printk("Xen heap: %luMB (%lukB)\n", heap_size >> 20, heap_size >> 10);
 
-    cpu_initialize();
+    cpu_initialize(0);
 
 #ifdef CONFIG_GDB
     initialise_gdb();
@@ -323,6 +325,37 @@ static void __init __start_xen(multiboot
 #endif
 
     start_of_day();
+
+    {
+        int i;
+
+        for (i = 1; i <= NR_CPUS; i++) {
+            void *stack, *toc;
+            void *syn = (void *)~0x0;
+
+            if (__per_cpu_init[i].id > 0) {
+                printk("CPU #%d is waiting for a stack ...\n", i);
+
+                __per_cpu_init[i].sp = syn;
+                do {
+                    mb();
+                } while (__per_cpu_init[i].sp == syn);
+
+                stack = xmalloc_bytes(STACK_SIZE);
+                if (stack == NULL)
+                    panic("failed to allocate stack\n");
+
+                __per_cpu_init[i].sp = stack;
+                asm("mr %0, 2" : "=r" (toc));
+                __per_cpu_init[i].toc = toc;
+                mb();
+
+                do {
+                    mb();
+                } while (__per_cpu_init[i].sp != 0x0);
+            }
+        }
+    }
 
     /* Create initial domain 0. */
     dom0 = domain_create(0);
diff -r bb510c274af8 xen/include/asm-powerpc/config.h
--- a/xen/include/asm-powerpc/config.h  Fri Aug 11 13:30:48 2006 -0400
+++ b/xen/include/asm-powerpc/config.h  Fri Aug 11 16:56:58 2006 -0400
@@ -51,7 +51,7 @@ extern char __bss_start[];
 #define CONFIG_GDB 1
 #define CONFIG_SMP 1
 #define CONFIG_PCI 1
-#define NR_CPUS 1
+#define NR_CPUS 6
 
 #ifndef ELFSIZE
 #define ELFSIZE 64
diff -r bb510c274af8 xen/include/asm-powerpc/processor.h
--- a/xen/include/asm-powerpc/processor.h       Fri Aug 11 13:30:48 2006 -0400
+++ b/xen/include/asm-powerpc/processor.h       Fri Aug 11 21:54:51 2006 -0400
@@ -40,7 +40,7 @@ extern void show_registers(struct cpu_us
 extern void show_registers(struct cpu_user_regs *);
 extern void show_execution_state(struct cpu_user_regs *);
 extern unsigned int cpu_rma_order(void);
-extern void cpu_initialize(void);
+extern void cpu_initialize(int cpuid);
 extern void cpu_init_vcpu(struct vcpu *);
 extern void save_cpu_sprs(struct vcpu *);
 extern void load_cpu_sprs(struct vcpu *);

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

<Prev in Thread] Current Thread [Next in Thread>