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.
This commit is contained in:
marcel 2001-11-12 07:18:16 +00:00
parent bf46dc27d6
commit 54721434df
4 changed files with 69 additions and 37 deletions

View File

@ -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
ld8 r16 = [r16]
mov r17 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
;;
mov r9 = 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
;;

View File

@ -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
ld8 r16 = [r16]
mov r17 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
;;
mov r9 = 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
;;

View File

@ -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));
}
/*

View File

@ -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;
/* Variables used by os_boot_rendez */
volatile void *ap_stack;
volatile int ap_delay;
volatile int ap_awake;
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);
}
panic(__func__": bad LID or RR5 misconfigured");
}
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;