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, &reg);
+               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

Reply via email to