On Fri, Oct 07, 2022 at 09:34:46AM -0500, Scott Cheloha wrote:
> On Thu, Sep 29, 2022 at 09:14:51AM -0500, Scott Cheloha wrote:
> > This patch computes the TSC frequency for AMD family 17h and 19h CPUs
> > (Zen microarchitecture and up) from AMD-specific MSRs.  Computing the
> > TSC frequency is faster than calibrating with a separate timer and
> > introduces no error.
> > 
> > We already do this for Intel CPUs in tsc_freq_cpuid().
> > 
> > I got several successful test reports on family 17h and 19h CPUs in
> > response to this mail:
> > 
> > https://marc.info/?l=openbsd-tech&m=166394236029484&w=2
> > 
> > The details for computing the frequency are in the PPR for 17h and
> > 19h, found here (page numbers are cited in the patch):
> > 
> > https://www.amd.com/system/files/TechDocs/55570-B1-PUB.zip
> > https://www.amd.com/system/files/TechDocs/56214-B0-PUB.zip
> > 
> > The process is slightly more complicated on AMD CPU families 10h-16h.
> > I will deal with them in a separate commit.
> > 
> > ok?
> 
> 1 week bump.

Whoops, forgot the patch, my mistake.

Index: amd64/tsc.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/tsc.c,v
retrieving revision 1.29
diff -u -p -r1.29 tsc.c
--- amd64/tsc.c 22 Sep 2022 04:57:08 -0000      1.29
+++ amd64/tsc.c 29 Sep 2022 01:52:27 -0000
@@ -100,6 +100,66 @@ tsc_freq_cpuid(struct cpu_info *ci)
        return (0);
 }
 
+uint64_t
+tsc_freq_msr(struct cpu_info *ci)
+{
+       uint64_t base, def, divisor, multiplier;
+
+       if (strcmp(cpu_vendor, "AuthenticAMD") != 0)
+               return 0;
+
+       /*
+        * All family 10h+ CPUs have MSR_HWCR and the TscFreqSel bit.
+        * If TscFreqSel is not set the TSC does not advance at the P0
+        * frequency, in which case something is wrong and we need to
+        * calibrate by hand.
+        */
+       if (ci->ci_family < 0x10)
+               return 0;
+       if (!ISSET(rdmsr(MSR_HWCR), HWCR_TSCFREQSEL))
+               return 0;
+
+       /*
+        * In family 10h+, core P-state voltage/frequency definitions
+        * are kept in MSR_PSTATEDEF.  We're interested in the MSR
+        * describing P0.  If the EN bit isn't set, the register doesn't
+        * define a valid P-state.
+        */
+       def = rdmsr(MSR_PSTATEDEF(0));
+       if (!ISSET(def, PSTATEDEF_EN))
+               return 0;
+
+       switch (ci->ci_family) {
+       case 0x17:
+       case 0x19:
+               /*
+                * PPR for AMD Family 17h [...]:
+                * Models 01h,08h B2, Rev 3.03, pp. 33, 139-140
+                * Model 18h B1, Rev 3.16, pp. 36, 143-144
+                * Model 60h A1, Rev 3.06, pp. 33, 155-157
+                * Model 71h B0, Rev 3.06, pp. 28, 150-151
+                *
+                * PPR for AMD Family 19h [...]:
+                * Model 21h B0, Rev 3.05, pp. 33, 166-167
+                *
+                * OSRR for AMD Family 17h processors,
+                * Models 00h-2Fh, Rev 3.03, pp. 130-131
+                */
+               base = 200000000;                       /* 200.0 MHz */
+               divisor = (def >> 8) & 0x3f;
+               if (divisor < 0x8 || divisor > 0x2c)
+                       return 0;                       /* reserved */
+               if (divisor >= 0x1b && divisor % 2 == 1)
+                       return 0;                       /* reserved */
+               multiplier = def & 0xff;
+               break;
+       default:
+               return 0;
+       }
+
+       return base * multiplier / divisor;
+}
+
 void
 tsc_identify(struct cpu_info *ci)
 {
@@ -118,6 +178,8 @@ tsc_identify(struct cpu_info *ci)
        tsc_is_invariant = 1;
 
        tsc_frequency = tsc_freq_cpuid(ci);
+       if (tsc_frequency == 0)
+               tsc_frequency = tsc_freq_msr(ci);
        if (tsc_frequency > 0)
                delay_init(tsc_delay, 5000);
 }
Index: include/specialreg.h
===================================================================
RCS file: /cvs/src/sys/arch/amd64/include/specialreg.h,v
retrieving revision 1.94
diff -u -p -r1.94 specialreg.h
--- include/specialreg.h        30 Aug 2022 17:09:21 -0000      1.94
+++ include/specialreg.h        29 Sep 2022 01:52:28 -0000
@@ -540,6 +540,10 @@
  */
 #define        MSR_HWCR        0xc0010015
 #define                HWCR_FFDIS              0x00000040
+#define                HWCR_TSCFREQSEL         0x01000000
+
+#define        MSR_PSTATEDEF(_n)       (0xc0010064 + (_n))
+#define                PSTATEDEF_EN            0x8000000000000000ULL
 
 #define        MSR_NB_CFG      0xc001001f
 #define                NB_CFG_DISIOREQLOCK     0x0000000000000004ULL

Reply via email to