git: dded0ab415cc - main - hwpmc: Disable AMD PMCs if in an unsupported VM
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 09 Jun 2026 19:46:34 UTC
The branch main has been updated by mhorne:
URL: https://cgit.FreeBSD.org/src/commit/?id=dded0ab415cc09eed506968366e383d406834823
commit dded0ab415cc09eed506968366e383d406834823
Author: Ali Mashtizadeh <ali@mashtizadeh.com>
AuthorDate: 2026-06-05 23:48:53 +0000
Commit: Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2026-06-09 19:46:31 +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 <jfc@mit.edu>
Reviewed by: mhorne, imp
Sponsored by: Netflix
MFC after: 1 week
Pull Request: https://github.com/freebsd/freebsd-src/pull/2272/changes
---
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 299021494716..e76bdef118d5 100644
--- a/sys/dev/hwpmc/hwpmc_amd.c
+++ b/sys/dev/hwpmc/hwpmc_amd.c
@@ -869,12 +869,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, nclasses;
+ int ncpus, nclasses, i;
int family, model, stepping;
- struct amd_descr *d;
+ int error;
/*
* The presence of hardware performance counters on the AMD
@@ -905,6 +907,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