Be more conservative during AP startup. Don't let the AP access the lapic

or do any setup until the boot processor has finished the init sequence,
and add a few more delays.
This commit is contained in:
ad 2008-05-13 22:39:17 +00:00
parent 5b61e403a2
commit 5d1d928fe1
5 changed files with 66 additions and 32 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: mptramp.S,v 1.8 2008/05/11 22:26:59 ad Exp $ */
/* $NetBSD: mptramp.S,v 1.9 2008/05/13 22:39:17 ad Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -216,10 +216,12 @@ _TRMP_LABEL(mptramp_longmode)
_C_LABEL(cpu_spinup_trampoline_end): #end of code copied to MP_TRAMPOLINE
movl _C_LABEL(local_apic)+LAPIC_ID,%ecx
shrl $LAPIC_ID_SHIFT,%ecx
1:
/* Don't touch lapic until BP has done init sequence. */
movq _C_LABEL(cpu_starting),%rdi
pause
testq %rdi, %rdi
jz 1b
movl _C_LABEL(cpu_feature),%eax
andl $CPUID_NOX,%eax

View File

@ -1,4 +1,4 @@
/* $NetBSD: mptramp.S,v 1.15 2008/05/11 22:26:59 ad Exp $ */
/* $NetBSD: mptramp.S,v 1.16 2008/05/13 22:39:17 ad Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -76,7 +76,7 @@
*/
#include <machine/asm.h>
__KERNEL_RCSID(0, "$NetBSD: mptramp.S,v 1.15 2008/05/11 22:26:59 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: mptramp.S,v 1.16 2008/05/13 22:39:17 ad Exp $");
#include "opt_mpbios.h" /* for MPDEBUG */
@ -184,9 +184,12 @@ _TRMP_LABEL(mp_startup)
# ok, we're now running with paging enabled and sharing page tables with cpu0.
# figure out which processor we really are, what stack we should be on, etc.
movl _C_LABEL(local_apic)+LAPIC_ID,%ecx
shrl $LAPIC_ID_SHIFT,%ecx
/* Don't touch lapic until BP has done init sequence. */
1:
movl _C_LABEL(cpu_starting),%ecx
pause
testl %ecx, %ecx
jz 1b
HALTT(0x7, %ecx)

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpuvar.h,v 1.26 2008/05/11 15:59:50 ad Exp $ */
/* $NetBSD: cpuvar.h,v 1.27 2008/05/13 22:39:17 ad Exp $ */
/*-
* Copyright (c) 2000, 2007 The NetBSD Foundation, Inc.
@ -100,6 +100,7 @@ extern uint32_t cpus_running;
int x86_ipi(int, int, int);
void x86_self_ipi(int);
int x86_ipi_init(int);
int x86_ipi_startup(int, int);
void x86_errata(void);
void identifycpu(struct cpu_info *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.49 2008/05/12 14:41:07 ad Exp $ */
/* $NetBSD: cpu.c,v 1.50 2008/05/13 22:39:18 ad Exp $ */
/*-
* Copyright (c) 2000, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.49 2008/05/12 14:41:07 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.50 2008/05/13 22:39:18 ad Exp $");
#include "opt_ddb.h"
#include "opt_mpbios.h" /* for MPDEBUG */
@ -551,20 +551,19 @@ cpu_start_secondary(struct cpu_info *ci)
u_long psl;
int i;
KASSERT(cpu_starting == NULL);
cpu_starting = ci;
mp_pdirpa = pmap_init_tmp_pgtbl(mp_trampoline_paddr);
atomic_or_32(&ci->ci_flags, CPUF_AP);
ci->ci_curlwp = ci->ci_data.cpu_idlelwp;
if (CPU_STARTUP(ci, mp_trampoline_paddr) != 0) {
cpu_starting = NULL;
return;
}
/*
* wait for it to become ready
* Wait for it to become ready. Setting cpu_starting opens the
* initial gate and allows the AP to start soft initialization.
*/
KASSERT(cpu_starting == NULL);
cpu_starting = ci;
for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i > 0; i--) {
#ifdef MPDEBUG
extern int cpu_trace[3];
@ -891,26 +890,23 @@ mp_cpu_start(struct cpu_info *ci, paddr_t target)
error = x86_ipi_init(ci->ci_cpuid);
if (error != 0) {
aprint_error_dev(ci->ci_dev, "%s: IPI not taken (1)\n",
__func__);
__func__);
return error;
}
i8254_delay(10000);
error = x86_ipi(target / PAGE_SIZE, ci->ci_cpuid,
LAPIC_DLMODE_STARTUP);
error = x86_ipi_startup(ci->ci_cpuid, target / PAGE_SIZE);
if (error != 0) {
aprint_error_dev(ci->ci_dev, "%s: IPI not taken (2)\n",
__func__);
__func__);
return error;
}
i8254_delay(200);
error = x86_ipi(target / PAGE_SIZE, ci->ci_cpuid,
LAPIC_DLMODE_STARTUP);
error = x86_ipi_startup(ci->ci_cpuid, target / PAGE_SIZE);
if (error != 0) {
aprint_error_dev(ci->ci_dev, "%s: IPI not taken (3)\n",
__func__);
__func__);
return error;
}
i8254_delay(200);

View File

@ -1,4 +1,4 @@
/* $NetBSD: lapic.c,v 1.39 2008/05/12 23:46:01 ad Exp $ */
/* $NetBSD: lapic.c,v 1.40 2008/05/13 22:39:18 ad Exp $ */
/*-
* Copyright (c) 2000, 2008 The NetBSD Foundation, Inc.
@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.39 2008/05/12 23:46:01 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.40 2008/05/13 22:39:18 ad Exp $");
#include "opt_ddb.h"
#include "opt_mpbios.h" /* for MPDEBUG */
@ -508,24 +508,56 @@ i82489_icr_wait(void)
int
x86_ipi_init(int target)
{
uint32_t esr;
i82489_writereg(LAPIC_ESR, 0);
(void)i82489_readreg(LAPIC_ESR);
if ((target&LAPIC_DEST_MASK)==0) {
i82489_writereg(LAPIC_ICRHI, target<<LAPIC_ID_SHIFT);
}
i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
LAPIC_DLMODE_INIT | LAPIC_LEVEL_ASSERT );
i82489_icr_wait();
i8254_delay(10000);
i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
LAPIC_DLMODE_INIT | LAPIC_TRIGGER_LEVEL | LAPIC_LEVEL_DEASSERT);
i82489_icr_wait();
return (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY)?EBUSY:0;
if ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) != 0) {
return EBUSY;
}
esr = i82489_readreg(LAPIC_ESR) & ~0x40;
if (esr != 0) {
printf("x86_ipi_init: ESR %08x\n", esr);
}
return 0;
}
int
x86_ipi_startup(int target, int vec)
{
uint32_t esr;
i82489_writereg(LAPIC_ESR, 0);
(void)i82489_readreg(LAPIC_ESR);
i82489_icr_wait();
i82489_writereg(LAPIC_ICRHI, target << LAPIC_ID_SHIFT);
i82489_writereg(LAPIC_ICRLO, vec | LAPIC_DLMODE_STARTUP |
LAPIC_LEVEL_ASSERT);
i82489_icr_wait();
if ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) != 0) {
return EBUSY;
}
esr = i82489_readreg(LAPIC_ESR) & ~0x40;
if (esr != 0) {
printf("x86_ipi_startup: ESR %08x\n", esr);
}
return 0;
}
int