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

2006-08-13 Thread Segher Boessenkool

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

2006-08-12 Thread Olof Johansson
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

2006-08-12 Thread Segher Boessenkool

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

2006-08-12 Thread Jimi Xenidis


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

2006-08-11 Thread Amos Waterland
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.