struct perf_ibs {
struct pmu pmu;
unsigned int msr;
+ unsigned int msr2;
u64 config_mask;
u64 cnt_mask;
u64 enable_mask;
+ u64 disable_mask;
u64 valid_mask;
u16 min_period;
u64 max_period;
return -ENOENT;
config = event->attr.config;
+ hwc->extra_reg.config = 0;
+ hwc->extra_reg.reg = 0;
if (event->pmu != &perf_ibs->pmu)
return -ENOENT;
if (perf_allow_kernel())
hwc->flags |= PERF_X86_EVENT_UNPRIVILEGED;
+ if (ibs_caps & IBS_CAPS_DIS) {
+ hwc->extra_reg.config &= ~perf_ibs->disable_mask;
+ hwc->extra_reg.reg = perf_ibs->msr2;
+ }
+
if (hwc->sample_period) {
if (config & perf_ibs->cnt_mask)
/* raw max_cnt may not be set */
wrmsrq(hwc->config_base, tmp & ~perf_ibs->enable_mask);
wrmsrq(hwc->config_base, tmp | perf_ibs->enable_mask);
+
+ if (hwc->extra_reg.reg)
+ wrmsrq(hwc->extra_reg.reg, hwc->extra_reg.config);
}
/*
static inline void perf_ibs_disable_event(struct perf_ibs *perf_ibs,
struct hw_perf_event *hwc, u64 config)
{
+ if (ibs_caps & IBS_CAPS_DIS) {
+ wrmsrq(hwc->extra_reg.reg, perf_ibs->disable_mask);
+ return;
+ }
+
config &= ~perf_ibs->cnt_mask;
if (boot_cpu_data.x86 == 0x10)
wrmsrq(hwc->config_base, config);
.check_period = perf_ibs_check_period,
},
.msr = MSR_AMD64_IBSFETCHCTL,
+ .msr2 = MSR_AMD64_IBSFETCHCTL2,
.config_mask = IBS_FETCH_MAX_CNT | IBS_FETCH_RAND_EN,
.cnt_mask = IBS_FETCH_MAX_CNT,
.enable_mask = IBS_FETCH_ENABLE,
.check_period = perf_ibs_check_period,
},
.msr = MSR_AMD64_IBSOPCTL,
+ .msr2 = MSR_AMD64_IBSOPCTL2,
.config_mask = IBS_OP_MAX_CNT,
.cnt_mask = IBS_OP_MAX_CNT | IBS_OP_CUR_CNT |
IBS_OP_CUR_CNT_RAND,
out:
if (!throttle) {
+ if (ibs_caps & IBS_CAPS_DIS)
+ wrmsrq(hwc->extra_reg.reg, perf_ibs->disable_mask);
+
if (perf_ibs == &perf_ibs_op) {
if (ibs_caps & IBS_CAPS_OPCNTEXT) {
new_config = period & IBS_OP_MAX_CNT_EXT_MASK;
if (ibs_caps & IBS_CAPS_ZEN4)
perf_ibs_fetch.config_mask |= IBS_FETCH_L3MISSONLY;
+ if (ibs_caps & IBS_CAPS_DIS)
+ perf_ibs_fetch.disable_mask = IBS_FETCH_2_DIS;
+
perf_ibs_fetch.pmu.attr_groups = fetch_attr_groups;
perf_ibs_fetch.pmu.attr_update = fetch_attr_update;
if (ibs_caps & IBS_CAPS_ZEN4)
perf_ibs_op.config_mask |= IBS_OP_L3MISSONLY;
+ if (ibs_caps & IBS_CAPS_DIS)
+ perf_ibs_op.disable_mask = IBS_OP_2_DIS;
+
perf_ibs_op.pmu.attr_groups = op_attr_groups;
perf_ibs_op.pmu.attr_update = op_attr_update;
static int x86_pmu_amd_ibs_starting_cpu(unsigned int cpu)
{
setup_APIC_ibs();
+
+ if (ibs_caps & IBS_CAPS_DIS) {
+ /*
+ * IBS enable sequence:
+ * CTL[En] = 1;
+ * CTL2[Dis] = 0;
+ *
+ * IBS disable sequence:
+ * CTL2[Dis] = 1;
+ *
+ * Set CTL2[Dis] when CPU comes up. This is needed to make
+ * enable sequence effective.
+ */
+ wrmsrq(MSR_AMD64_IBSFETCHCTL2, IBS_FETCH_2_DIS);
+ wrmsrq(MSR_AMD64_IBSOPCTL2, IBS_OP_2_DIS);
+ }
+
return 0;
}