aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorAndre Silva <andasilv@amd.com>2026-06-12 15:38:14 +0000
committerMitchell Horne <mhorne@FreeBSD.org>2026-07-21 17:14:39 +0000
commit8c4d5701924f8401798265d2175f0b2bc704a222 (patch)
treea1dd9c220b311816c196d429b803cb7c68e235a1 /sys/dev
parent2e3892671a6fe2bceff6a9d8b439e7acd27dc28a (diff)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/hwpmc/hwpmc_amd.c24
-rw-r--r--sys/dev/hwpmc/hwpmc_ibs.c45
2 files changed, 45 insertions, 24 deletions
diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c
index b075837cd3e8..185ceff133b0 100644
--- a/sys/dev/hwpmc/hwpmc_amd.c
+++ b/sys/dev/hwpmc/hwpmc_amd.c
@@ -43,6 +43,9 @@
#include <sys/sysctl.h>
#include <sys/systm.h>
+#define EXTERR_CATEGORY EXTERR_CAT_HWPMC_AMD
+#include <sys/exterrvar.h>
+
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
@@ -405,21 +408,24 @@ amd_allocate_pmc(int cpu __unused, int ri, struct pmc *pm,
caps = pm->pm_caps;
- if (((caps & PMC_CAP_PRECISE) != 0) &&
- ((pd->pd_caps & PMC_CAP_PRECISE) == 0))
- return (EINVAL);
-
PMCDBG2(MDP, ALL, 1,"amd-allocate ri=%d caps=0x%x", ri, caps);
/* Validate sub-class. */
if (amd_pmcdesc[ri].pm_subclass != a->pm_md.pm_amd.pm_amd_sub_class)
return (EINVAL);
+ if (((caps & PMC_CAP_PRECISE) != 0) &&
+ ((pd->pd_caps & PMC_CAP_PRECISE) == 0))
+ return (EINVAL);
+
if (strlen(pmc_cpuid) != 0) {
config = a->pm_md.pm_amd.pm_amd_config;
if ((config & ~amd_config_mask(amd_pmcdesc[ri].pm_subclass,
caps)) != 0)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "AMD PMU config has unsupported bits %#jx",
+ (uintmax_t)(config & ~amd_config_mask(
+ amd_pmcdesc[ri].pm_subclass, caps))));
pm->pm_md.pm_amd.pm_amd_evsel = config;
PMCDBG2(MDP, ALL, 2, "amd-allocate ri=%d -> config=0x%jx",
ri, (uintmax_t)config);
@@ -443,11 +449,15 @@ amd_allocate_pmc(int cpu __unused, int ri, struct pmc *pm,
}
}
if (i == amd_event_codes_size)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "AMD legacy event %ju is not supported",
+ (uintmax_t)pe));
unitmask = a->pm_md.pm_amd.pm_amd_config & AMD_PMC_UNITMASK;
if ((unitmask & ~allowed_unitmask) != 0) /* disallow reserved bits */
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "AMD unitmask %#jx exceeds allowed mask %#jx",
+ (uintmax_t)unitmask, (uintmax_t)allowed_unitmask));
if (unitmask && (caps & PMC_CAP_QUALIFIER) != 0)
config |= unitmask;
diff --git a/sys/dev/hwpmc/hwpmc_ibs.c b/sys/dev/hwpmc/hwpmc_ibs.c
index 16bc5edd5019..ce9e038e5d0b 100644
--- a/sys/dev/hwpmc/hwpmc_ibs.c
+++ b/sys/dev/hwpmc/hwpmc_ibs.c
@@ -147,9 +147,14 @@ ibs_init_policy(void)
static int
ibs_validate_fetch_config(uint64_t config)
{
+ uint64_t allowed_mask;
- if ((config & ~(ibs_fetch_allowed_mask | ibs_fetch_extra_mask)) != 0)
- return (EINVAL);
+ allowed_mask = ibs_fetch_allowed_mask | ibs_fetch_extra_mask;
+ if ((config & ~allowed_mask) != 0) {
+ return (EXTERROR(EINVAL,
+ "IBS fetch ctl config 0x%jx has bits outside allowed mask"
+ " 0x%jx", (uintmax_t)config, (uintmax_t)allowed_mask));
+ }
return (0);
}
@@ -163,22 +168,27 @@ ibs_validate_op_config(uint64_t config)
if ((config & IBS_OP_CTL_LATFLTEN) != 0) {
if ((ibs_features & CPUID_IBSID_IBSLOADLATENCYFILT) == 0)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "IBS op load-latency filter is not supported"));
/*
* Zen 6 decouples L3MISSONLY from load-latency filtering
* (AMD pub 69205); enforce the pairing only on older parts.
*/
if ((ibs_features & CPUID_IBSID_IBSDIS) == 0 &&
(config & IBS_OP_CTL_L3MISSONLY) == 0)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "IBS op load-latency filter requires l3miss"));
allowed_mask |= IBS_OP_CTL_LDLATMASK | IBS_OP_CTL_L3MISSONLY;
}
allowed_mask |= ibs_op_extra_mask;
- if ((config & ~allowed_mask) != 0)
- return (EINVAL);
+ if ((config & ~allowed_mask) != 0) {
+ return (EXTERROR(EINVAL,
+ "IBS op ctl config 0x%jx has bits outside allowed mask"
+ " 0x%jx", (uintmax_t)config, (uintmax_t)allowed_mask));
+ }
return (0);
}
@@ -197,10 +207,11 @@ ibs_validate_fetch_ctl2_config(uint64_t config)
allowed_mask = ibs_fetch_ctl2_allowed_mask | ibs_fetch_ctl2_extra_mask;
- if ((config & ~allowed_mask) != 0)
+ if ((config & ~allowed_mask) != 0) {
return (EXTERROR(EINVAL,
"IBS fetch ctl2 config 0x%jx has bits outside allowed"
- " mask 0x%jx", (uint64_t)config, (uint64_t)allowed_mask));
+ " mask 0x%jx", (uintmax_t)config, (uintmax_t)allowed_mask));
+ }
return (0);
}
@@ -219,10 +230,11 @@ ibs_validate_op_ctl2_config(uint64_t config)
allowed_mask = ibs_op_ctl2_allowed_mask | ibs_op_ctl2_extra_mask;
- if ((config & ~allowed_mask) != 0)
+ if ((config & ~allowed_mask) != 0) {
return (EXTERROR(EINVAL,
"IBS op ctl2 config 0x%jx has bits outside allowed mask"
- " 0x%jx", (uint64_t)config, (uint64_t)allowed_mask));
+ " 0x%jx", (uintmax_t)config, (uintmax_t)allowed_mask));
+ }
return (0);
}
@@ -244,7 +256,8 @@ ibs_validate_pmc_config(int ri, uint64_t config, uint64_t config2)
return (error);
return (ibs_validate_op_ctl2_config(config2));
default:
- return (EXTERROR(EINVAL, "invalid IBS PMC index %d", ri));
+ return (EXTERROR(EINVAL, "Unsupported IBS PMC type %ju",
+ (uintmax_t)ri));
}
}
@@ -364,13 +377,11 @@ ibs_allocate_pmc(int cpu __unused, int ri, struct pmc *pm,
KASSERT(ri >= 0 && ri < IBS_NPMCS,
("[ibs,%d] illegal row index %d", __LINE__, ri));
- /* check class match */
+ /* Row discriminators; the allocation loop probes every row. */
if (a->pm_class != PMC_CLASS_IBS)
- return (EXTERROR(EINVAL, "PMC class is not IBS"));
+ return (EINVAL);
if (a->pm_md.pm_ibs.ibs_type != ri)
- return (EXTERROR(EINVAL,
- "IBS type %ju does not match PMC index %ju",
- (uint64_t)a->pm_md.pm_ibs.ibs_type, (uint64_t)ri));
+ return (EINVAL);
caps = pm->pm_caps;
@@ -390,7 +401,7 @@ ibs_allocate_pmc(int cpu __unused, int ri, struct pmc *pm,
}
if (!PMC_IS_SAMPLING_MODE(a->pm_mode))
- return (EINVAL);
+ return (EXTERROR(EINVAL, "IBS only supports sampling mode"));
config = a->pm_md.pm_ibs.ibs_ctl;
config2 = a->pm_md.pm_ibs.ibs_ctl2;