aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAndre Silva <andasilv@amd.com>2026-06-11 14:15:35 +0000
committerMitchell Horne <mhorne@FreeBSD.org>2026-06-11 15:12:30 +0000
commit0aa4c25f3e836e98da419a37526bd51c9e04427b (patch)
tree62a8654e50690d81d05ae21688998352449cc163 /sys
parentff46acfd521e7b7b3761a395c8fa0a929e49e5d7 (diff)
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/hwpmc/hwpmc_ibs.c214
-rw-r--r--sys/dev/hwpmc/hwpmc_ibs.h45
2 files changed, 234 insertions, 25 deletions
diff --git a/sys/dev/hwpmc/hwpmc_ibs.c b/sys/dev/hwpmc/hwpmc_ibs.c
index ae14f2ccb14c..16bc5edd5019 100644
--- a/sys/dev/hwpmc/hwpmc_ibs.c
+++ b/sys/dev/hwpmc/hwpmc_ibs.c
@@ -60,9 +60,15 @@ struct ibs_descr {
static uint64_t ibs_features;
static uint64_t ibs_fetch_allowed_mask;
static uint64_t ibs_op_allowed_mask;
+static uint64_t ibs_fetch_ctl2_allowed_mask;
+static uint64_t ibs_op_ctl2_allowed_mask;
+static bool ibs_fetch_ctl2_supported;
+static bool ibs_op_ctl2_supported;
static uint64_t ibs_fetch_extra_mask;
+static uint64_t ibs_fetch_ctl2_extra_mask;
static uint64_t ibs_op_extra_mask;
+static uint64_t ibs_op_ctl2_extra_mask;
SYSCTL_DECL(_kern_hwpmc);
@@ -70,10 +76,18 @@ SYSCTL_U64(_kern_hwpmc, OID_AUTO, ibs_fetch_extra_mask, CTLFLAG_RDTUN,
&ibs_fetch_extra_mask, 0,
"Extra allowed bits in the IBS fetch control MSR (override; default 0)");
+SYSCTL_U64(_kern_hwpmc, OID_AUTO, ibs_fetch_ctl2_extra_mask, CTLFLAG_RDTUN,
+ &ibs_fetch_ctl2_extra_mask, 0,
+ "Extra allowed bits in the IBS fetch control 2 MSR (override; default 0)");
+
SYSCTL_U64(_kern_hwpmc, OID_AUTO, ibs_op_extra_mask, CTLFLAG_RDTUN,
&ibs_op_extra_mask, 0,
"Extra allowed bits in the IBS op control MSR (override; default 0)");
+SYSCTL_U64(_kern_hwpmc, OID_AUTO, ibs_op_ctl2_extra_mask, CTLFLAG_RDTUN,
+ &ibs_op_ctl2_extra_mask, 0,
+ "Extra allowed bits in the IBS op control 2 MSR (override; default 0)");
+
/*
* Per-processor information
*/
@@ -92,8 +106,10 @@ ibs_init_policy(void)
{
ibs_fetch_allowed_mask = IBS_FETCH_ALLOWED_MASK_BASE;
+ ibs_fetch_ctl2_allowed_mask = 0;
ibs_op_allowed_mask = IBS_OP_CTL_MAXCNTBASEMASK;
+ ibs_op_ctl2_allowed_mask = 0;
if ((ibs_features & CPUID_IBSID_ZEN4IBSEXTENSIONS) != 0)
ibs_fetch_allowed_mask |= IBS_FETCH_CTL_L3MISSONLY;
@@ -106,6 +122,26 @@ ibs_init_policy(void)
if ((ibs_features & CPUID_IBSID_ZEN4IBSEXTENSIONS) != 0)
ibs_op_allowed_mask |= IBS_OP_CTL_L3MISSONLY;
+
+ if ((ibs_features & CPUID_IBSID_FETCHLATFILTERING) != 0)
+ ibs_fetch_ctl2_allowed_mask |= IBS_FETCH_CTL2_LATFILTERMASK;
+
+ if ((ibs_features & CPUID_IBSID_STRMSTANDRMTSOCKET) != 0)
+ ibs_op_ctl2_allowed_mask |= IBS_OP_CTL2_STRMSTFILTER;
+
+ if ((ibs_features & CPUID_IBSID_IBSDIS) != 0) {
+ ibs_fetch_ctl2_supported = true;
+ ibs_op_ctl2_supported = true;
+ }
+
+ /*
+ * ctl2 MSRs only exist on Zen 6; writing them on older silicon
+ * would #GP.
+ */
+ if (!ibs_fetch_ctl2_supported)
+ ibs_fetch_ctl2_supported = (ibs_fetch_ctl2_allowed_mask != 0);
+ if (!ibs_op_ctl2_supported)
+ ibs_op_ctl2_supported = (ibs_op_ctl2_allowed_mask != 0);
}
static int
@@ -128,7 +164,12 @@ ibs_validate_op_config(uint64_t config)
if ((config & IBS_OP_CTL_LATFLTEN) != 0) {
if ((ibs_features & CPUID_IBSID_IBSLOADLATENCYFILT) == 0)
return (EINVAL);
- if ((config & IBS_OP_CTL_L3MISSONLY) == 0)
+ /*
+ * 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);
allowed_mask |= IBS_OP_CTL_LDLATMASK | IBS_OP_CTL_L3MISSONLY;
@@ -143,16 +184,67 @@ ibs_validate_op_config(uint64_t config)
}
static int
-ibs_validate_pmc_config(int ri, uint64_t config)
+ibs_validate_fetch_ctl2_config(uint64_t config)
+{
+ uint64_t allowed_mask;
+
+ if (config == 0)
+ return (0);
+
+ if (!ibs_fetch_ctl2_supported)
+ return (EXTERROR(EINVAL,
+ "IBS fetch ctl2 features are not supported on this CPU"));
+
+ allowed_mask = ibs_fetch_ctl2_allowed_mask | ibs_fetch_ctl2_extra_mask;
+
+ 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));
+
+ return (0);
+}
+
+static int
+ibs_validate_op_ctl2_config(uint64_t config)
+{
+ uint64_t allowed_mask;
+
+ if (config == 0)
+ return (0);
+
+ if (!ibs_op_ctl2_supported)
+ return (EXTERROR(EINVAL,
+ "IBS op ctl2 features are not supported on this CPU"));
+
+ allowed_mask = ibs_op_ctl2_allowed_mask | ibs_op_ctl2_extra_mask;
+
+ 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));
+
+ return (0);
+}
+
+static int
+ibs_validate_pmc_config(int ri, uint64_t config, uint64_t config2)
{
+ int error;
switch (ri) {
case IBS_PMC_FETCH:
- return (ibs_validate_fetch_config(config));
+ error = ibs_validate_fetch_config(config);
+ if (error != 0)
+ return (error);
+ return (ibs_validate_fetch_ctl2_config(config2));
case IBS_PMC_OP:
- return (ibs_validate_op_config(config));
+ error = ibs_validate_op_config(config);
+ if (error != 0)
+ return (error);
+ return (ibs_validate_op_ctl2_config(config2));
default:
- return (EINVAL);
+ return (EXTERROR(EINVAL, "invalid IBS PMC index %d", ri));
}
}
@@ -266,7 +358,7 @@ static int
ibs_allocate_pmc(int cpu __unused, int ri, struct pmc *pm,
const struct pmc_op_pmcallocate *a)
{
- uint64_t caps, config;
+ uint64_t caps, config, config2;
int error;
KASSERT(ri >= 0 && ri < IBS_NPMCS,
@@ -284,20 +376,53 @@ ibs_allocate_pmc(int cpu __unused, int ri, struct pmc *pm,
PMCDBG2(MDP, ALL, 1, "ibs-allocate ri=%d caps=0x%x", ri, caps);
- if ((caps & PMC_CAP_SYSTEM) == 0)
- return (EXTERROR(EINVAL, "IBS requires SYSTEM capability"));
+ if ((ibs_features & CPUID_IBSID_ADDRBIT63FILTERING) != 0) {
+ if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
+ return (EXTERROR(EINVAL,
+ "IBS requires at least USER or SYSTEM capability"));
+ } else {
+ if ((caps & PMC_CAP_SYSTEM) == 0)
+ return (EXTERROR(EINVAL,
+ "IBS requires SYSTEM capability"));
+ if ((caps & PMC_CAP_USER) != 0)
+ return (EXTERROR(EINVAL,
+ "IBS USER filtering requires Zen 6 addr63 support"));
+ }
if (!PMC_IS_SAMPLING_MODE(a->pm_mode))
return (EINVAL);
config = a->pm_md.pm_ibs.ibs_ctl;
- error = ibs_validate_pmc_config(ri, config);
+ config2 = a->pm_md.pm_ibs.ibs_ctl2;
+ error = ibs_validate_pmc_config(ri, config, config2);
if (error != 0)
return (error);
pm->pm_md.pm_ibs.ibs_ctl = config;
+ pm->pm_md.pm_ibs.ibs_ctl2 = config2;
- PMCDBG2(MDP, ALL, 2, "ibs-allocate ri=%d -> config=0x%jx", ri,
- config);
+ if ((ibs_features & CPUID_IBSID_ADDRBIT63FILTERING) != 0) {
+ if ((caps & PMC_CAP_USER) != 0 &&
+ (caps & PMC_CAP_SYSTEM) == 0) {
+ if (ri == IBS_PMC_FETCH)
+ pm->pm_md.pm_ibs.ibs_ctl2 |=
+ IBS_FETCH_CTL2_EXCLADDR63EQ1;
+ else
+ pm->pm_md.pm_ibs.ibs_ctl2 |=
+ IBS_OP_CTL2_EXCLRIP63EQ1;
+ } else if ((caps & PMC_CAP_SYSTEM) != 0 &&
+ (caps & PMC_CAP_USER) == 0) {
+ if (ri == IBS_PMC_FETCH)
+ pm->pm_md.pm_ibs.ibs_ctl2 |=
+ IBS_FETCH_CTL2_EXCLADDR63EQ0;
+ else
+ pm->pm_md.pm_ibs.ibs_ctl2 |=
+ IBS_OP_CTL2_EXCLRIP63EQ0;
+ }
+ }
+
+ PMCDBG3(MDP, ALL, 2,
+ "ibs-allocate ri=%d -> config=0x%jx config2=0x%jx", ri,
+ config, config2);
return (0);
}
@@ -349,16 +474,24 @@ ibs_start_pmc(int cpu __diagused, int ri, struct pmc *pm)
/*
* Turn on the ENABLE bit. Zeroing out the control register eliminates
- * stale valid bits from spurious NMIs and it resets the counter.
+ * stale valid bits from spurious NMIs and it resets the counter. This
+ * is safe here because the counter is not yet enabled; the NMI re-arm
+ * path must not do the same (Family 10h erratum #420).
*/
switch (ri) {
case IBS_PMC_FETCH:
wrmsr(IBS_FETCH_CTL, 0);
+ if (ibs_fetch_ctl2_supported)
+ wrmsr(IBS_FETCH_CTL2,
+ pm->pm_md.pm_ibs.ibs_ctl2 & ~IBS_FETCH_CTL2_DISABLE);
config = pm->pm_md.pm_ibs.ibs_ctl | IBS_FETCH_CTL_ENABLE;
wrmsr(IBS_FETCH_CTL, config);
break;
case IBS_PMC_OP:
wrmsr(IBS_OP_CTL, 0);
+ if (ibs_op_ctl2_supported)
+ wrmsr(IBS_OP_CTL2,
+ pm->pm_md.pm_ibs.ibs_ctl2 & ~IBS_OP_CTL2_DISABLE);
config = pm->pm_md.pm_ibs.ibs_ctl | IBS_OP_CTL_ENABLE;
wrmsr(IBS_OP_CTL, config);
break;
@@ -374,7 +507,8 @@ static int
ibs_stop_pmc(int cpu __diagused, int ri, struct pmc *pm)
{
int i;
- uint64_t config;
+ uint64_t config, config2;
+ bool use_alt_disable;
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[ibs,%d] illegal CPU value %d", __LINE__, cpu));
@@ -394,23 +528,47 @@ ibs_stop_pmc(int cpu __diagused, int ri, struct pmc *pm)
* are stopping and discard spurious NMIs. We then retry clearing the
* control register for 50us. This gives us enough time and ensures
* that the valid bit is not accidently stuck after a spurious NMI.
+ *
+ * On Zen 6 with the alternate disable bit (CPUID IbsDis), assert the
+ * ctl2 DISABLE bit first. This avoids an RMW hazard in ctl1 that the
+ * processor may update concurrently while sampling.
*/
config = pm->pm_md.pm_ibs.ibs_ctl;
+ config2 = pm->pm_md.pm_ibs.ibs_ctl2;
+ use_alt_disable = (ibs_features & CPUID_IBSID_IBSDIS) != 0;
atomic_store_int(&ibs_pcpu[cpu]->pc_status, IBS_CPU_STOPPING);
+ /*
+ * On Zen 6, ctl2 DISABLE is the authoritative stop switch; skip
+ * the legacy ctl1 RMW and clear it directly
+ */
switch (ri) {
case IBS_PMC_FETCH:
- wrmsr(IBS_FETCH_CTL, config & ~IBS_FETCH_CTL_MAXCNTMASK);
- DELAY(1);
- config &= ~IBS_FETCH_CTL_ENABLE;
- wrmsr(IBS_FETCH_CTL, config);
+ if (use_alt_disable) {
+ wrmsr(IBS_FETCH_CTL2,
+ config2 | IBS_FETCH_CTL2_DISABLE);
+ wrmsr(IBS_FETCH_CTL, config & ~IBS_FETCH_CTL_ENABLE);
+ } else {
+ wrmsr(IBS_FETCH_CTL,
+ config & ~IBS_FETCH_CTL_MAXCNTMASK);
+ DELAY(1);
+ config &= ~IBS_FETCH_CTL_ENABLE;
+ wrmsr(IBS_FETCH_CTL, config);
+ }
break;
case IBS_PMC_OP:
- wrmsr(IBS_OP_CTL, config & ~IBS_OP_CTL_MAXCNTMASK);
- DELAY(1);
- config &= ~IBS_OP_CTL_ENABLE;
- wrmsr(IBS_OP_CTL, config);
+ if (use_alt_disable) {
+ wrmsr(IBS_OP_CTL2,
+ config2 | IBS_OP_CTL2_DISABLE);
+ wrmsr(IBS_OP_CTL, config & ~IBS_OP_CTL_ENABLE);
+ } else {
+ wrmsr(IBS_OP_CTL,
+ config & ~IBS_OP_CTL_MAXCNTMASK);
+ DELAY(1);
+ config &= ~IBS_OP_CTL_ENABLE;
+ wrmsr(IBS_OP_CTL, config);
+ }
break;
}
@@ -420,9 +578,13 @@ ibs_stop_pmc(int cpu __diagused, int ri, struct pmc *pm)
switch (ri) {
case IBS_PMC_FETCH:
wrmsr(IBS_FETCH_CTL, 0);
+ if (ibs_fetch_ctl2_supported)
+ wrmsr(IBS_FETCH_CTL2, 0);
break;
case IBS_PMC_OP:
wrmsr(IBS_OP_CTL, 0);
+ if (ibs_op_ctl2_supported)
+ wrmsr(IBS_OP_CTL2, 0);
break;
}
}
@@ -456,6 +618,9 @@ pmc_ibs_process_fetch(struct pmc *pm, struct trapframe *tf, uint64_t config)
mpd.pl_mpdata[PMC_MPIDX_FETCH_PHYSADDR] =
rdmsr(IBS_FETCH_PHYSADDR);
}
+ if (ibs_fetch_ctl2_supported) {
+ mpd.pl_mpdata[PMC_MPIDX_FETCH_CTL2] = rdmsr(IBS_FETCH_CTL2);
+ }
pmc_process_interrupt_mp(PMC_HR, pm, tf, &mpd);
@@ -490,6 +655,9 @@ pmc_ibs_process_op(struct pmc *pm, struct trapframe *tf, uint64_t config)
if ((ibs_features & CPUID_IBSID_IBSOPDATA4) != 0) {
mpd.pl_mpdata[PMC_MPIDX_OP_DATA4] = rdmsr(IBS_OP_DATA4);
}
+ if (ibs_op_ctl2_supported) {
+ mpd.pl_mpdata[PMC_MPIDX_OP_CTL2] = rdmsr(IBS_OP_CTL2);
+ }
pmc_process_interrupt_mp(PMC_HR, pm, tf, &mpd);
@@ -647,6 +815,10 @@ ibs_pcpu_fini(struct pmc_mdep *md, int cpu)
*/
wrmsr(IBS_FETCH_CTL, 0);
wrmsr(IBS_OP_CTL, 0);
+ if (ibs_fetch_ctl2_supported)
+ wrmsr(IBS_FETCH_CTL2, 0);
+ if (ibs_op_ctl2_supported)
+ wrmsr(IBS_OP_CTL2, 0);
/*
* Free up allocated space.
diff --git a/sys/dev/hwpmc/hwpmc_ibs.h b/sys/dev/hwpmc/hwpmc_ibs.h
index 433397954d4f..d1474b7cba32 100644
--- a/sys/dev/hwpmc/hwpmc_ibs.h
+++ b/sys/dev/hwpmc/hwpmc_ibs.h
@@ -35,6 +35,9 @@
/*
* All of the CPUID definitions come from AMD PPR Vol 1 for AMD Family 1Ah
* Model 02h C1 (57238) 2024-09-29 Revision 0.24.
+ * Zen 6 CPUID bits (IBSDIS, FETCHLATFILTERING, ADDRBIT63FILTERING) come from
+ * AMD64 Architecture Programmer's Manual Volume 2: System Programming (24593)
+ * 2025-07-02 Version 3.43.
*/
#define CPUID_IBSID 0x8000001B
#define CPUID_IBSID_IBSFFV 0x00000001 /* IBS Feature Flags Valid */
@@ -50,6 +53,12 @@
#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_IBSDIS 0x00002000 /* Alternate IBS Disable */
+#define CPUID_IBSID_FETCHLATFILTERING 0x00004000 /* Fetch Latency Filter */
+#define CPUID_IBSID_ADDRBIT63FILTERING 0x00008000 /* Addr Bit 63 Filter */
+#define CPUID_IBSID_STRMSTANDRMTSOCKET 0x00010000 /* StrmSt + RmtSocket */
+#define CPUID_IBSID_BUFFERV1 0x00020000 /* IBS Buffering V1 */
+#define CPUID_IBSID_MEMPROFILERV1 0x00040000 /* IBS Memory Profiler V1 */
#define CPUID_IBSID_IBSUPDTDDTLBSTATS 0x00080000 /* Simplified DTLB Stats */
/*
@@ -107,11 +116,27 @@
#define IBS_FETCH_PHYSADDR 0xC0011032 /* Fetch Physical Address */
#define IBS_FETCH_EXTCTL 0xC001103C /* Fetch Control Extended */
+/* IBS Fetch Control 2 (Zen 6) */
+#define IBS_FETCH_CTL2 0xC001103F /* IBS Fetch Control 2 */
+#define IBS_FETCH_CTL2_DISABLE (1ULL << 0) /* IBS Fetch Disable */
+#define IBS_FETCH_CTL2_LATFILTERMASK (0xFULL << 1) /* Fetch Latency Filter */
+#define IBS_FETCH_CTL2_EXCLADDR63EQ1 (1ULL << 5) /* Exclude addr bit63=1 */
+#define IBS_FETCH_CTL2_EXCLADDR63EQ0 (1ULL << 6) /* Exclude addr bit63=0 */
+#define IBS_FETCH_CTL2_ADDR63MASK (IBS_FETCH_CTL2_EXCLADDR63EQ0 | \
+ IBS_FETCH_CTL2_EXCLADDR63EQ1)
+
+#define IBS_FETCH_CTL2_LAT_MIN 128
+#define IBS_FETCH_CTL2_LAT_MAX 1920
+#define IBS_FETCH_CTL2_LAT_STEP 128
+#define IBS_FETCH_CTL2_LAT_TO_CTL(_l) ((((_l) >> 7) & 0xFULL) << 1)
+#define IBS_FETCH_CTL2_CTL_TO_LAT(_c) ((((_c) >> 1) & 0xFULL) << 7)
+
#define PMC_MPIDX_FETCH_CTL 0
#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)
+#define PMC_MPIDX_FETCH_CTL2 4
+#define PMC_MPIDX_FETCH_MAX (PMC_MPIDX_FETCH_CTL2 + 1)
/* IBS Execution Control */
#define IBS_OP_CTL 0xC0011033 /* IBS Execution Control */
@@ -148,6 +173,8 @@
#define IBS_OP_DATA_RETURN (1ULL << 34) /* Return */
#define IBS_OP_DATA2 0xC0011036 /* IBS Op Data 2 */
+#define IBS_OP_DATA2_RMTSOCKET (1ULL << 9) /* Remote Socket */
+#define IBS_OP_DATA2_STRMST (1ULL << 8) /* Streaming Store */
#define IBS_OP_DATA3 0xC0011037 /* IBS Op Data 3 */
#define IBS_OP_DATA3_DCPHYADDRVALID (1ULL << 18) /* DC Physical Address */
#define IBS_OP_DATA3_DCLINADDRVALID (1ULL << 17) /* DC Linear Address */
@@ -169,6 +196,15 @@
#define IBS_OP_DATA4 0xC001103D /* IBS Op Data 4 */
#define IBS_OP_DATA4_LDRESYNC (1ULL << 0) /* Load Resync */
+/* IBS Execution Control 2 (Zen 6) */
+#define IBS_OP_CTL2 0xC001103E /* IBS Execution Control 2 */
+#define IBS_OP_CTL2_DISABLE (1ULL << 0) /* IBS Execution Disable */
+#define IBS_OP_CTL2_EXCLRIP63EQ0 (1ULL << 1) /* Exclude RIP bit63=0 */
+#define IBS_OP_CTL2_EXCLRIP63EQ1 (1ULL << 2) /* Exclude RIP bit63=1 */
+#define IBS_OP_CTL2_STRMSTFILTER (1ULL << 3) /* Streaming Store Filter */
+#define IBS_OP_CTL2_RIP63MASK (IBS_OP_CTL2_EXCLRIP63EQ0 | \
+ IBS_OP_CTL2_EXCLRIP63EQ1)
+
#define PMC_MPIDX_OP_CTL 0
#define PMC_MPIDX_OP_RIP 1
#define PMC_MPIDX_OP_DATA 2
@@ -178,7 +214,8 @@
#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)
+#define PMC_MPIDX_OP_CTL2 9
+#define PMC_MPIDX_OP_MAX (PMC_MPIDX_OP_CTL2 + 1)
/*
* IBS data is encoded as using the multipart flag in the existing callchain
@@ -204,8 +241,8 @@ struct pmc_md_ibs_pmc {
uint64_t ibs_ctl2;
};
-#define IBS_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_SYSTEM | \
- PMC_CAP_EDGE | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE)
+#define IBS_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \
+ PMC_CAP_SYSTEM | PMC_CAP_EDGE | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE)
int pmc_ibs_initialize(struct pmc_mdep *md, int ncpu);
void pmc_ibs_finalize(struct pmc_mdep *md);