summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2001-11-12 07:18:16 +0000
committermarcel <marcel@FreeBSD.org>2001-11-12 07:18:16 +0000
commit54721434df82333886cc6315afa403c22f5ec26d (patch)
tree7788c5a2ff2e57112b2c056f2eba2ab472899b91 /sys
parentbf46dc27d670ffcafac18e4dcf4f360a2d34973b (diff)
downloadFreeBSD-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.S20
-rw-r--r--sys/ia64/ia64/locore.s20
-rw-r--r--sys/ia64/ia64/machdep.c13
-rw-r--r--sys/ia64/ia64/mp_machdep.c53
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;
OpenPOWER on IntegriCloud