From nobody Fri Jul 10 15:28:28 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gxbMK0096z6lJ6J for ; Fri, 10 Jul 2026 15:28:29 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gxbMJ66cyz4449 for ; Fri, 10 Jul 2026 15:28:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1783697308; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=2XJZ3XcgDtUNu25RZmPp6/mShP/0ml94SZyEKgFl5E8=; b=g4bLsfsOyzz1pmB+tUhlNB2isnH9txqBsXdjirNGXoQ1z79pf2nuIUr5FUFbBS5s6yJ4yt CWVmTcuIj7Mfo1CujdffHaDOTUMbji8iJ5MPBXEvbHn0/AlyVcR/0oIX8Lb/75MtQDYCrR 5pPDhPmSIvaxmpmJZ0Ni0QUG3VrazL0onTMTT4EIxrDiDEdStgq5Tr2xFfnXtQrOGElOO5 2K+u+rRGk5EyTPHdt1CijY78CT4UHsc/NoPcer1PlhaG3rpJA0SJvv6F8AEv2YLe7qNPkA y10uo2SFlylJLHIIINruIWyGIC1lVvWlvS35BiIakgt3Ss3dsf38xyVESFItLQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1783697308; a=rsa-sha256; cv=none; b=XitZ22am5ku9He711FXi9rKQv5Ee6AU6KehrHEpoTm+USYbFuqjQx1I80KAibDwzAy/Zxl QGkmIJEAW8EtXkMGZ//4dJSJ3SZqYlWCvqbIBPGHrPToCs0mpjlRl84k7fluxpVzy1heWb Teej3y2NvngjJpbiug3jJObP9sBZ1lrhI/5e4INmwXo8WOb1llKeMEtiv46iYAP87egU+I V00ETiRUPOAwjaSwsAaXT2eA8gJlkkeF35AzsP1BwfmV11vbENQFw/E9ZpwWaXWs4F5zHY 553dRBy24S2eQkPvHnhdz5QfLDgXjYWuSj80RFhXsd4I8RrguYdvhSdLgQSo0w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1783697308; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=2XJZ3XcgDtUNu25RZmPp6/mShP/0ml94SZyEKgFl5E8=; b=MeqYaVEhjarA5PEStEmkdPCWmvF90tSOr3etu3vgTmwhqE3zahZE7PPJfKhVb04SBHAOaO 2dzae9T7UuiyE82gNweeeMTTh3xsrjh56u4RRzhGJ3a7XgBnHRiTPFKR8ybSeeCa1N4fV+ hvEFuxqgYUlKROPywd26MkGpqdVe594BrgSoSLrEbBv1Gf3wUqGL1+X4RFyCIH7Yh9LW3X YmOaYEPTpt6D7Q1z9xKS+kIjWeoprCs4IO22pnZw75/0w6ZCb8EO8VOpzm4WSBHIRltljr 9pwl9nhiuKpxMs+cl1Oql8+zHRMYEMEg1X0doM3+tdxv8VlmfGKPTrMtD+BCuw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gxbMJ5357z11G6 for ; Fri, 10 Jul 2026 15:28:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 33c2d by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 10 Jul 2026 15:28:28 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Cc: Ali Mashtizadeh From: Mitchell Horne Subject: git: a854d977c39a - stable/15 - hwpmc_amd: Avoid using PMCs if in use by firmware List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mhorne X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: a854d977c39a09dfbe3d9b4b5c84a8008ef0710a Auto-Submitted: auto-generated Date: Fri, 10 Jul 2026 15:28:28 +0000 Message-Id: <6a510f9c.33c2d.1d56f4f5@gitrepo.freebsd.org> The branch stable/15 has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=a854d977c39a09dfbe3d9b4b5c84a8008ef0710a commit a854d977c39a09dfbe3d9b4b5c84a8008ef0710a Author: Ali Mashtizadeh AuthorDate: 2026-06-10 23:20:16 +0000 Commit: Mitchell Horne CommitDate: 2026-07-10 15:28:09 +0000 hwpmc_amd: Avoid using PMCs if in use by firmware Some firmwares use the PMCs to monitor OS performance. We can't be certain that the BIOS would detect any change to the counters if we reprogram them. In cases where the firmware is using the PMCs to control power management this could have dangerous side effects or unexpected performance effects. During initialization, detect if any of the counters are enabled and fail if so. Reported by: Sandipan Das Reviewed by: mhorne MFC after: 1 week Sponsored by: Netflix Pull Request: https://github.com/freebsd/freebsd-src/pull/2277 (cherry picked from commit cf469ab83012ee47d06bc89874b6c109f49446e0) --- sys/dev/hwpmc/hwpmc_amd.c | 110 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 33 deletions(-) diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c index e950ee3c84af..792411ec2033 100644 --- a/sys/dev/hwpmc/hwpmc_amd.c +++ b/sys/dev/hwpmc/hwpmc_amd.c @@ -782,16 +782,84 @@ amd_pcpu_fini(struct pmc_mdep *md, int cpu) return (0); } +/* + * Check that the PMC hardware is safe to use. First, we check that the PMCs + * are not in use by firmware or another module. Second, if none of the PMC + * feature flags are set, we check that the event selector is working, because + * virtual machines have no way to communicate the absence of PMCs. + */ +static int +amd_hwcheck(void) +{ + uint64_t reg; + int error, i; + + /* + * 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_core_npmcs; i++) { + error = rdmsr_safe(amd_pmcdesc[i].pm_evsel, ®); + if (error != 0) { + printf("hwpmc: AMD evsel %d rdmsr failed!\n", i); + return (-1); + } + + 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 (-1); + } + } + + /* + * Unfortunately, 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 (-1); + } + + error = rdmsr_safe(AMD_PMC_EVSEL_0, ®); + if (error != 0) { + printf("hwpmc: AMD evsel 0 rdmsr failed!\n"); + return (-1); + } + + if (reg == 0) { + printf("hwpmc: AMD evsel returned invalid value! " + "You may be in a VM without PMC support.\n"); + return (-1); + } + + wrmsr(AMD_PMC_EVSEL_0, 0); + } + + return (0); +} + /* * Initialize ourselves. */ struct pmc_mdep * pmc_amd_initialize(void) { + u_int regs[4]; struct amd_descr *d; struct pmc_classdep *pcd; struct pmc_mdep *pmc_mdep; - uint64_t reg; enum pmc_cputype cputype; int ncpus, i; int family, model, stepping; @@ -826,37 +894,6 @@ 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 @@ -872,7 +909,6 @@ pmc_amd_initialize(void) amd_df_npmcs = AMD_PMC_DF_DEFAULT; if (cpu_exthigh >= CPUID_EXTPERFMON) { - u_int regs[4]; do_cpuid(CPUID_EXTPERFMON, regs); if (regs[1] != 0) { amd_core_npmcs = EXTPERFMON_CORE_PMCS(regs[1]); @@ -939,6 +975,14 @@ pmc_amd_initialize(void) amd_npmcs += amd_df_npmcs; } + /* + * Sanity check that the hardware is safe to use. Do not read or write + * any of the PMC MSRs until after this check passes. + */ + if (amd_hwcheck() < 0) { + return (NULL); + } + /* * Allocate space for pointers to PMC HW descriptors and for * the MDEP structure used by MI code.