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:
parent
bf46dc27d6
commit
54721434df
@ -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
|
||||
;;
|
||||
|
@ -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
|
||||
;;
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user