/* attr.config1 */
#define IBS_OP_CONFIG1_LDLAT_MASK (0xFFFULL << 0)
+#define IBS_FETCH_CONFIG1_FETCHLAT_MASK (0x7FFULL << 0)
+
/*
* IBS states:
*
(event->attr.config1 & IBS_OP_CONFIG1_LDLAT_MASK);
}
+static bool perf_ibs_fetch_lat_event(struct perf_ibs *perf_ibs,
+ struct perf_event *event)
+{
+ return perf_ibs == &perf_ibs_fetch &&
+ (ibs_caps & IBS_CAPS_FETCHLAT) &&
+ (event->attr.config1 & IBS_FETCH_CONFIG1_FETCHLAT_MASK);
+}
+
static int perf_ibs_init(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
config |= IBS_OP_L3MISSONLY;
}
+ if (perf_ibs_fetch_lat_event(perf_ibs, event)) {
+ u64 fetchlat = event->attr.config1 & IBS_FETCH_CONFIG1_FETCHLAT_MASK;
+
+ if (fetchlat < 128 || fetchlat > 1920)
+ return -EINVAL;
+ fetchlat >>= 7;
+
+ hwc->extra_reg.reg = perf_ibs->msr2;
+ hwc->extra_reg.config |= fetchlat << IBS_FETCH_2_FETCHLAT_FILTER_SHIFT;
+ }
+
/*
* If we modify hwc->sample_period, we also need to update
* hwc->last_period and hwc->period_left.
PMU_EVENT_ATTR_STRING(zen4_ibs_extensions, zen4_ibs_extensions, "1");
PMU_EVENT_ATTR_STRING(ldlat, ibs_op_ldlat_cap, "1");
PMU_EVENT_ATTR_STRING(dtlb_pgsize, ibs_op_dtlb_pgsize_cap, "1");
+PMU_EVENT_ATTR_STRING(fetchlat, ibs_fetch_lat_format, "config1:0-10");
+PMU_EVENT_ATTR_STRING(fetchlat, ibs_fetch_lat_cap, "1");
static umode_t
zen4_ibs_extensions_is_visible(struct kobject *kobj, struct attribute *attr, int i)
return ibs_caps & IBS_CAPS_ZEN4 ? attr->mode : 0;
}
+static umode_t
+ibs_fetch_lat_is_visible(struct kobject *kobj, struct attribute *attr, int i)
+{
+ return ibs_caps & IBS_CAPS_FETCHLAT ? attr->mode : 0;
+}
+
static umode_t
ibs_op_ldlat_is_visible(struct kobject *kobj, struct attribute *attr, int i)
{
NULL,
};
+static struct attribute *ibs_fetch_lat_format_attrs[] = {
+ &ibs_fetch_lat_format.attr.attr,
+ NULL,
+};
+
+static struct attribute *ibs_fetch_lat_cap_attrs[] = {
+ &ibs_fetch_lat_cap.attr.attr,
+ NULL,
+};
+
static struct attribute *ibs_op_ldlat_cap_attrs[] = {
&ibs_op_ldlat_cap.attr.attr,
NULL,
.is_visible = zen4_ibs_extensions_is_visible,
};
+static struct attribute_group group_ibs_fetch_lat_cap = {
+ .name = "caps",
+ .attrs = ibs_fetch_lat_cap_attrs,
+ .is_visible = ibs_fetch_lat_is_visible,
+};
+
+static struct attribute_group group_ibs_fetch_lat_format = {
+ .name = "format",
+ .attrs = ibs_fetch_lat_format_attrs,
+ .is_visible = ibs_fetch_lat_is_visible,
+};
+
static struct attribute_group group_ibs_op_ldlat_cap = {
.name = "caps",
.attrs = ibs_op_ldlat_cap_attrs,
static const struct attribute_group *fetch_attr_update[] = {
&group_fetch_l3missonly,
&group_zen4_ibs_extensions,
+ &group_ibs_fetch_lat_cap,
+ &group_ibs_fetch_lat_format,
NULL,
};
{
if (event->attr.sample_type & PERF_SAMPLE_RAW ||
perf_ibs_is_mem_sample_type(perf_ibs, event) ||
- perf_ibs_ldlat_event(perf_ibs, event))
+ perf_ibs_ldlat_event(perf_ibs, event) ||
+ perf_ibs_fetch_lat_event(perf_ibs, event))
return perf_ibs->offset_max;
else if (check_rip)
return 3;
}
}
+ if (perf_ibs_fetch_lat_event(perf_ibs, event)) {
+ union ibs_fetch_ctl fetch_ctl;
+
+ fetch_ctl.val = ibs_data.regs[ibs_fetch_msr_idx(MSR_AMD64_IBSFETCHCTL)];
+ if (fetch_ctl.fetch_lat < (event->attr.config1 & IBS_FETCH_CONFIG1_FETCHLAT_MASK)) {
+ throttle = perf_event_account_interrupt(event);
+ goto out;
+ }
+ }
+
/*
* Read IbsBrTarget, IbsOpData4, and IbsExtdCtl separately
* depending on their availability.