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
|