From nobody Tue Jun 23 16:37:04 2026 X-Original-To: dev-commits-src-all@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 4gl9hK35s9z6hjNy for ; Tue, 23 Jun 2026 16:37:05 +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 4gl9hK0Yfqz3bVS for ; Tue, 23 Jun 2026 16:37:05 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782232625; 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=DTtP5x13n8Q6K0DybOH6eq2ic2L079KwRluiysSuizM=; b=aMB8OtZieycK+i512ZG8igE/nW8kq82pezDhO2HJVxx+F63EuSBaS5lJ+c+bj/zoqb5jWy pCDQvfJVyRccyNKmkZWnomo7ktBbO9uxeqL87hMXIfxVj9N20lY1k/FYI4/wNQxvSDsZNg plcjx3R2NGQOgtwkLhLMLXPt/nVPB6Qwyck9+hHngx+GezY0f168hvupA1owL1IoRIe78B j2GVERsg/yTVLWTAGASasMphJOnTXZTBPhJePZOTDq7yBtubYgEopn/MvbP+ENL/qazJ9H hZ+c17rMS1LSS881gcG0w19CkeZAwzY38FIEH/MMozE766RWtaVRqnqiJNm8qQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782232625; a=rsa-sha256; cv=none; b=iX/1J0mjngrgWhisajqa4uN2cQqwgjG5+pqxuJXNbCnlLcLmkDfDIAz1pffOnXLYV2OG04 FX4PgouxDXRk4S9b4o7tbT8hmHye7B0p+Ft3gN3lfBrFL4KhJ1ZPzLLlHex7vYq2tD6X+t /oOYtp+/LIu9bqAWJlgAgRBsWehH1wzBHvF1m2A9yiNnsQahRu9PAfsPJoKuwVqr2FzkM6 dIv5iuYw6ksKv5dmkxCCDqk+sVgmMjrBISHFPDu0YmBjpWbS+kcv+9f4l/qh/mW8ypY/aI DkZ34tjlDPmEfX0uvupmGg9P8UsYg60cDetu2cjoirfGUWl1T6ldByp5keacIA== 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=1782232625; 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=DTtP5x13n8Q6K0DybOH6eq2ic2L079KwRluiysSuizM=; b=m36heHTqYBYhDMmBfK6LYcNm893yH5s304Djozo++iS6G6p5159HwIM/1+3KTepruMg5e2 E8gPJyZC6rPw36HOrMayh1GnCnI0QCDyQ5MWxiKR0cNpqvKa4hPtffrCLw996ZNJR/aAdi fEkd9zsN7Pe28hKjugK2h+nWA0CvUo/z8TvSgnpFsSuCbOBKHhJ19TvkuRID591zHMsRsL +ehGmniOwrGhJFuJvcIWZae9Xi9OLxV4+r8BjbzmiRdXGIRnJHp8kRUXz3BZ0dN+YW24yv LE+Di1s/xj4p2fQBOEn76loA/0rOIY6fWqibyCLQDCzYmDQ+e4uA3/TnmAEsuA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gl9hJ6GPxzhnJ for ; Tue, 23 Jun 2026 16:37:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 27fa1 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 23 Jun 2026 16:37:04 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Ali Mashtizadeh From: Mitchell Horne Subject: git: cf469ab83012 - main - hwpmc_amd: Avoid using PMCs if in use by firmware List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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/main X-Git-Reftype: branch X-Git-Commit: cf469ab83012ee47d06bc89874b6c109f49446e0 Auto-Submitted: auto-generated Date: Tue, 23 Jun 2026 16:37:04 +0000 Message-Id: <6a3ab630.27fa1.55266c52@gitrepo.freebsd.org> The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=cf469ab83012ee47d06bc89874b6c109f49446e0 commit cf469ab83012ee47d06bc89874b6c109f49446e0 Author: Ali Mashtizadeh AuthorDate: 2026-06-10 23:20:16 +0000 Commit: Mitchell Horne CommitDate: 2026-06-23 16:36:47 +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 --- 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 e76bdef118d5..b075837cd3e8 100644 --- a/sys/dev/hwpmc/hwpmc_amd.c +++ b/sys/dev/hwpmc/hwpmc_amd.c @@ -863,16 +863,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, nclasses, i; int family, model, stepping; @@ -907,37 +975,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 @@ -953,7 +990,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]); @@ -1020,6 +1056,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.