summaryrefslogtreecommitdiffstats
path: root/sys/i386/i386
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2014-12-22 19:53:55 +0000
committerjhb <jhb@FreeBSD.org>2014-12-22 19:53:55 +0000
commit71f9e38fa2d4dc13b36ced356445eea08f620127 (patch)
treef5ea67c6a3628107d872a3d3fd63e6e23fd40a44 /sys/i386/i386
parent77f68eb34a5227ee871dceac46abbd1db966388b (diff)
downloadFreeBSD-src-71f9e38fa2d4dc13b36ced356445eea08f620127.zip
FreeBSD-src-71f9e38fa2d4dc13b36ced356445eea08f620127.tar.gz
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).
Diffstat (limited to 'sys/i386/i386')
-rw-r--r--sys/i386/i386/initcpu.c89
-rw-r--r--sys/i386/i386/machdep.c2
-rw-r--r--sys/i386/i386/mp_machdep.c17
3 files changed, 73 insertions, 35 deletions
diff --git a/sys/i386/i386/initcpu.c b/sys/i386/i386/initcpu.c
index f93ea13..6872aec 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 1b54075..d764a0b 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 acc4989..e368ee8 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);
OpenPOWER on IntegriCloud