Re: [XenPPC] [PATCH/RFC] Run C code that inits HID registers from secondary procs
It is not necessarily the processors PIR register value, nor does it have any other meaning. You can set the PIR to whatever you want, it's R/W. It doesn't have to be. Book3 2.02 says: "Read access to the PIR is privileged; write access, if provided, is described in the Book IV, PowerPC Implementation Features document for the implementation". Yeah. We were talking specifically about 970 though (or I was at least, heh). In other words, it's up to the implemenation if it's writable or not, and how it's writable: Chip in init scans, mtspr or other ways. ...and I goofed: PIR is R/O on 970, it's initialised via a bunch of pin straps on the CPU package. Segher ___ Xen-ppc-devel mailing list Xen-ppc-devel@lists.xensource.com http://lists.xensource.com/xen-ppc-devel
Re: [XenPPC] [PATCH/RFC] Run C code that inits HID registers from secondary procs
On Sat, Aug 12, 2006 at 08:29:49PM +0200, Segher Boessenkool wrote: > >It is not necessarily the processors PIR register value, nor does > >it have any other meaning. > > You can set the PIR to whatever you want, it's R/W. It doesn't have to be. Book3 2.02 says: "Read access to the PIR is privileged; write access, if provided, is described in the Book IV, PowerPC Implementation Features document for the implementation". In other words, it's up to the implemenation if it's writable or not, and how it's writable: Chip in init scans, mtspr or other ways. -Olof ___ Xen-ppc-devel mailing list Xen-ppc-devel@lists.xensource.com http://lists.xensource.com/xen-ppc-devel
Re: [XenPPC] [PATCH/RFC] Run C code that inits HID registers from secondary procs
Question to all: The "cpuid" from firmware (OF "reg" property) is significant only to uniquely identify the interrupt line that FW assigned to it (usually for IPIs). Not firmware in most cases; it's "hardcoded" in the hardware. It is not necessarily the processors PIR register value, nor does it have any other meaning. You can set the PIR to whatever you want, it's R/W. Should we use it as our global index or use our own numbering system You want to remap those numbers; they can be sparse (like, on a 970GX system, the CPUs are 0 and 2 typically). Segher ___ Xen-ppc-devel mailing list Xen-ppc-devel@lists.xensource.com http://lists.xensource.com/xen-ppc-devel
Re: [XenPPC] [PATCH/RFC] Run C code that inits HID registers from secondary procs
On Aug 11, 2006, at 10:26 PM, Amos Waterland wrote: This patch gets things to the point that each secondary processor can call the same C routine that the primary processor did I would like the initial CPU enumeration to be simpler, like it was in the last patch: - one int to communicate - an array of bytes (or bits) for the barrier These two would have temporary storage. I do believe we will need a global array only contains pointers to the pareas: struct processor_area *global_cpu_table[NR_CPUS]; Mostly for debugging and maybe some crosscalls or IPIs Note: I consider NR_CPUS a statement of what the code supports not what the machine supports, so it is ment to be artificially high. There is no reason that this cannot be dymanically allocated, especially once if we can express the architectural limit, ie. 970FX:max_cpus=2, 970MP:max_cpus=4 etc... Question to all: The "cpuid" from firmware (OF "reg" property) is significant only to uniquely identify the interrupt line that FW assigned to it (usually for IPIs). It is not necessarily the processors PIR register value, nor does it have any other meaning. Should we use it as our global index or use our own numbering system to invalidate the segment table and initialize the HID registers. Segment table? what segment table? 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; correct, you can't do that :) The idle domain is our first SMP domain, so only _one_ idle domain please. 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.cFri Aug 11 13:30:48 2006 -0400 +++ b/xen/arch/powerpc/boot_of.cFri Aug 11 21:58:19 2006 -0400 @@ -30,6 +30,9 @@ #include #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]; If there is no OF then this file will never get run, or even compiled, so _no_ "persistent" storage should be declared here, declare it in setup.c. I should have mentioned this earlier but it looks like you intend for this to live beyond that. 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"); if you are going to use cpuid as an index then you need to: if (cpuid >= NR_CPUS) of_panic(); + +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; +} wh
[XenPPC] [PATCH/RFC] Run C code that inits HID registers from secondary procs
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: 0376c000 (XEN) CPU #1: hid0: 0x005111818000 (XEN) CPU #2 is waiting for a stack ... (XEN) CPU #2: Hello World! (XEN) CPU #2: stack is here: 0007 (XEN) CPU #2: hid0: 0x005111818000 (XEN) CPU #3 is waiting for a stack ... (XEN) CPU #3: Hello World! (XEN) CPU #3: stack is here: 0006c000 (XEN) CPU #3: hid0: 0x005111818000 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.cFri Aug 11 13:30:48 2006 -0400 +++ b/xen/arch/powerpc/boot_of.cFri Aug 11 21:58:19 2006 -0400 @@ -30,6 +30,9 @@ #include #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 #include + +/* 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.