MFC 271405,271408,271409,272658:

MFamd64: Use initializecpu() to set various model-specific registers on
AP startup and AP resume (it was already used for BSP startup and BSP
resume).
This commit is contained in:
jhb 2014-12-22 19:53:55 +00:00
parent 77f68eb34a
commit 71f9e38fa2
9 changed files with 83 additions and 85 deletions

View File

@ -723,7 +723,7 @@ init_secondary(void)
/* set up CPU registers and state */
cpu_setregs();
/* set up SSE/NX registers */
/* set up SSE/NX */
initializecpu();
/* set up FPU state on the AP */

View File

@ -59,6 +59,12 @@ static void init_i486_on_386(void);
static void init_6x86(void);
#endif /* I486_CPU */
#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
static void enable_K5_wt_alloc(void);
static void enable_K6_wt_alloc(void);
static void enable_K6_2_wt_alloc(void);
#endif
#ifdef I686_CPU
static void init_6x86MX(void);
static void init_ppro(void);
@ -451,7 +457,7 @@ init_winchip(void)
fcr &= ~(1ULL << 11);
/*
* Additioanlly, set EBRPRED, E2MMX and EAMD3D for WinChip 2 and 3.
* Additionally, set EBRPRED, E2MMX and EAMD3D for WinChip 2 and 3.
*/
if (CPUID_TO_MODEL(cpu_id) >= 8)
fcr |= (1 << 12) | (1 << 19) | (1 << 20);
@ -527,6 +533,8 @@ init_6x86MX(void)
intr_restore(saveintr);
}
static int ppro_apic_used = -1;
static void
init_ppro(void)
{
@ -535,9 +543,29 @@ init_ppro(void)
/*
* Local APIC should be disabled if it is not going to be used.
*/
apicbase = rdmsr(MSR_APICBASE);
apicbase &= ~APICBASE_ENABLED;
wrmsr(MSR_APICBASE, apicbase);
if (ppro_apic_used != 1) {
apicbase = rdmsr(MSR_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;
}
}
/*
@ -646,20 +674,6 @@ init_transmeta(void)
}
#endif
/*
* Initialize CR4 (Control register 4) to enable SSE instructions.
*/
void
enable_sse(void)
{
#if defined(CPU_ENABLE_SSE)
if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
cpu_fxsr = hw_instruction_sse = 1;
}
#endif
}
extern int elf32_nxstack;
void
@ -692,6 +706,27 @@ initializecpu(void)
#ifdef I586_CPU
case CPU_586:
switch (cpu_vendor_id) {
case CPU_VENDOR_AMD:
#ifdef CPU_WT_ALLOC
if (((cpu_id & 0x0f0) > 0) &&
((cpu_id & 0x0f0) < 0x60) &&
((cpu_id & 0x00f) > 3))
enable_K5_wt_alloc();
else if (((cpu_id & 0x0f0) > 0x80) ||
(((cpu_id & 0x0f0) == 0x80) &&
(cpu_id & 0x00f) > 0x07))
enable_K6_2_wt_alloc();
else if ((cpu_id & 0x0f0) > 0x50)
enable_K6_wt_alloc();
#endif
if ((cpu_id & 0xf0) == 0xa0)
/*
* Make sure the TSC runs through
* suspension, otherwise we can't use
* it as timecounter
*/
wrmsr(0x1900, rdmsr(0x1900) | 0x20ULL);
break;
case CPU_VENDOR_CENTAUR:
init_winchip();
break;
@ -762,7 +797,17 @@ initializecpu(void)
default:
break;
}
enable_sse();
#if defined(CPU_ENABLE_SSE)
if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
cpu_fxsr = hw_instruction_sse = 1;
}
#endif
}
void
initializecpucache(void)
{
/*
* CPUID with %eax = 1, %ebx returns
@ -839,7 +884,7 @@ initializecpu(void)
* Enable write allocate feature of AMD processors.
* Following two functions require the Maxmem variable being set.
*/
void
static void
enable_K5_wt_alloc(void)
{
u_int64_t msr;
@ -885,7 +930,7 @@ enable_K5_wt_alloc(void)
}
}
void
static void
enable_K6_wt_alloc(void)
{
quad_t size;
@ -945,7 +990,7 @@ enable_K6_wt_alloc(void)
intr_restore(saveintr);
}
void
static void
enable_K6_2_wt_alloc(void)
{
quad_t size;

View File

@ -2733,6 +2733,7 @@ init386(first)
setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
initializecpucache();
/* make an initial tss so cpu can get interrupt stack on syscall! */
/* Note: -16 is so we can grow the trapframe if we came from vm86 */
@ -3009,6 +3010,7 @@ init386(first)
setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
initializecpucache();
/* make an initial tss so cpu can get interrupt stack on syscall! */
/* Note: -16 is so we can grow the trapframe if we came from vm86 */

View File

@ -747,25 +747,15 @@ init_secondary(void)
/* set up CPU registers and state */
cpu_setregs();
/* set up SSE/NX */
initializecpu();
/* set up FPU state on the AP */
npxinit();
/* set up SSE registers */
enable_sse();
if (cpu_ops.cpu_init)
cpu_ops.cpu_init();
#ifdef PAE
/* Enable the PTE no-execute bit. */
if ((amd_feature & AMDID_NX) != 0) {
uint64_t msr;
msr = rdmsr(MSR_EFER) | EFER_NXE;
wrmsr(MSR_EFER, msr);
}
#endif
/* A quick check from sanity claus */
cpuid = PCPU_GET(cpuid);
if (PCPU_GET(apic_id) != lapic_id()) {
@ -1530,6 +1520,7 @@ cpususpend_handler(void)
} else {
npxresume(&susppcbs[cpu]->sp_fpususpend);
pmap_init_pat();
initializecpu();
PCPU_SET(switchtime, 0);
PCPU_SET(switchticks, ticks);

View File

@ -99,14 +99,9 @@ void doreti_popl_fs_fault(void) __asm(__STRING(doreti_popl_fs_fault));
void dump_add_page(vm_paddr_t);
void dump_drop_page(vm_paddr_t);
void finishidentcpu(void);
#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
void enable_K5_wt_alloc(void);
void enable_K6_wt_alloc(void);
void enable_K6_2_wt_alloc(void);
#endif
void enable_sse(void);
void fillw(int /*u_short*/ pat, void *base, size_t cnt);
void initializecpu(void);
void initializecpucache(void);
void i686_pagezero(void *addr);
void sse2_pagezero(void *addr);
void init_AMD_Elan_sc520(void);
@ -114,6 +109,7 @@ int is_physical_memory(vm_paddr_t addr);
int isa_nmi(int cd);
vm_paddr_t kvtop(void *addr);
void panicifcpuunsupported(void);
void ppro_reenable_apic(void);
void printcpuinfo(void);
void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec);
int user_dbreg_trap(void);

View File

@ -598,22 +598,13 @@ init_secondary(void)
for (addr = 0; addr < NKPT * NBPDR - 1; addr += PAGE_SIZE)
invlpg(addr);
#if 0
/* set up SSE/NX */
initializecpu();
#endif
/* set up FPU state on the AP */
npxinit();
#if 0
/* set up SSE registers */
enable_sse();
#endif
#if 0 && defined(PAE)
/* Enable the PTE no-execute bit. */
if ((amd_feature & AMDID_NX) != 0) {
uint64_t msr;
msr = rdmsr(MSR_EFER) | EFER_NXE;
wrmsr(MSR_EFER, msr);
}
#endif
#if 0
/* A quick check from sanity claus */
if (PCPU_GET(apic_id) != lapic_id()) {

View File

@ -2310,6 +2310,7 @@ init386(first)
setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
initializecpucache();
/* make an initial tss so cpu can get interrupt stack on syscall! */
/* Note: -16 is so we can grow the trapframe if we came from vm86 */

View File

@ -405,30 +405,11 @@ printcpuinfo(void)
break;
case 0x5a0:
strcat(cpu_model, "Geode LX");
/*
* Make sure the TSC runs through suspension,
* otherwise we can't use it as timecounter
*/
wrmsr(0x1900, rdmsr(0x1900) | 0x20ULL);
break;
default:
strcat(cpu_model, "Unknown");
break;
}
#if defined(I586_CPU) && defined(CPU_WT_ALLOC)
if ((cpu_id & 0xf00) == 0x500) {
if (((cpu_id & 0x0f0) > 0)
&& ((cpu_id & 0x0f0) < 0x60)
&& ((cpu_id & 0x00f) > 3))
enable_K5_wt_alloc();
else if (((cpu_id & 0x0f0) > 0x80)
|| (((cpu_id & 0x0f0) == 0x80)
&& (cpu_id & 0x00f) > 0x07))
enable_K6_2_wt_alloc();
else if ((cpu_id & 0x0f0) > 0x50)
enable_K6_wt_alloc();
}
#endif
#else
if ((cpu_id & 0xf00) == 0xf00)
strcat(cpu_model, "AMD64 Processor");

View File

@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <x86/apicreg.h>
#include <machine/cpu.h>
#include <machine/cputypes.h>
#include <machine/frame.h>
#include <machine/intr_machdep.h>
@ -1264,9 +1263,6 @@ static void
apic_init(void *dummy __unused)
{
struct apic_enumerator *enumerator;
#ifndef __amd64__
uint64_t apic_base;
#endif
int retval, best;
/* We only support built in local APICs. */
@ -1308,12 +1304,7 @@ apic_init(void *dummy __unused)
* CPUs during early startup. We need to turn the local APIC back
* on on such CPUs now.
*/
if (cpu == CPU_686 && cpu_vendor_id == CPU_VENDOR_INTEL &&
(cpu_id & 0xff0) == 0x610) {
apic_base = rdmsr(MSR_APICBASE);
apic_base |= APICBASE_ENABLED;
wrmsr(MSR_APICBASE, apic_base);
}
ppro_reenable_apic();
#endif
/* Probe the CPU's in the system. */