diff options
| -rw-r--r-- | lib/libpmc/pmc.perf.3 | 79 | ||||
| -rw-r--r-- | sys/amd64/amd64/initcpu.c | 31 | ||||
| -rw-r--r-- | sys/amd64/include/pmc_mdep.h | 2 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_amd.c | 15 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_perf.c | 124 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_perf.h | 14 | ||||
| -rw-r--r-- | sys/dev/hwpmc/pmc_events.h | 7 | ||||
| -rw-r--r-- | sys/x86/include/specialreg.h | 23 |
8 files changed, 215 insertions, 80 deletions
diff --git a/lib/libpmc/pmc.perf.3 b/lib/libpmc/pmc.perf.3 index 2404abd53555..4595829eb362 100644 --- a/lib/libpmc/pmc.perf.3 +++ b/lib/libpmc/pmc.perf.3 @@ -3,12 +3,12 @@ .\" .\" SPDX-License-Identifier: BSD-2-Clause .\" -.Dd August 5, 2026 +.Dd October 13, 2026 .Dt PMC.PERF 3 .Os .Sh NAME .Nm pmc.perf -.Nd measurements using the MPERF/APERF effective frequency counters +.Nd measurements using the MPERF/APERF/IRPERF frequency counters .Sh LIBRARY .Lb libpmc .Sh SYNOPSIS @@ -38,12 +38,24 @@ to scaled by the processor's nominal frequency, yields the average effective frequency. .Pp +AMD processors additionally provide a third fixed-counter machine +specific register, +.Va IRPERF +.Pq Dq Instructions Retired Performance Count , +which increments by one for each instruction retired by the core. +Unlike +.Va MPERF +and +.Va APERF , +.Va IRPERF +is an AMD-only facility and is not available on Intel processors. +.Pp The .Dv PMC_CLASS_PERF -class exposes these two MSRs as read-only 64-bit counters that may +class exposes these MSRs as read-only 64-bit counters that may only be allocated in system-wide counting mode .Pq Dv PMC_MODE_SC. -Both counters expose the unmodified contents of the underlying MSRs. +All counters expose the unmodified contents of the underlying MSRs. .Pp It reflects the free-running count of the underlying MSR since the processor was last reset, and continues to accumulate across @@ -70,19 +82,29 @@ By default AMD/Intel PERF enables the read flag. PERF events do not support further event qualifiers. .Ss Event Specifiers The following event names are supported: -.Bl -tag -width "perf-mperf / mperf" +.Bl -tag -width "perf-irperf / irperf" .It Cm perf-mperf , Cm mperf The Max Performance Frequency Clock Count MSR of the core the counter is bound to. .It Cm perf-aperf , Cm aperf The Actual Performance Frequency Clock Count MSR of the core the counter is bound to. +.It Cm perf-irperf , Cm irperf +The Instructions Retired Performance Count +MSR of the core the counter is bound to. +This event is only available on AMD processors; it is not +supported on Intel processors. +See +.Sx Availability +below for the full set of conditions that must hold for this +event to be present. .El .Ss Counter Scope -.Va MPERF +.Va MPERF , +.Va APERF , and -.Va APERF -are per-core registers: each core has its own independent pair of +.Va IRPERF +are per-core registers: each core has its own independent set of MSRs, and a PMC of this class always reads the value local to the CPU it is bound to. Readings from different cores must not be combined or averaged @@ -108,10 +130,47 @@ class is not registered and does not appear in the output of .Xr pmccontrol 8 or .Xr pmcstat 8 . +.Pp +The +.Cm perf-irperf +event is further restricted to AMD processors that advertise +support for the IRPERF MSR in CPUID 8000_0008H bit 1 EBX. +On processors that do not advertise this bit, including all +Intel processors, the +.Cm perf-irperf +event specifier is not available even though the rest of the +.Dv PMC_CLASS_PERF +class may be present. +.Pp +Due to erratum #1054 +.Pq Dq Instructions Retired Performance Counter May Be Inaccurate , +IRPERF is additionally left disabled on affected AMD Zen 1 parts +.Pq Family 17h, Models below 30h , +even though those processors advertise CPUID support for the MSR. +It is enabled only for Zen 1 Family 17h Model 30h and later, and for +all subsequent microarchitectures. +.Pp +As with +.Va MPERF +and +.Va APERF , +the kernel also verifies, at boot time, that the IRPERF MSR is +actually incrementing before enabling it; some virtualized +environments advertise CPUID and erratum-safe family/model +information without functional MSR support behind it. +.Pp +If IRPERF is unavailable for any of the reasons above, the rest of +the +.Dv PMC_CLASS_PERF +class +.Pq Va MPERF No and Va APERF +is still registered normally; only the +.Cm perf-irperf +event specifier is absent. .Sh EXAMPLES -Sample both counters on CPU 0 for five seconds: +Sample all three counters on CPU 0 for five seconds: .Bd -literal -offset indent -pmcstat -c 0 -s perf-mperf -s perf-aperf -w 5 +pmcstat -c 0 -s perf-mperf -s perf-aperf -s perf-irperf -w 5 .Ed .Sh SEE ALSO .Xr pmc 3 , diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c index 2d2f5835e3b3..a690e3829e7a 100644 --- a/sys/amd64/amd64/initcpu.c +++ b/sys/amd64/amd64/initcpu.c @@ -275,6 +275,7 @@ cpu_init_small_core(void) void initializecpu(void) { + uint64_t irperf1, irperf2; uint64_t msr; uint64_t cr4; @@ -360,6 +361,36 @@ initializecpu(void) (cpu_stdext_feature2 & CPUID_STDEXT2_RDPID) != 0) wrmsr(MSR_TSC_AUX, cpu_auxmsr()); + /* + * According to erratum #1054 "Instructions Retired Performance + * Counter May Be Inaccurate", the IRPERF feature should be + * enabled only for a subset of Zen 1 (Family 17h Models 30h and above) + * and all later processors. + * + * Separately, verify IRPERF is actually incrementing across two + * back-to-back reads. This only catches a dead/non-functional MSR + * (e.g. a hypervisor or emulator exposing the CPUID feature bit + * without real MSR support behind it) -- it cannot detect the + * erratum's actual failure mode, a counter that increments but + * returns inaccurate values. That case is handled entirely by the + * family/model check above. + * + * This runs on every core (BSP and each AP) via initializecpu(); + * pmc_amd_initialize() later assumes IRPERF's enabled/disabled state + * is consistent across all cores. + */ + if ((amd_extended_feature_extensions & AMDFEID_IRPERF) && + ((CPUID_TO_FAMILY(cpu_id) > 0x17) || + (CPUID_TO_FAMILY(cpu_id) == 0x17 && CPUID_TO_MODEL(cpu_id) >= 0x30))) { + wrmsr(MSR_HWCR, rdmsr(MSR_HWCR) | HWCR_IRPERFEN); + + irperf1 = rdmsr(MSR_IRPERF); + irperf2 = rdmsr(MSR_IRPERF); + + if (irperf2 <= irperf1) + wrmsr(MSR_HWCR, rdmsr(MSR_HWCR) & ~HWCR_IRPERFEN); + } + if (!IS_BSP()) cpu_init_small_core(); TSEXIT(); diff --git a/sys/amd64/include/pmc_mdep.h b/sys/amd64/include/pmc_mdep.h index 8eccff3dfa30..f073d1f7594c 100644 --- a/sys/amd64/include/pmc_mdep.h +++ b/sys/amd64/include/pmc_mdep.h @@ -67,7 +67,7 @@ struct pmc_mdep; * TSC The timestamp counter * K8 AMD Athlon64 and Opteron PMCs in 64 bit mode. * IBS AMD IBS - * PERF AMD/Intel MPERF and APERF + * PERF AMD/Intel MPERF, APERF and IRPERF * IAP Intel Core/Core2/Atom CPUs in 64 bits mode. * IAF Intel fixed-function PMCs in Core2 and later CPUs. * UCP Intel Uncore programmable PMCs. diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c index 5de283946384..2231824df6a8 100644 --- a/sys/dev/hwpmc/hwpmc_amd.c +++ b/sys/dev/hwpmc/hwpmc_amd.c @@ -1643,8 +1643,21 @@ pmc_amd_initialize(void) * cpu_startup() -> startrtclock()), not by hwpmc's TSC PMC class. It is * set only after confirming both MSRs actually increment (some emulators * expose the CPUID bit without real MSR support). + * + * Separately, detect support for the IRPERF MSR (AMD-only). If the + * feature is present, HWCR_IRPERFEN should already be set in MSR_HWCR + * by initializecpu() at boot, which also accounts for erratum #1054 + * (IRPERF is left disabled on affected Zen 1 parts) and verifies IRPERF + * is actually incrementing on a dead/emulated MSR. This code only reads + * back that already-decided state. + * + * Either condition above causes the PERF class to be registered, so at + * least one of MPERF/APERF or IRPERF is expected to be usable when this + * branch is taken. */ - if ((cpu_power_ecx & CPUID_PERF_STAT) && (tsc_perf_stat == 1)) { + if (((cpu_power_ecx & CPUID_PERF_STAT) && (tsc_perf_stat == 1)) || + ((amd_extended_feature_extensions & AMDFEID_IRPERF) && + (rdmsr(MSR_HWCR) & HWCR_IRPERFEN))) { nclasses++; } diff --git a/sys/dev/hwpmc/hwpmc_perf.c b/sys/dev/hwpmc/hwpmc_perf.c index c6f271947829..db7d89b70549 100644 --- a/sys/dev/hwpmc/hwpmc_perf.c +++ b/sys/dev/hwpmc/hwpmc_perf.c @@ -3,10 +3,11 @@ * * SPDX-License-Identifier: BSD-2-Clause * - * AMD/Intel MPERF and APERF MSRs counters exposed as an hwpmc(4) PMC class. + * AMD/Intel MPERF/APERF and AMD-only IRPERF MSR counters exposed as an + * hwpmc(4) PMC class. * * Read-only, system-scope (PMC_MODE_SC), 64-bit counters reporting - * MPERF and APERF MSR values. + * MPERF/APERF and IRPERF MSR values. */ #include <sys/param.h> @@ -18,31 +19,18 @@ #define PERF_CAPS PMC_CAP_READ +static int perf_npmcs = 0; + struct perf_descr { struct pmc_descr pm_descr; /* "base class" */ + enum pmc_event pm_ev; + u_int pm_msr; }; -static const struct perf_descr perf_pmcdesc[PERF_NPMCS] = { - { - .pm_descr = { - .pd_name = "MPERF", - .pd_class = PMC_CLASS_PERF, - .pd_caps = PERF_CAPS, - .pd_width = 64 - }, - }, - { - .pm_descr = { - .pd_name = "APERF", - .pd_class = PMC_CLASS_PERF, - .pd_caps = PERF_CAPS, - .pd_width = 64 - } - } -}; +static struct perf_descr perf_pmcdesc[PERF_NPMCS_TOTAL]; struct perf_cpu { - struct pmc_hw tc_hw[PERF_NPMCS]; + struct pmc_hw tc_hw[PERF_NPMCS_TOTAL]; }; static struct perf_cpu **perf_pcpu; @@ -54,7 +42,7 @@ perf_allocate_pmc(int cpu __diagused, int ri __diagused, { KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[perf,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PERF_NPMCS, + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] illegal row index %d", __LINE__, ri)); if (a->pm_class != PMC_CLASS_PERF) @@ -69,7 +57,6 @@ perf_allocate_pmc(int cpu __diagused, int ri __diagused, * Frequency is an indirect power proxy and could be abused by * attacks like Hertzbleed. */ - if (priv_check(curthread, PRIV_PMC_SYSTEM) != 0) return (EPERM); @@ -78,18 +65,8 @@ perf_allocate_pmc(int cpu __diagused, int ri __diagused, if ((a->pm_caps & ~PERF_CAPS) != 0) return (EPERM); - switch (ri) { - case PERF_MPERF: - if (a->pm_ev != PMC_EV_PERF_MPERF) - return (EINVAL); - break; - case PERF_APERF: - if (a->pm_ev != PMC_EV_PERF_APERF) - return (EINVAL); - break; - default: + if (a->pm_ev != perf_pmcdesc[ri].pm_ev) return (EINVAL); - } return (0); } @@ -103,7 +80,7 @@ perf_config_pmc(int cpu, int ri, struct pmc *pm) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[perf,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PERF_NPMCS, ("[perf,%d] illegal row-index %d", + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] illegal row-index %d", __LINE__, ri)); phw = &perf_pcpu[cpu]->tc_hw[ri]; @@ -125,7 +102,7 @@ perf_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[perf,%d] illegal CPU %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PERF_NPMCS, ("[perf,%d] illegal row-index %d", + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] illegal row-index %d", __LINE__, ri)); phw = &perf_pcpu[cpu]->tc_hw[ri]; @@ -150,7 +127,7 @@ perf_get_config(int cpu, int ri, struct pmc **ppm) { KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[perf,%d] illegal CPU %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PERF_NPMCS, ("[perf,%d] illegal row-index %d", + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] illegal row-index %d", __LINE__, ri)); *ppm = perf_pcpu[cpu]->tc_hw[ri].phw_pmc; @@ -161,7 +138,7 @@ perf_get_config(int cpu, int ri, struct pmc **ppm) static int perf_get_msr(int ri __diagused, uint32_t *msr __unused) { - KASSERT(ri >= 0 && ri < PERF_NPMCS, + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] ri %d out of range", __LINE__, ri)); return (EINVAL); @@ -183,7 +160,7 @@ perf_pcpu_fini(struct pmc_mdep *md, int cpu) ri = md->pmd_classdep[perf_classindex].pcd_ri; pc = pmc_pcpu[cpu]; - for (i = 0; i < PERF_NPMCS; i++) { + for (i = 0; i < perf_npmcs; i++) { pc->pc_hwpmcs[i + ri] = NULL; } @@ -215,7 +192,7 @@ perf_pcpu_init(struct pmc_mdep *md, int cpu) KASSERT(pc, ("[perf,%d] null generic per-cpu", __LINE__)); - for (i = 0; i < PERF_NPMCS; i++) { + for (i = 0; i < perf_npmcs; i++) { perf_pc->tc_hw[i].phw_state = PMC_PHW_FLAG_IS_ENABLED | PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i) | PMC_PHW_FLAG_IS_SHAREABLE; @@ -232,7 +209,7 @@ perf_read_pmc(int cpu __diagused, int ri, struct pmc *pm, pmc_value_t *v) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[perf,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PERF_NPMCS, ("[perf,%d] illegal ri %d", + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] illegal ri %d", __LINE__, ri)); mode = PMC_TO_MODE(pm); @@ -242,16 +219,7 @@ perf_read_pmc(int cpu __diagused, int ri, struct pmc *pm, pmc_value_t *v) PMCDBG1(MDP, REA, 1, "perf-read id=%d", ri); - switch (ri) { - case PERF_MPERF: - *v = rdmsr(MSR_MPERF); - break; - case PERF_APERF: - *v = rdmsr(MSR_APERF); - break; - default: - return (EINVAL); - } + *v = rdmsr(perf_pmcdesc[ri].pm_msr); return (0); } @@ -262,7 +230,7 @@ perf_write_pmc(int cpu __diagused, int ri __diagused, struct pmc *pm __unused, { KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[perf,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PERF_NPMCS, ("[perf,%d] illegal row-index %d", + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] illegal row-index %d", __LINE__, ri)); return (0); @@ -273,7 +241,7 @@ perf_release_pmc(int cpu __diagused, int ri __diagused, struct pmc *pmc __unused { KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[perf,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PERF_NPMCS, + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] illegal row-index %d", __LINE__, ri)); KASSERT(perf_pcpu[cpu]->tc_hw[ri].phw_pmc == NULL, ("[perf,%d] PHW pmc non-NULL", __LINE__)); @@ -286,7 +254,7 @@ perf_start_pmc(int cpu __diagused, int ri __diagused, struct pmc *pm __unused) { KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[perf,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PERF_NPMCS, ("[perf,%d] illegal row-index %d", + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] illegal row-index %d", __LINE__, ri)); return (0); @@ -297,7 +265,7 @@ perf_stop_pmc(int cpu __diagused, int ri __diagused, struct pmc *pm __unused) { KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[perf,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PERF_NPMCS, ("[perf,%d] illegal row-index %d", + KASSERT(ri >= 0 && ri < perf_npmcs, ("[perf,%d] illegal row-index %d", __LINE__, ri)); return (0); @@ -313,6 +281,46 @@ pmc_perf_initialize(struct pmc_mdep *md, int maxcpu, int classindex) __LINE__, md->pmd_nclass)); if ((cpu_power_ecx & CPUID_PERF_STAT) && (tsc_perf_stat == 1)) { + strlcpy(perf_pmcdesc[perf_npmcs].pm_descr.pd_name, "MPERF", + PMC_NAME_MAX); + + perf_pmcdesc[perf_npmcs].pm_descr.pd_class = PMC_CLASS_PERF; + perf_pmcdesc[perf_npmcs].pm_descr.pd_caps = PERF_CAPS; + perf_pmcdesc[perf_npmcs].pm_descr.pd_width = 64; + perf_pmcdesc[perf_npmcs].pm_msr = MSR_MPERF; + perf_pmcdesc[perf_npmcs].pm_ev = PMC_EV_PERF_MPERF; + perf_npmcs++; + + strlcpy(perf_pmcdesc[perf_npmcs].pm_descr.pd_name, "APERF", + PMC_NAME_MAX); + + perf_pmcdesc[perf_npmcs].pm_descr.pd_class = PMC_CLASS_PERF; + perf_pmcdesc[perf_npmcs].pm_descr.pd_caps = PERF_CAPS; + perf_pmcdesc[perf_npmcs].pm_descr.pd_width = 64; + perf_pmcdesc[perf_npmcs].pm_msr = MSR_APERF; + perf_pmcdesc[perf_npmcs].pm_ev = PMC_EV_PERF_APERF; + perf_npmcs++; + } + + /* + * The IRPERF MSR is supported only for AMD CPUs. The feature is + * enabled during the boot on each CPU available if AMDFEID_IRPERF + * is set on amd_extended_feature_extensions. + */ + if ((amd_extended_feature_extensions & AMDFEID_IRPERF) && + (rdmsr(MSR_HWCR) & HWCR_IRPERFEN)) { + strlcpy(perf_pmcdesc[perf_npmcs].pm_descr.pd_name, "IRPERF", + PMC_NAME_MAX); + + perf_pmcdesc[perf_npmcs].pm_descr.pd_class = PMC_CLASS_PERF; + perf_pmcdesc[perf_npmcs].pm_descr.pd_caps = PERF_CAPS; + perf_pmcdesc[perf_npmcs].pm_descr.pd_width = 64; + perf_pmcdesc[perf_npmcs].pm_msr = MSR_IRPERF; + perf_pmcdesc[perf_npmcs].pm_ev = PMC_EV_PERF_IRPERF; + perf_npmcs++; + } + + if (perf_npmcs) { perf_pcpu = malloc(sizeof(struct perf_cpu *) * maxcpu, M_PMC, M_ZERO | M_WAITOK); @@ -320,9 +328,9 @@ pmc_perf_initialize(struct pmc_mdep *md, int maxcpu, int classindex) perf_classindex = classindex; pcd = &md->pmd_classdep[classindex]; - pcd->pcd_caps = PMC_CAP_READ; + pcd->pcd_caps = PERF_CAPS; pcd->pcd_class = PMC_CLASS_PERF; - pcd->pcd_num = PERF_NPMCS; + pcd->pcd_num = perf_npmcs; pcd->pcd_ri = md->pmd_npmc; pcd->pcd_width = 64; @@ -339,7 +347,7 @@ pmc_perf_initialize(struct pmc_mdep *md, int maxcpu, int classindex) pcd->pcd_start_pmc = perf_start_pmc; pcd->pcd_stop_pmc = perf_stop_pmc; - md->pmd_npmc += PERF_NPMCS; + md->pmd_npmc += perf_npmcs; } return (0); diff --git a/sys/dev/hwpmc/hwpmc_perf.h b/sys/dev/hwpmc/hwpmc_perf.h index 855c91d290f9..0fc2dfbe70fc 100644 --- a/sys/dev/hwpmc/hwpmc_perf.h +++ b/sys/dev/hwpmc/hwpmc_perf.h @@ -3,21 +3,21 @@ * * SPDX-License-Identifier: BSD-2-Clause * - * AMD/Intel MPERF and APERF MSRs counters exposed as an hwpmc(4) PMC class. + * AMD/Intel MPERF/APERF MSR counters, and the AMD-only IRPERF counter, + * exposed as an hwpmc(4) PMC class. */ #ifdef _KERNEL /* - * A row per MSR: MPERF and APERF. + * A row per MSR: MPERF, APERF and IRPERF. */ -#define PERF_NPMCS 2 -#define PERF_MPERF 0 -#define PERF_APERF 1 +#define PERF_NPMCS_TOTAL 3 -extern int tsc_perf_stat; -extern u_int cpu_power_ecx; +extern int tsc_perf_stat; +extern u_int cpu_power_ecx; +extern u_int amd_extended_feature_extensions; /* * Prototypes. diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h index 442c1e0a0fe0..e49bf6d99fc6 100644 --- a/sys/dev/hwpmc/pmc_events.h +++ b/sys/dev/hwpmc/pmc_events.h @@ -62,13 +62,14 @@ __PMC_EV_ALIAS("cycles", TSC_TSC) #define PMC_EV_RAPL_FIRST PMC_EV_RAPL_ENERGY_PKG #define PMC_EV_RAPL_LAST PMC_EV_RAPL_ENERGY_DRAM -/* MPERF / APERF MSRs */ +/* MPERF / APERF / IRPERF MSRs */ #define __PMC_EV_PERF() \ __PMC_EV(PERF, MPERF) \ - __PMC_EV(PERF, APERF) + __PMC_EV(PERF, APERF) \ + __PMC_EV(PERF, IRPERF) #define PMC_EV_PERF_FIRST PMC_EV_PERF_MPERF -#define PMC_EV_PERF_LAST PMC_EV_PERF_APERF +#define PMC_EV_PERF_LAST PMC_EV_PERF_IRPERF /* * Software events are dynamically defined. diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h index 32d672522965..d51d826fc6f7 100644 --- a/sys/x86/include/specialreg.h +++ b/sys/x86/include/specialreg.h @@ -111,6 +111,28 @@ #define EFER_AIBRSE 0x000200000 /* Automatic IBRS */ /* + * Bits in AMD64 special registers. HWCR is 64 bits wide + */ +#define HWCR_SMMLOCK 0x00000001 /* SMM code lock (R/W) */ +#define HWCR_TLBCACHEDIS 0x00000008 /* Cacheable memory disable (R/W) */ +#define HWCR_INVDWBINVD 0x00000010 /* INVD to WBINVD conversion (R/W) */ +#define HWCR_ALLOWFERRONNE 0x00000080 /* Allow FERR on NE (R/W) */ +#define HWCR_IGNNEEM 0x00000100 /* IGNNE port emulation enable (R/W) */ +#define HWCR_MONMWAITDIS 0x00000200 /* MONITOR and MWAIT disable (R/W) */ +#define HWCR_MONMWAITUSEREN 0x00000400 /* MONITOR/MWAIT user mode enable (R/W) */ +#define HWCR_SMISPCYCDIS 0x00002000 /* SMI special bus cycle disable */ +#define HWCR_RSMSPCYCDIS 0x00004000 /* RSM special bus cycle disable */ +#define HWCR_WRAP32DIS 0x00020000 /* 32-bit address wrap disable (R/W) */ +#define HWCR_MCSTATUSWREN 0x00040000 /* Machine check status write enable (R/W) */ +#define HWCR_IOCFGGPFAULT 0x00100000 /* IO-space configuration causes a GP fault (R/W) */ +#define HWCR_LOCKTSCTOCURRENTP0 0x00200000 /* Lock the TSC to the current P0 frequency (R/W) */ +#define HWCR_TSCFREQSEL 0x01000000 /* TSC frequency select (R) */ +#define HWCR_CPBDIS 0x02000000 /* Core performance boost disable (R/W) */ +#define HWCR_EFFFREQCNTMWAIT 0x04000000 /* Effective frequency counting during mwait (R/W) */ +#define HWCR_EFFFREQREADONLYLOCK 0x08000000 /* Read-only effective frequency counter lock */ +#define HWCR_IRPERFEN 0x40000000 /* Enable instructions retired counter (R/W) */ + +/* * Intel Extended Features registers */ #define XCR0 0 /* XFEATURE_ENABLED_MASK register */ @@ -1253,6 +1275,7 @@ #define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target rip */ #define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target rip */ #define MSR_SF_MASK 0xc0000084 /* syscall flags mask */ +#define MSR_IRPERF 0xc00000e9 /* instructions retired performance count */ #define MSR_FSBASE 0xc0000100 /* base address of the %fs "segment" */ #define MSR_GSBASE 0xc0000101 /* base address of the %gs "segment" */ #define MSR_KGSBASE 0xc0000102 /* base address of the kernel %gs */ |
