The branch stable/15 has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=620bca5338abdb599e304e3437446f7731cb78db
commit 620bca5338abdb599e304e3437446f7731cb78db Author: Ali Mashtizadeh <[email protected]> AuthorDate: 2026-06-05 23:48:53 +0000 Commit: Mitchell Horne <[email protected]> CommitDate: 2026-07-10 15:28:08 +0000 hwpmc: Disable AMD PMCs if in an unsupported VM AMD does not have a CPUID bit to indicate the lack of K8 PMCs. If all other PMC features are not present we should test an event selector to see if it stores and returns a value. If the VM is implemented correctly, this should result in a #GP on the initial wrmsr_safe. Bhyve and a few other VMs ignore writes, so I got one step further and test that it retains the OS and USR bits. Tested on Zen 5 native and a Zen 5 Bhyve virtual machine. This code should not run on any recent hardware, except in a VM, as it checks that the core counter extension is missing. PR: 268943 Reported by: Sandipan Das, John F. Carr <[email protected]> Reviewed by: mhorne, imp Sponsored by: Netflix MFC after: 1 week Pull Request: https://github.com/freebsd/freebsd-src/pull/2272/changes (cherry picked from commit dded0ab415cc09eed506968366e383d406834823) --- sys/dev/hwpmc/hwpmc_amd.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c index c174502caefb..e950ee3c84af 100644 --- a/sys/dev/hwpmc/hwpmc_amd.c +++ b/sys/dev/hwpmc/hwpmc_amd.c @@ -788,12 +788,14 @@ amd_pcpu_fini(struct pmc_mdep *md, int cpu) struct pmc_mdep * pmc_amd_initialize(void) { + struct amd_descr *d; struct pmc_classdep *pcd; struct pmc_mdep *pmc_mdep; + uint64_t reg; enum pmc_cputype cputype; - int error, i, ncpus; + int ncpus, i; int family, model, stepping; - struct amd_descr *d; + int error; /* * The presence of hardware performance counters on the AMD @@ -824,6 +826,37 @@ pmc_amd_initialize(void) return (NULL); } + /* + * Unforunately, there is no way to communicate that the original four + * core counters are disabled through CPUIDs alone. We attempt to + * write and read back the MSR to validate that it is working. + * + * Referenced the BIOS and Kernel Developer Guide for AMD Athlon 64 and + * AMD Opteron Processors 26094 Rev. 3.24 January, 2005 to ensure these + * fields are valid. + */ + if ((amd_feature2 & AMDID2_PCXC) == 0) { + error = wrmsr_safe(AMD_PMC_EVSEL_0, AMD_PMC_OS | AMD_PMC_USR); + if (error != 0) { + printf("hwpmc: AMD evsel 0 wrmsr failed!\n"); + return (NULL); + } + + error = rdmsr_safe(AMD_PMC_EVSEL_0, ®); + if (error != 0) { + printf("hwpmc: AMD evsel 0 rdmsr failed!\n"); + return (NULL); + } + + if (reg == 0) { + printf("hwpmc: AMD evsel returned invalid value! " + "You may be in a VM without PMC support.\n"); + return (NULL); + } + + wrmsr(AMD_PMC_EVSEL_0, 0); + } + /* * From PPR for AMD Family 1Ah, a new cpuid leaf specifies the maximum * number of PMCs of each type. If we do not have that leaf, we use
