To workaround an errata on certain Pentium Pro CPUs, i386 disables
the local APIC in initializecpu() and re-enables it if the APIC code decides to use the local APIC after all. Rework this workaround slightly so that initializecpu() won't re-disable the local APIC if it is called after the APIC code re-enables the local APIC.
This commit is contained in:
parent
a005d36245
commit
645b112b68
@ -533,6 +533,8 @@ init_6x86MX(void)
|
|||||||
intr_restore(saveintr);
|
intr_restore(saveintr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ppro_apic_used = -1;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_ppro(void)
|
init_ppro(void)
|
||||||
{
|
{
|
||||||
@ -541,9 +543,29 @@ init_ppro(void)
|
|||||||
/*
|
/*
|
||||||
* Local APIC should be disabled if it is not going to be used.
|
* Local APIC should be disabled if it is not going to be used.
|
||||||
*/
|
*/
|
||||||
apicbase = rdmsr(MSR_APICBASE);
|
if (ppro_apic_used != 1) {
|
||||||
apicbase &= ~APICBASE_ENABLED;
|
apicbase = rdmsr(MSR_APICBASE);
|
||||||
wrmsr(MSR_APICBASE, apicbase);
|
apicbase &= ~APICBASE_ENABLED;
|
||||||
|
wrmsr(MSR_APICBASE, apicbase);
|
||||||
|
ppro_apic_used = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the local APIC is going to be used after being disabled above,
|
||||||
|
* re-enable it and don't disable it in the future.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ppro_reenable_apic(void)
|
||||||
|
{
|
||||||
|
u_int64_t apicbase;
|
||||||
|
|
||||||
|
if (ppro_apic_used == 0) {
|
||||||
|
apicbase = rdmsr(MSR_APICBASE);
|
||||||
|
apicbase |= APICBASE_ENABLED;
|
||||||
|
wrmsr(MSR_APICBASE, apicbase);
|
||||||
|
ppro_apic_used = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -109,6 +109,7 @@ int is_physical_memory(vm_paddr_t addr);
|
|||||||
int isa_nmi(int cd);
|
int isa_nmi(int cd);
|
||||||
vm_paddr_t kvtop(void *addr);
|
vm_paddr_t kvtop(void *addr);
|
||||||
void panicifcpuunsupported(void);
|
void panicifcpuunsupported(void);
|
||||||
|
void ppro_reenable_apic(void);
|
||||||
void printcpuinfo(void);
|
void printcpuinfo(void);
|
||||||
void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec);
|
void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec);
|
||||||
int user_dbreg_trap(void);
|
int user_dbreg_trap(void);
|
||||||
|
@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <vm/pmap.h>
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
#include <x86/apicreg.h>
|
#include <x86/apicreg.h>
|
||||||
#include <machine/cpu.h>
|
|
||||||
#include <machine/cputypes.h>
|
#include <machine/cputypes.h>
|
||||||
#include <machine/frame.h>
|
#include <machine/frame.h>
|
||||||
#include <machine/intr_machdep.h>
|
#include <machine/intr_machdep.h>
|
||||||
@ -1331,9 +1330,6 @@ static void
|
|||||||
apic_init(void *dummy __unused)
|
apic_init(void *dummy __unused)
|
||||||
{
|
{
|
||||||
struct apic_enumerator *enumerator;
|
struct apic_enumerator *enumerator;
|
||||||
#ifndef __amd64__
|
|
||||||
uint64_t apic_base;
|
|
||||||
#endif
|
|
||||||
int retval, best;
|
int retval, best;
|
||||||
|
|
||||||
/* We only support built in local APICs. */
|
/* We only support built in local APICs. */
|
||||||
@ -1375,12 +1371,7 @@ apic_init(void *dummy __unused)
|
|||||||
* CPUs during early startup. We need to turn the local APIC back
|
* CPUs during early startup. We need to turn the local APIC back
|
||||||
* on on such CPUs now.
|
* on on such CPUs now.
|
||||||
*/
|
*/
|
||||||
if (cpu == CPU_686 && cpu_vendor_id == CPU_VENDOR_INTEL &&
|
ppro_reenable_apic();
|
||||||
(cpu_id & 0xff0) == 0x610) {
|
|
||||||
apic_base = rdmsr(MSR_APICBASE);
|
|
||||||
apic_base |= APICBASE_ENABLED;
|
|
||||||
wrmsr(MSR_APICBASE, apic_base);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Probe the CPU's in the system. */
|
/* Probe the CPU's in the system. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user