diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c index e76bdef118d54..9c13c36184a73 100644 --- a/sys/dev/hwpmc/hwpmc_amd.c +++ b/sys/dev/hwpmc/hwpmc_amd.c @@ -907,6 +907,36 @@ pmc_amd_initialize(void) return (NULL); } + /* + * Some PC vendors enable the core counters in firmware to track + * performance. The best guess is that this is being used to control + * power management from within the SMM mode. We shouldn't just take + * over the PMCs in this case. The user should try disabling any + * performance monitoring or power management functions in the BIOS to + * safely make use of the counters. + */ + for (i = 0; i < AMD_PMC_CORE_DEFAULT; i++) { + if ((amd_feature2 & AMDID2_PCXC) != 0) { + error = rdmsr_safe(AMD_PMC_CORE_BASE + 2 * i, ®); + } else { + if (i >= AMD_NPMCS_K8) + break; + + error = rdmsr_safe(AMD_PMC_EVSEL_0 + i, ®); + } + + if (error != 0) { + printf("hwpmc: AMD evsel %d rdmsr failed!\n", i); + return (NULL); + } + + if ((reg & AMD_PMC_ENABLE) != 0) { + printf("hwpmc: PMCs maybe in use by firmware!\n"); + printf("hwpmc: Disable the PMC use in the BIOS before loading\n"); + return (NULL); + } + } + /* * Unforunately, there is no way to communicate that the original four * core counters are disabled through CPUIDs alone. We attempt to