aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorAli Mashtizadeh <ali@mashtizadeh.com>2026-06-05 23:48:53 +0000
committerMitchell Horne <mhorne@FreeBSD.org>2026-06-09 19:46:31 +0000
commitdded0ab415cc09eed506968366e383d406834823 (patch)
tree4e9b6cd81df2d2ab4cc06c39b6e5e2b009d73f67 /sys/dev
parent8f9aabbdbcd55b25b698bd762e8693d43f295bbd (diff)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/hwpmc/hwpmc_amd.c37
1 files 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
@@ -906,6 +908,37 @@ pmc_amd_initialize(void)
}
/*
+ * 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
* the prior default values that are only valid if we have the feature