Clear pending interrupts before we enable external interrupts.

Recently the AP in my Merced box seems to have grown a habit
of getting unexpected interrupts, such as redundant wake-ups
and legacy interrupts that require an INTA cycle.

While here, replace DELAY(0) with cpu_spinwait() so that it's
clear what we're doing as well as enable the code to take
advantage of cpu_spinwait() when it gets implemented.

Approved by: re (blanket)
This commit is contained in:
marcel 2007-08-06 05:15:57 +00:00
parent 48dc5445bf
commit 5f4b9d20fc

View File

@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/ktr.h>
#include <sys/proc.h>
#include <sys/bus.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
@ -50,7 +51,9 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_kern.h>
#include <machine/atomic.h>
#include <machine/cpu.h>
#include <machine/fpu.h>
#include <machine/intr.h>
#include <machine/mca.h>
#include <machine/md_var.h>
#include <machine/pal.h>
@ -64,8 +67,6 @@ MALLOC_DECLARE(M_PMAP);
void ia64_ap_startup(void);
extern uint64_t ia64_lapic_address;
#define LID_SAPIC_ID(x) ((int)((x) >> 24) & 0xff)
#define LID_SAPIC_EID(x) ((int)((x) >> 16) & 0xff)
#define LID_SAPIC_SET(id,eid) (((id & 0xff) << 8 | (eid & 0xff)) << 16);
@ -86,6 +87,8 @@ static void cpu_mp_unleash(void *);
void
ia64_ap_startup(void)
{
volatile struct ia64_interrupt_block *ib = IA64_INTERRUPT_BLOCK;
int vector;
pcpup = ap_pcpu;
ia64_set_k4((intptr_t)pcpup);
@ -104,7 +107,7 @@ ia64_ap_startup(void)
/* Wait until it's time for us to be unleashed */
while (ap_spin)
DELAY(0);
cpu_spinwait();
/* Initialize curthread. */
KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
@ -119,10 +122,22 @@ ia64_ap_startup(void)
ap_awake++;
while (!smp_started)
DELAY(0);
cpu_spinwait();
CTR1(KTR_SMP, "SMP: cpu%d launched", PCPU_GET(cpuid));
/* Acknowledge and EOI all interrupts. */
vector = ia64_get_ivr();
while (vector != 15) {
ia64_srlz_d();
if (vector == 0)
vector = (int)ib->ib_inta;
ia64_set_eoi(0);
ia64_srlz_d();
vector = ia64_get_ivr();
}
ia64_srlz_d();
/* kick off the clock on this AP */
pcpu_initclock();
@ -278,7 +293,7 @@ cpu_mp_unleash(void *dummy)
ap_spin = 0;
while (ap_awake != smp_cpus)
DELAY(0);
cpu_spinwait();
if (smp_cpus != cpus || cpus != mp_ncpus) {
printf("SMP: %d CPUs found; %d CPUs usable; %d CPUs woken\n",