Date: Fri, 24 Apr 2026 15:34:00 +0000 From: Mitchell Horne <mhorne@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Ali Mashtizadeh <ali@mashtizadeh.com> Subject: git: 576c6e9620df - main - pmc: Implement the feature bits for recent Zen 4/5 Message-ID: <69eb8d68.36b92.4722e81@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=576c6e9620dff3e92f3c5d1e5be4d92c9eb29828 commit 576c6e9620dff3e92f3c5d1e5be4d92c9eb29828 Author: Ali Mashtizadeh <ali@mashtizadeh.com> AuthorDate: 2026-04-08 05:36:53 +0000 Commit: Mitchell Horne <mhorne@FreeBSD.org> CommitDate: 2026-04-24 15:33:42 +0000 pmc: Implement the feature bits for recent Zen 4/5 Ensure that the optional MSRs and the user flags are guarded by the cpuid feature flags. This prevents the user from triggering undefined behavior or crashes on AMD processors where some of these features are not present. As part of this, I added the branch target and DATA4 MSRs to the IBS op state as those are only present on a subset of the Zen chips that I have tested. Reviewed by: mhorne Sponsored by: Netflix Pull Request: https://github.com/freebsd/freebsd-src/pull/2133 --- lib/libpmc/libpmc.c | 29 ++++++++++++++++++++++++++++- lib/libpmc/pmc.ibs.3 | 10 ++++++---- sys/dev/hwpmc/hwpmc_ibs.c | 12 +++++++++--- sys/dev/hwpmc/hwpmc_ibs.h | 15 +++++++++------ 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c index ebb642e8d16b..562000aef4e4 100644 --- a/lib/libpmc/libpmc.c +++ b/lib/libpmc/libpmc.c @@ -32,6 +32,10 @@ #include <sys/pmc.h> #include <sys/syscall.h> +#if defined(__amd64__) || defined(__i386__) +#include <machine/cpufunc.h> +#endif + #include <ctype.h> #include <errno.h> #include <err.h> @@ -697,6 +701,8 @@ ibs_allocate_pmc(enum pmc_event pe, char *ctrspec, { char *e, *p, *q; uint64_t ctl, ldlat; + u_int ibs_features; + u_int regs[4]; pmc_config->pm_caps |= (PMC_CAP_SYSTEM | PMC_CAP_EDGE | PMC_CAP_PRECISE); @@ -719,11 +725,22 @@ ibs_allocate_pmc(enum pmc_event pe, char *ctrspec, return (-1); } + /* Read the ibs feature flags */ + ibs_features = 0; + do_cpuid(0x80000000, regs); + if (regs[0] >= CPUID_IBSID) { + do_cpuid(CPUID_IBSID, regs); + ibs_features = regs[0]; + } + /* parse parameters */ ctl = 0; if (pe == PMC_EV_IBS_FETCH) { while ((p = strsep(&ctrspec, ",")) != NULL) { if (KWMATCH(p, "l3miss")) { + if ((ibs_features & CPUID_IBSID_ZEN4IBSEXTENSIONS) == 0) + return (-1); + ctl |= IBS_FETCH_CTL_L3MISSONLY; } else if (KWMATCH(p, "randomize")) { ctl |= IBS_FETCH_CTL_RANDOMIZE; @@ -742,6 +759,9 @@ ibs_allocate_pmc(enum pmc_event pe, char *ctrspec, if (KWMATCH(p, "l3miss")) { ctl |= IBS_OP_CTL_L3MISSONLY; } else if (KWPREFIXMATCH(p, "ldlat=")) { + if ((ibs_features & CPUID_IBSID_IBSLOADLATENCYFILT) == 0) + return (-1); + q = strchr(p, '='); if (*++q == '\0') /* skip '=' */ return (-1); @@ -765,7 +785,10 @@ ibs_allocate_pmc(enum pmc_event pe, char *ctrspec, return (-1); ctl |= IBS_OP_CTL_LDLAT_TO_CTL(ldlat); ctl |= IBS_OP_CTL_L3MISSONLY | IBS_OP_CTL_LATFLTEN; - } else if (KWMATCH(p, "randomize")) { + } else if (KWMATCH(p, "opcount")) { + if ((ibs_features & CPUID_IBSID_OPCNT) == 0) + return (-1); + ctl |= IBS_OP_CTL_COUNTERCONTROL; } else { return (-1); @@ -776,6 +799,10 @@ ibs_allocate_pmc(enum pmc_event pe, char *ctrspec, pmc_config->pm_count > IBS_OP_MAX_RATE) return (-1); + if (((ibs_features & CPUID_IBSID_OPCNTEXT) == 0) && + (pmc_config->pm_count > IBS_OP_MAX_RATE_PREEXT)) + return (-1); + ctl |= IBS_OP_INTERVAL_TO_CTL(pmc_config->pm_count); } diff --git a/lib/libpmc/pmc.ibs.3 b/lib/libpmc/pmc.ibs.3 index f0534a0955d2..574db4df6fa1 100644 --- a/lib/libpmc/pmc.ibs.3 +++ b/lib/libpmc/pmc.ibs.3 @@ -107,6 +107,8 @@ IBS only supports filtering latencies that are a multiple of 128 and between 128 and 2048. Load latency filtering can only be used with ibs-op events and imply the l3miss qualifier. +.It Li opcount +Count ops rather than cycles. .It Li randomize Randomize the sampling rate. .El @@ -124,13 +126,13 @@ qualifier randomly sets the bottom four bits of the sample rate. .It Li ibs-op Xo .Op ,l3miss .Op ,ldlat= Ns Ar ldlat -.Op ,randomize +.Op ,opcount .Xc Collect performance samples during instruction execution. The -.Ar randomize -qualifier, upon reaching the maximum count, restarts the count with a value -between 1 and 127. +.Ar opcount +qualifier, upon reaching the maximum count, restarts the count with a random +value between 1 and 127. .El .Pp You may collect both events at the same time. diff --git a/sys/dev/hwpmc/hwpmc_ibs.c b/sys/dev/hwpmc/hwpmc_ibs.c index 574df12093f8..56903699ac51 100644 --- a/sys/dev/hwpmc/hwpmc_ibs.c +++ b/sys/dev/hwpmc/hwpmc_ibs.c @@ -351,9 +351,9 @@ pmc_ibs_process_fetch(struct pmc *pm, struct trapframe *tf, uint64_t config) memset(&mpd, 0, sizeof(mpd)); mpd.pl_type = PMC_CC_MULTIPART_IBS_FETCH; - mpd.pl_length = 4; + mpd.pl_length = PMC_MPIDX_FETCH_MAX; mpd.pl_mpdata[PMC_MPIDX_FETCH_CTL] = config; - if (ibs_features) { + if ((ibs_features & CPUID_IBSID_IBSFETCHCTLEXTD) != 0) { mpd.pl_mpdata[PMC_MPIDX_FETCH_EXTCTL] = rdmsr(IBS_FETCH_EXTCTL); } mpd.pl_mpdata[PMC_MPIDX_FETCH_CTL] = config; @@ -382,7 +382,7 @@ pmc_ibs_process_op(struct pmc *pm, struct trapframe *tf, uint64_t config) memset(&mpd, 0, sizeof(mpd)); mpd.pl_type = PMC_CC_MULTIPART_IBS_OP; - mpd.pl_length = 8; + mpd.pl_length = PMC_MPIDX_OP_MAX; mpd.pl_mpdata[PMC_MPIDX_OP_CTL] = config; mpd.pl_mpdata[PMC_MPIDX_OP_RIP] = rdmsr(IBS_OP_RIP); mpd.pl_mpdata[PMC_MPIDX_OP_DATA] = rdmsr(IBS_OP_DATA); @@ -390,6 +390,12 @@ pmc_ibs_process_op(struct pmc *pm, struct trapframe *tf, uint64_t config) mpd.pl_mpdata[PMC_MPIDX_OP_DATA3] = rdmsr(IBS_OP_DATA3); mpd.pl_mpdata[PMC_MPIDX_OP_DC_LINADDR] = rdmsr(IBS_OP_DC_LINADDR); mpd.pl_mpdata[PMC_MPIDX_OP_DC_PHYSADDR] = rdmsr(IBS_OP_DC_PHYSADDR); + if ((ibs_features & CPUID_IBSID_BRNTRGT) != 0) { + mpd.pl_mpdata[PMC_MPIDX_OP_TGT_RIP] = rdmsr(IBS_OP_TGT_RIP); + } + if ((ibs_features & CPUID_IBSID_IBSOPDATA4) != 0) { + mpd.pl_mpdata[PMC_MPIDX_OP_DATA4] = rdmsr(IBS_OP_DATA4); + } pmc_process_interrupt_mp(PMC_HR, pm, tf, &mpd); diff --git a/sys/dev/hwpmc/hwpmc_ibs.h b/sys/dev/hwpmc/hwpmc_ibs.h index 4cb69503bd8b..2b4e111ba171 100644 --- a/sys/dev/hwpmc/hwpmc_ibs.h +++ b/sys/dev/hwpmc/hwpmc_ibs.h @@ -45,11 +45,11 @@ #define CPUID_IBSID_BRNTRGT 0x00000020 /* Branch Target Address */ #define CPUID_IBSID_OPCNTEXT 0x00000040 /* Extend Counter */ #define CPUID_IBSID_RIPINVALIDCHK 0x00000080 /* Invalid RIP Indication */ -#define CPUID_IBSID_OPFUSE 0x00000010 /* Fused Branch Operation */ -#define CPUID_IBSID_IBSFETCHCTLEXTD 0x00000020 /* IBS Fetch Control Ext */ -#define CPUID_IBSID_IBSOPDATA4 0x00000040 /* IBS OP DATA4 */ -#define CPUID_IBSID_ZEN4IBSEXTENSIONS 0x00000080 /* IBS Zen 4 Extensions */ -#define CPUID_IBSID_IBSLOADLATENCYFILT 0x00000100 /* Load Latency Filtering */ +#define CPUID_IBSID_OPFUSE 0x00000100 /* Fused Branch Operation */ +#define CPUID_IBSID_IBSFETCHCTLEXTD 0x00000200 /* IBS Fetch Control Ext */ +#define CPUID_IBSID_IBSOPDATA4 0x00000400 /* IBS OP DATA4 */ +#define CPUID_IBSID_ZEN4IBSEXTENSIONS 0x00000800 /* IBS Zen 4 Extensions */ +#define CPUID_IBSID_IBSLOADLATENCYFILT 0x00001000 /* Load Latency Filtering */ #define CPUID_IBSID_IBSUPDTDDTLBSTATS 0x00080000 /* Simplified DTLB Stats */ /* @@ -77,6 +77,7 @@ #define IBS_FETCH_MAX_RATE 1048560 #define IBS_OP_MIN_RATE 65536 #define IBS_OP_MAX_RATE 134217712 +#define IBS_OP_MAX_RATE_PREEXT 1048560 /* IBS Fetch Control */ #define IBS_FETCH_CTL 0xC0011030 /* IBS Fetch Control */ @@ -108,6 +109,7 @@ #define PMC_MPIDX_FETCH_EXTCTL 1 #define PMC_MPIDX_FETCH_LINADDR 2 #define PMC_MPIDX_FETCH_PHYSADDR 3 +#define PMC_MPIDX_FETCH_MAX (PMC_MPIDX_FETCH_PHYSADDR + 1) /* IBS Execution Control */ #define IBS_OP_CTL 0xC0011033 /* IBS Execution Control */ @@ -151,7 +153,7 @@ #define IBS_OP_DC_LINADDR 0xC0011038 /* IBS DC Linear Address */ #define IBS_OP_DC_PHYSADDR 0xC0011039 /* IBS DC Physical Address */ -#define IBS_TGT_RIP 0xC001103B /* IBS Branch Target */ +#define IBS_OP_TGT_RIP 0xC001103B /* IBS Branch Target */ #define IBS_OP_DATA4 0xC001103D /* IBS Op Data 4 */ #define IBS_OP_DATA4_LDRESYNC (1ULL << 0) /* Load Resync */ @@ -164,6 +166,7 @@ #define PMC_MPIDX_OP_DC_PHYSADDR 6 #define PMC_MPIDX_OP_TGT_RIP 7 #define PMC_MPIDX_OP_DATA4 8 +#define PMC_MPIDX_OP_MAX (PMC_MPIDX_OP_DATA4 + 1) /* * IBS data is encoded as using the multipart flag in the existing callchainhome | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69eb8d68.36b92.4722e81>
