Split out handling of cpu family specific MSRs from cpu_init_msrs()
authorrobert <robert@openbsd.org>
Tue, 20 Sep 2022 14:28:27 +0000 (14:28 +0000)
committerrobert <robert@openbsd.org>
Tue, 20 Sep 2022 14:28:27 +0000 (14:28 +0000)
to a separate function that gets called after identifycpu() so that
we have the required information to handle the correct MSRs for each
cpu.

Additionally, move the handling of the DE_CFG_SERIALIZE_LFENCE and
IA32_DEBUG_INTERFACE_LOCK MSRs out of identifycpu() to the new
function so that they get set again after a suspend/resume cycle as
well, which in fixes TSC sync failures.

discussed with and input from deraadt@, mlarkin@

sys/arch/amd64/amd64/acpi_machdep.c
sys/arch/amd64/amd64/cpu.c
sys/arch/amd64/amd64/identcpu.c
sys/arch/amd64/include/cpu.h

index db68939..1d97931 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: acpi_machdep.c,v 1.104 2022/08/07 23:56:06 guenther Exp $     */
+/*     $OpenBSD: acpi_machdep.c,v 1.105 2022/09/20 14:28:27 robert Exp $       */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  *
@@ -456,6 +456,7 @@ void
 acpi_resume_cpu(struct acpi_softc *sc, int state)
 {
        cpu_init_msrs(&cpu_info_primary);
+       cpu_fix_msrs(&cpu_info_primary);
 
 #if NISA > 0
        i8259_default_setup();
index 8ebd254..68c83d9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.c,v 1.159 2022/09/15 19:30:51 cheloha Exp $       */
+/*     $OpenBSD: cpu.c,v 1.160 2022/09/20 14:28:27 robert Exp $        */
 /* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
 
 /*-
@@ -601,6 +601,7 @@ cpu_attach(struct device *parent, struct device *self, void *aux)
 #endif
                cpu_tsx_disable(ci);
                identifycpu(ci);
+               cpu_fix_msrs(ci);
 #ifdef MTRR
                mem_range_attach();
 #endif /* MTRR */
@@ -615,6 +616,7 @@ cpu_attach(struct device *parent, struct device *self, void *aux)
                    CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY);
                cpu_intr_init(ci);
                identifycpu(ci);
+               cpu_fix_msrs(ci);
 #ifdef MTRR
                mem_range_attach();
 #endif /* MTRR */
@@ -955,6 +957,9 @@ cpu_hatch(void *v)
                atomic_setbits_int(&ci->ci_flags, CPUF_IDENTIFIED);
        }
 
+       /* These have to run after identifycpu() */ 
+       cpu_fix_msrs(ci);
+
        /*
         * Test if our TSC is synchronized for the first time.
         * Note that interrupts are off at this point.
@@ -1095,9 +1100,6 @@ extern vector Xsyscall_meltdown, Xsyscall, Xsyscall32;
 void
 cpu_init_msrs(struct cpu_info *ci)
 {
-       uint64_t msr;
-       int family;
-
        wrmsr(MSR_STAR,
            ((uint64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |
            ((uint64_t)GSEL(GUCODE32_SEL, SEL_UPL) << 48));
@@ -1109,18 +1111,60 @@ cpu_init_msrs(struct cpu_info *ci)
        wrmsr(MSR_FSBASE, 0);
        wrmsr(MSR_GSBASE, (u_int64_t)ci);
        wrmsr(MSR_KERNELGSBASE, 0);
+       patinit(ci);
+}
 
-       family = ci->ci_family;
-       if (strcmp(cpu_vendor, "GenuineIntel") == 0 &&
-           (family > 6 || (family == 6 && ci->ci_model >= 0xd)) &&
-           rdmsr_safe(MSR_MISC_ENABLE, &msr) == 0 &&
-           (msr & MISC_ENABLE_FAST_STRINGS) == 0) {
-               msr |= MISC_ENABLE_FAST_STRINGS;
-               wrmsr(MSR_MISC_ENABLE, msr);
-               DPRINTF("%s: enabled fast strings\n", ci->ci_dev->dv_xname);
+void
+cpu_fix_msrs(struct cpu_info *ci)
+{
+       int family = ci->ci_family;
+       uint64_t msr;
+
+       if (!strcmp(cpu_vendor, "GenuineIntel")) {
+               if ((family > 6 || (family == 6 && ci->ci_model >= 0xd)) &&
+                   rdmsr_safe(MSR_MISC_ENABLE, &msr) == 0 &&
+                   (msr & MISC_ENABLE_FAST_STRINGS) == 0) {
+                       msr |= MISC_ENABLE_FAST_STRINGS;
+                       wrmsr(MSR_MISC_ENABLE, msr);
+                       DPRINTF("%s: enabled fast strings\n", ci->ci_dev->dv_xname);
+       
+               /*
+                * Attempt to disable Silicon Debug and lock the configuration
+                * if it's enabled and unlocked.
+                */
+               if (cpu_ecxfeature & CPUIDECX_SDBG) {
+                       msr = rdmsr(IA32_DEBUG_INTERFACE);
+                       if ((msr & IA32_DEBUG_INTERFACE_ENABLE) &&
+                           (msr & IA32_DEBUG_INTERFACE_LOCK) == 0) {
+                               msr &= IA32_DEBUG_INTERFACE_MASK;
+                               msr |= IA32_DEBUG_INTERFACE_LOCK;
+                               wrmsr(IA32_DEBUG_INTERFACE, msr);
+                       } else if (msr & IA32_DEBUG_INTERFACE_ENABLE)
+                               printf("%s: cannot disable silicon debug\n",
+                                   ci->ci_dev->dv_xname);
+                       }
+               }
        }
 
-       patinit(ci);
+       /*
+        * "Mitigation G-2" per AMD's Whitepaper "Software Techniques
+        * for Managing Speculation on AMD Processors"
+        *
+        * By setting MSR C001_1029[1]=1, LFENCE becomes a dispatch
+        * serializing instruction.
+        *
+        * This MSR is available on all AMD families >= 10h, except 11h
+        * where LFENCE is always serializing.
+        */
+       if (!strcmp(cpu_vendor, "AuthenticAMD")) {
+               if (family >= 0x10 && family != 0x11) {
+                       msr = rdmsr(MSR_DE_CFG);
+                       if ((msr & DE_CFG_SERIALIZE_LFENCE) == 0) {
+                               msr |= DE_CFG_SERIALIZE_LFENCE;
+                               wrmsr(MSR_DE_CFG, msr);
+                       }
+               }
+       }
 }
 
 void
index 7cb1d81..09c7ce8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: identcpu.c,v 1.127 2022/08/30 17:09:21 dv Exp $       */
+/*     $OpenBSD: identcpu.c,v 1.128 2022/09/20 14:28:27 robert Exp $   */
 /*     $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $        */
 
 /*
@@ -699,47 +699,6 @@ identifycpu(struct cpu_info *ci)
        replacemeltdown();
        x86_print_cacheinfo(ci);
 
-       /*
-        * "Mitigation G-2" per AMD's Whitepaper "Software Techniques
-        * for Managing Speculation on AMD Processors"
-        *
-        * By setting MSR C001_1029[1]=1, LFENCE becomes a dispatch
-        * serializing instruction.
-        *
-        * This MSR is available on all AMD families >= 10h, except 11h
-        * where LFENCE is always serializing.
-        */
-       if (!strcmp(cpu_vendor, "AuthenticAMD")) {
-               if (ci->ci_family >= 0x10 && ci->ci_family != 0x11) {
-                       uint64_t msr;
-
-                       msr = rdmsr(MSR_DE_CFG);
-                       if ((msr & DE_CFG_SERIALIZE_LFENCE) == 0) {
-                               msr |= DE_CFG_SERIALIZE_LFENCE;
-                               wrmsr(MSR_DE_CFG, msr);
-                       }
-               }
-       }
-
-       /*
-        * Attempt to disable Silicon Debug and lock the configuration
-        * if it's enabled and unlocked.
-        */
-       if (!strcmp(cpu_vendor, "GenuineIntel") &&
-           (cpu_ecxfeature & CPUIDECX_SDBG)) {
-               uint64_t msr;
-
-               msr = rdmsr(IA32_DEBUG_INTERFACE);
-               if ((msr & IA32_DEBUG_INTERFACE_ENABLE) &&
-                   (msr & IA32_DEBUG_INTERFACE_LOCK) == 0) {
-                       msr &= IA32_DEBUG_INTERFACE_MASK;
-                       msr |= IA32_DEBUG_INTERFACE_LOCK;
-                       wrmsr(IA32_DEBUG_INTERFACE, msr);
-               } else if (msr & IA32_DEBUG_INTERFACE_ENABLE)
-                       printf("%s: cannot disable silicon debug\n",
-                           ci->ci_dev->dv_xname);
-       }
-
        if (CPU_IS_PRIMARY(ci)) {
 #ifndef SMALL_KERNEL
                if (!strcmp(cpu_vendor, "AuthenticAMD") &&
index 2689505..1a8c6dd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.h,v 1.150 2022/08/30 17:09:21 dv Exp $    */
+/*     $OpenBSD: cpu.h,v 1.151 2022/09/20 14:28:27 robert Exp $        */
 /*     $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $     */
 
 /*-
@@ -428,6 +428,7 @@ void        i8254_inittimecounter_simple(void);
 void   i8259_default_setup(void);
 
 void cpu_init_msrs(struct cpu_info *);
+void cpu_fix_msrs(struct cpu_info *);
 void cpu_tsx_disable(struct cpu_info *);
 
 /* dkcsum.c */