From 71f9e38fa2d4dc13b36ced356445eea08f620127 Mon Sep 17 00:00:00 2001 From: jhb Date: Mon, 22 Dec 2014 19:53:55 +0000 Subject: [PATCH] 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). --- sys/amd64/amd64/mp_machdep.c | 2 +- sys/i386/i386/initcpu.c | 89 +++++++++++++++++++++++++++--------- sys/i386/i386/machdep.c | 2 + sys/i386/i386/mp_machdep.c | 17 ++----- sys/i386/include/md_var.h | 8 +--- sys/i386/xen/mp_machdep.c | 19 ++------ sys/pc98/pc98/machdep.c | 1 + sys/x86/x86/identcpu.c | 19 -------- sys/x86/x86/local_apic.c | 11 +---- 9 files changed, 83 insertions(+), 85 deletions(-) diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 629ffaa2b6d5..ae4421e8f540 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -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 */ diff --git a/sys/i386/i386/initcpu.c b/sys/i386/i386/initcpu.c index f93ea13cb546..6872aecf47a9 100644 --- a/sys/i386/i386/initcpu.c +++ b/sys/i386/i386/initcpu.c @@ -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; diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 1b540755c6f0..d764a0bf71c3 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -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 */ diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index acc498923e05..e368ee85bb07 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -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); diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index c2c8c6c64ac0..950fa1f0556c 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -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); diff --git a/sys/i386/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c index 165b319bd6ae..3502151e3239 100644 --- a/sys/i386/xen/mp_machdep.c +++ b/sys/i386/xen/mp_machdep.c @@ -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()) { diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index f17bc198716c..e0469602408b 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -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 */ diff --git a/sys/x86/x86/identcpu.c b/sys/x86/x86/identcpu.c index e33ab8a2fe71..da24761057f5 100644 --- a/sys/x86/x86/identcpu.c +++ b/sys/x86/x86/identcpu.c @@ -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"); diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c index 9c33ee410a55..25cdec605f27 100644 --- a/sys/x86/x86/local_apic.c +++ b/sys/x86/x86/local_apic.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -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. */