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:
parent
5b61e403a2
commit
5d1d928fe1
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user