mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
hwpmc/amd: replace static pmcdesc[] and pc_amdpmcs[] with dynamic allocation
AMD_NPMCS_MAX = 342 (16 core + 6 L3 + 64 DF + 256 UMC). On a Zen 4 EPYC 9654 with 6 core, 6 L3, 16 DF, and 4 UMC counters, only 32 descriptors are needed; the static arrays over-allocate by ~10x. Replace both amd_pmcdesc[AMD_NPMCS_MAX] and per-CPU pc_amdpmcs[AMD_NPMCS_MAX] with mallocarray() sized to the actual registered PMC count: - amd_pmcdesc: allocated in pmc_amd_initialize() - pc_amdpmcs: allocated per-CPU in amd_pcpu_init(), freed in fini() Normalize amd_l3_npmcs and amd_df_npmcs against the AMDID2_PTSCEL2I and AMDID2_PNXC feature bits before computing npmcs_total, so that allocation, registration, and amd_get_msr() row offsets are all derived from the same values. Previously the ternary in npmcs_total excluded L3/DF from the allocation while the globals retained their defaults, causing amd_get_msr() to miscompute DF row offsets when L3 is absent. amd_umc_npmcs comes from CPUID Fn8000_0022h EBX[23:16] (NumUMCCounters) and is zero when the leaf is absent, so no additional feature flag is needed. See AMD64 APM Vol.3 Appendix E. Fix three error-path memory leaks: amd_hwcheck() failure, goto error, and finalize. Reset amd_npmcs = 0 on the error path. Tested on AMD EPYC 9654 (Zen 4, Family 19h Model 11h, 192 threads). Full PMC test suite (IBS/UMCDF/PMC/L3/DF/TSC): 0 failures. Signed-off-by: Osvaldo Janeri Filho <[email protected]> Reviewed by: mhorne MFC after: 1 week Sponsored by: AMD Pull Request: https://github.com/freebsd/freebsd-src/pull/2415
This commit is contained in:
1 parent
c745fccd9b
commit
8a0cab240f
2 files changed
+43
-3
No files matched your search
@@ -65,7 +65,7 @@ struct amd_descr {
|
||||
|
||||
static int amd_npmcs;
|
||||
static int amd_core_npmcs, amd_l3_npmcs, amd_df_npmcs, amd_umc_npmcs;
|
||||
static struct amd_descr amd_pmcdesc[AMD_NPMCS_MAX];
|
||||
static struct amd_descr *amd_pmcdesc;
|
||||
struct amd_event_code_map {
|
||||
enum pmc_event pe_ev; /* enum value */
|
||||
uint16_t pe_code; /* encoded event mask */
|
||||
@@ -178,7 +178,7 @@ const int amd_event_codes_size = nitems(amd_event_codes);
|
||||
* Per-processor information
|
||||
*/
|
||||
struct amd_cpu {
|
||||
struct pmc_hw pc_amdpmcs[AMD_NPMCS_MAX];
|
||||
struct pmc_hw *pc_amdpmcs;
|
||||
};
|
||||
static struct amd_cpu **amd_pcpu;
|
||||
|
||||
@@ -840,6 +840,8 @@ amd_pcpu_init(struct pmc_mdep *md, int cpu)
|
||||
|
||||
amd_pcpu[cpu] = pac = malloc(sizeof(struct amd_cpu), M_PMC,
|
||||
M_WAITOK | M_ZERO);
|
||||
pac->pc_amdpmcs = mallocarray(amd_npmcs, sizeof(*pac->pc_amdpmcs),
|
||||
M_PMC, M_WAITOK | M_ZERO);
|
||||
|
||||
/*
|
||||
* Set the content of the hardware descriptors to a known
|
||||
@@ -903,6 +905,7 @@ amd_pcpu_fini(struct pmc_mdep *md, int cpu)
|
||||
for (i = 0; i < amd_npmcs; i++)
|
||||
pc->pc_hwpmcs[i + first_ri] = NULL;
|
||||
|
||||
free(pac->pc_amdpmcs, M_PMC);
|
||||
free(pac, M_PMC);
|
||||
return (0);
|
||||
}
|
||||
@@ -988,6 +991,7 @@ pmc_amd_initialize(void)
|
||||
enum pmc_cputype cputype;
|
||||
int ncpus, nclasses, i;
|
||||
int family, model, stepping;
|
||||
int npmcs_total;
|
||||
int error;
|
||||
int pmcs_per_umc;
|
||||
|
||||
@@ -1046,6 +1050,24 @@ pmc_amd_initialize(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Normalize per-class counts against feature bits so that allocation,
|
||||
* registration, and amd_get_msr() row offsets all use the same values.
|
||||
* UMC counters have no CPUID feature flag; amd_umc_npmcs is 0 when
|
||||
* the CPUID leaf is absent.
|
||||
*/
|
||||
if ((amd_feature2 & AMDID2_PTSCEL2I) == 0)
|
||||
amd_l3_npmcs = 0;
|
||||
if ((amd_feature2 & AMDID2_PNXC) == 0)
|
||||
amd_df_npmcs = 0;
|
||||
npmcs_total = amd_core_npmcs + amd_l3_npmcs + amd_df_npmcs +
|
||||
amd_umc_npmcs;
|
||||
KASSERT(npmcs_total <= AMD_NPMCS_MAX,
|
||||
("%s: npmcs_total %d exceeds AMD_NPMCS_MAX %d",
|
||||
__func__, npmcs_total, AMD_NPMCS_MAX));
|
||||
amd_pmcdesc = mallocarray(npmcs_total, sizeof(*amd_pmcdesc),
|
||||
M_PMC, M_WAITOK | M_ZERO);
|
||||
|
||||
/* Enable the newer core counters */
|
||||
for (i = 0; i < amd_core_npmcs; i++) {
|
||||
d = &amd_pmcdesc[i];
|
||||
@@ -1105,6 +1127,9 @@ pmc_amd_initialize(void)
|
||||
amd_npmcs += amd_df_npmcs;
|
||||
}
|
||||
|
||||
KASSERT(amd_npmcs == npmcs_total - amd_umc_npmcs,
|
||||
("%s: UMC cursor wrong: got %d expected %d",
|
||||
__func__, amd_npmcs, npmcs_total - amd_umc_npmcs));
|
||||
for (i = 0; i < amd_umc_npmcs; i++) {
|
||||
d = &amd_pmcdesc[amd_npmcs + i];
|
||||
snprintf(d->pm_descr.pd_name, PMC_NAME_MAX,
|
||||
@@ -1118,11 +1143,17 @@ pmc_amd_initialize(void)
|
||||
}
|
||||
amd_npmcs += amd_umc_npmcs;
|
||||
|
||||
KASSERT(amd_npmcs == npmcs_total,
|
||||
("%s: descriptor cursor %d != npmcs_total %d",
|
||||
__func__, amd_npmcs, npmcs_total));
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
free(amd_pmcdesc, M_PMC);
|
||||
amd_pmcdesc = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -1216,6 +1247,11 @@ pmc_amd_initialize(void)
|
||||
|
||||
error:
|
||||
free(pmc_mdep, M_PMC);
|
||||
free(amd_pcpu, M_PMC);
|
||||
amd_pcpu = NULL;
|
||||
free(amd_pmcdesc, M_PMC);
|
||||
amd_pmcdesc = NULL;
|
||||
amd_npmcs = 0;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -1240,4 +1276,7 @@ pmc_amd_finalize(struct pmc_mdep *md)
|
||||
|
||||
free(amd_pcpu, M_PMC);
|
||||
amd_pcpu = NULL;
|
||||
|
||||
free(amd_pmcdesc, M_PMC);
|
||||
amd_pmcdesc = NULL;
|
||||
}
|
||||
@@ -197,7 +197,8 @@
|
||||
#define AMD_PMC_UMC_TO_RDWRMASK(x) (((x) << 8) & AMD_PMC_UMC_RDWRMASK)
|
||||
|
||||
#define AMD_NPMCS_K8 4
|
||||
#define AMD_NPMCS_MAX (AMD_PMC_CORE_MAX + AMD_PMC_L3_MAX + \
|
||||
/* Compile-time upper bound; npmcs_total must not exceed this. */
|
||||
#define AMD_NPMCS_MAX (AMD_PMC_CORE_MAX + AMD_PMC_L3_MAX + \
|
||||
AMD_PMC_DF_MAX + AMD_PMC_UMC_MAX)
|
||||
|
||||
#define AMD_PMC_IS_STOPPED(evsel) ((rdmsr((evsel)) & AMD_PMC_ENABLE) == 0)
|
||||
|
||||
Reference in new issue
Block a user