diff options
author | marcel <marcel@FreeBSD.org> | 2001-11-12 07:18:16 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2001-11-12 07:18:16 +0000 |
commit | 54721434df82333886cc6315afa403c22f5ec26d (patch) | |
tree | 7788c5a2ff2e57112b2c056f2eba2ab472899b91 /sys | |
parent | bf46dc27d670ffcafac18e4dcf4f360a2d34973b (diff) | |
download | FreeBSD-src-54721434df82333886cc6315afa403c22f5ec26d.zip FreeBSD-src-54721434df82333886cc6315afa403c22f5ec26d.tar.gz |
o os_boot_rendez is responsible for clearing the IRR bit by
reading cr.ivr, as well as writing to cr.eoi.
o use global variables to pass information to os_boot_rendez
so that it doesn't have to jump through hoops to find it
out. This avoids traps on the AP without it even being
initialized. This fixes SMP configurations.
o Move the probing of the MADT to the end of cpu_startup,
instead of at the start of cpu_mp_probe. We need to probe
the MADT for non-SMP configurations as well. This fixes
uniprocessor configurations.
o Serialize AP wake-up by waiting for the AP. We need to do
this since we use global variables to for the AP to use.
As a side-effect, we can use printf() more easily to see
what's going on.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ia64/ia64/locore.S | 20 | ||||
-rw-r--r-- | sys/ia64/ia64/locore.s | 20 | ||||
-rw-r--r-- | sys/ia64/ia64/machdep.c | 13 | ||||
-rw-r--r-- | sys/ia64/ia64/mp_machdep.c | 53 |
4 files changed, 69 insertions, 37 deletions
diff --git a/sys/ia64/ia64/locore.S b/sys/ia64/ia64/locore.S index 24ac142..544d192 100644 --- a/sys/ia64/ia64/locore.S +++ b/sys/ia64/ia64/locore.S @@ -151,9 +151,18 @@ END(mi_startup_trampoline) * as described on page 3-9 of the IPF SAL Specification. The difference * lies in the contents of register b0. For APs this register holds the * return address into the SAL rendezvous routine. + * + * Note that we're responsible for clearing the IRR bit by reading cr.ivr + * and issuing the EOI to the local SAPIC. */ .align 32 ENTRY(os_boot_rendez,0) + mov r16=cr.ivr // clear IRR bit + ;; + srlz.d + mov cr.eoi=r0 // ACK the wake-up + ;; + srlz.d rsm IA64_PSR_IC|IA64_PSR_I ;; srlz.d @@ -214,18 +223,17 @@ ENTRY(os_boot_rendez,0) mov cr.pta = r17 ;; srlz.i - ssm psr.i ;; srlz.d + movl r16 = ap_stack mov ar.rsc = 0 movl gp = __gp ;; - br.call.sptk.few rp = ia64_ap_get_stack - ;; - mov r9 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16 + ld8 r16 = [r16] + mov r17 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16 ;; - add sp = r9, r8 - mov ar.bspstore = r8 + add sp = r17, r16 + mov ar.bspstore = r16 ;; loadrs ;; diff --git a/sys/ia64/ia64/locore.s b/sys/ia64/ia64/locore.s index 24ac142..544d192 100644 --- a/sys/ia64/ia64/locore.s +++ b/sys/ia64/ia64/locore.s @@ -151,9 +151,18 @@ END(mi_startup_trampoline) * as described on page 3-9 of the IPF SAL Specification. The difference * lies in the contents of register b0. For APs this register holds the * return address into the SAL rendezvous routine. + * + * Note that we're responsible for clearing the IRR bit by reading cr.ivr + * and issuing the EOI to the local SAPIC. */ .align 32 ENTRY(os_boot_rendez,0) + mov r16=cr.ivr // clear IRR bit + ;; + srlz.d + mov cr.eoi=r0 // ACK the wake-up + ;; + srlz.d rsm IA64_PSR_IC|IA64_PSR_I ;; srlz.d @@ -214,18 +223,17 @@ ENTRY(os_boot_rendez,0) mov cr.pta = r17 ;; srlz.i - ssm psr.i ;; srlz.d + movl r16 = ap_stack mov ar.rsc = 0 movl gp = __gp ;; - br.call.sptk.few rp = ia64_ap_get_stack - ;; - mov r9 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16 + ld8 r16 = [r16] + mov r17 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16 ;; - add sp = r9, r8 - mov ar.bspstore = r8 + add sp = r17, r16 + mov ar.bspstore = r16 ;; loadrs ;; diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index c59fd6f..a67f7a9 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -81,6 +81,8 @@ #include <machine/rse.h> #include <machine/unwind.h> +void ia64_probe_sapics(void); + #ifdef SKI extern void ia64_ski_init(void); #endif @@ -228,6 +230,12 @@ cpu_startup(dummy) */ bufinit(); vm_pager_bufferinit(); + + /* + * Traverse the MADT to discover IOSAPIC and Local SAPIC + * information. + */ + ia64_probe_sapics(); } static void @@ -744,15 +752,12 @@ DELAY(int n) { u_int64_t start, end, now; - /* - * XXX This can't cope with rollovers. - */ start = ia64_get_itc(); end = start + (itc_frequency * n) / 1000000; /* printf("DELAY from 0x%lx to 0x%lx\n", start, end); */ do { now = ia64_get_itc(); - } while (now < end); + } while (now < end || (now > start && end < start)); } /* diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index eb8c0f0..aadbd7d 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -51,8 +51,6 @@ #define LID_SAPIC_ID(x) ((int)((x) >> 24) & 0xff) #define LID_SAPIC_EID(x) ((int)((x) >> 16) & 0xff) -void ia64_probe_sapics(void); - static MALLOC_DEFINE(M_SMP, "smp", "SMP structures"); static void ipi_send(u_int64_t, int); @@ -71,28 +69,26 @@ int mp_hardware = 0; int mp_ipi_vector[IPI_COUNT]; int mp_ipi_test = 0; -TAILQ_HEAD(, mp_cpu) ia64_cpus = TAILQ_HEAD_INITIALIZER(ia64_cpus); - -void * -ia64_ap_get_stack(void) -{ - struct mp_cpu *cpu; - u_int64_t lid = ia64_get_lid() & 0xffff0000L; - - TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) { - if (cpu->cpu_lid == lid) - return (cpu->cpu_stack); - } +/* Variables used by os_boot_rendez */ +volatile void *ap_stack; +volatile int ap_delay; +volatile int ap_awake; - panic(__func__": bad LID or RR5 misconfigured"); -} +TAILQ_HEAD(, mp_cpu) ia64_cpus = TAILQ_HEAD_INITIALIZER(ia64_cpus); void ia64_ap_startup(void) { +#if 0 struct mp_cpu *cpu; u_int64_t lid = ia64_get_lid() & 0xffff0000L; +#endif + ap_awake = 1; + ap_delay = 0; + while (1); + +#if 0 TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) { if (cpu->cpu_lid == lid) break; @@ -102,16 +98,17 @@ ia64_ap_startup(void) cpu->cpu_lid = ia64_get_lid(); cpu->cpu_awake = 1; - - while(1) - ia64_call_pal_static(PAL_HALT_LIGHT, 0, 0, 0); +#endif } int cpu_mp_probe() { - ia64_probe_sapics(); - return (mp_hardware); + /* + * We've already discovered any APs when they're present. + * Just return the result here. + */ + return (mp_hardware && mp_ncpus > 1); } void @@ -157,9 +154,23 @@ cpu_mp_start() if (!cpu->cpu_bsp) { cpu->cpu_stack = malloc(KSTACK_PAGES * PAGE_SIZE, M_SMP, M_WAITOK); + if (bootverbose) printf("SMP: waking up cpu%d\n", cpu->cpu_no); + + ap_stack = cpu->cpu_stack; + ap_delay = 2000; + ap_awake = 0; ipi_send(cpu->cpu_lid, IPI_AP_WAKEUP); + + do { + DELAY(1000); + } while (--ap_delay > 0); + cpu->cpu_awake = (ap_awake) ? 1 : 0; + + if (bootverbose && !ap_awake) + printf("SMP: WARNING: cpu%d did not wake up\n", + cpu->cpu_no); } else { cpu->cpu_lid = ia64_get_lid(); cpu->cpu_awake = 1; |