index | | raw e-mail
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
home |
help
