> Date: Sat, 22 Oct 2022 13:43:23 -0500 > From: Scott Cheloha <scottchel...@gmail.com> > > On Fri, Oct 07, 2022 at 12:38:24PM -0500, Scott Cheloha wrote: > > On Fri, Oct 07, 2022 at 11:27:45AM -0500, Scott Cheloha wrote: > > > 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. > > > > ... and sent the wrong patch. > > > > This is patch I meant to send. Sorry for the noise. > > 3 week bump. > > Is this patch ok? > > I have the following tests. Obviously the calibrated frequencies > change from boot to boot, but I imagine they are usually in the > ballpark of the given value. > > TESTER CALIBRATE MSR MACHINE > hrovje 2994383812 3000000000 AMD EPYC 7313P 16-Core > Processor, 2994.38 MHz, 19-01-01 > hrovje 2650006089 2650000000 AMD EPYC 7413 24-Core > Processor, 2650.06 MHz, 19-01-01 > hrovje 1996256074 2000000000 AMD EPYC 7702P 64-Core > Processor, 1996.28 MHz, 17-31-00 > hrovje 2370556228 2375000000 AMD Ryzen 5 4500U with > Radeon Graphics, 2370.59 MHz, 17-60-01 > jmc 1996260074 2000000000 AMD Ryzen 7 4700U with Radeon > Graphics, 2000.00 MHz, 17-60-01 > Masato Asou 3593266153 3600000000 AMD Ryzen 7 3700X 8-Core > Processor, 3593.49 MHz, 17-71-00 > Masato Asou 2295691309 2300000000 AMD Ryzen 5 5625U with Radeon > Graphics, 2295.73 MHz, 19-50-00 > robert 3892696616 3900000000 AMD Ryzen 7 3800XT > 8-Core Processor, 3892.77 MHz, 17-71-00 > Timo Myyra 1996264149 2000000000 AMD Ryzen 5 2500U with Radeon > Vega Mobile Gfx, 1996.30 MHz, 17-11-00 > > In every case, the MSR math arrives at a frequency similar to but > rounder than the calibrated frequency.
So the biggest change is ~800 ppm, whereas our NTP code can handle 5000 ppm. So that's probably fine. ok kettenis@ > 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 22 Oct 2022 18:39:57 -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 > 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 22 Oct 2022 18:39:57 -0000 > @@ -100,6 +100,67 @@ 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 10h+ CPUs have Core::X86::Msr:HWCR and the TscFreqSel > + * bit. If TscFreqSel hasn't been set, the TSC isn't advancing > + * at the core P0 frequency and we need to calibrate by hand. > + */ > + if (ci->ci_family < 0x10) > + return 0; > + if (!ISSET(rdmsr(MSR_HWCR), HWCR_TSCFREQSEL)) > + return 0; > + > + /* > + * In 10h+ CPUs, Core::X86::Msr::PStateDef defines the voltage > + * and frequency for each core P-state. We want the P0 frequency. > + * 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 <= 0x07 || divisor >= 0x2d) > + return 0; /* reserved */ > + if (divisor >= 0x1b && divisor % 2 == 1) > + return 0; /* reserved */ > + multiplier = def & 0xff; > + if (multiplier <= 0x0f) > + return 0; /* reserved */ > + break; > + default: > + return 0; > + } > + > + return base * multiplier / divisor; > +} > + > void > tsc_identify(struct cpu_info *ci) > { > @@ -118,6 +179,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); > } > >