Skip to content

Commit d29e744

Browse files
namhyungIngo Molnar
authored andcommitted
perf/x86: Relax privilege filter restriction on AMD IBS
While IBS is available for per-thread profiling, still regular users cannot open an event due to the default paranoid setting (2) which doesn't allow unprivileged users to get kernel samples. That means it needs to set exclude_kernel bit in the attribute but IBS driver would reject it since it has PERF_PMU_CAP_NO_EXCLUDE. This is not what we want and I've been getting requests to fix this issue. This should be done in the hardware, but until we get the HW fix we may allow exclude_{kernel,user,hv} in the attribute and silently drop the samples in the PMU IRQ handler. It won't guarantee the sampling frequency or even it'd miss some with fixed period too. Not ideal, but that'd still be helpful to regular users. To minimize the confusion, let's add 'swfilt' bit to attr.config2 which is exposed in the sysfs format directory so that users can figure out if the kernel support the privilege filters by software. $ perf record -e ibs_op/swfilt=1/u true This uses perf_exclude_event() which checks regs->cs. But it should be fine because set_linear_ip() also updates the CS according to the RIP provided by IBS. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Tested-by: Ravi Bangoria <ravi.bangoria@amd.com> Reviewed-by: Ravi Bangoria <ravi.bangoria@amd.com> Link: https://lore.kernel.org/r/20241203180441.1634709-3-namhyung@kernel.org
1 parent 6057b90 commit d29e744

File tree

1 file changed

+41
-18
lines changed

1 file changed

+41
-18
lines changed

arch/x86/events/amd/ibs.c

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static u32 ibs_caps;
3131
#define IBS_FETCH_CONFIG_MASK (IBS_FETCH_RAND_EN | IBS_FETCH_MAX_CNT)
3232
#define IBS_OP_CONFIG_MASK IBS_OP_MAX_CNT
3333

34+
/* attr.config2 */
35+
#define IBS_SW_FILTER_MASK 1
3436

3537
/*
3638
* IBS states:
@@ -290,6 +292,16 @@ static int perf_ibs_init(struct perf_event *event)
290292
if (has_branch_stack(event))
291293
return -EOPNOTSUPP;
292294

295+
/* handle exclude_{user,kernel} in the IRQ handler */
296+
if (event->attr.exclude_host || event->attr.exclude_guest ||
297+
event->attr.exclude_idle)
298+
return -EINVAL;
299+
300+
if (!(event->attr.config2 & IBS_SW_FILTER_MASK) &&
301+
(event->attr.exclude_kernel || event->attr.exclude_user ||
302+
event->attr.exclude_hv))
303+
return -EINVAL;
304+
293305
ret = validate_group(event);
294306
if (ret)
295307
return ret;
@@ -550,24 +562,14 @@ static struct attribute *attrs_empty[] = {
550562
NULL,
551563
};
552564

553-
static struct attribute_group empty_format_group = {
554-
.name = "format",
555-
.attrs = attrs_empty,
556-
};
557-
558565
static struct attribute_group empty_caps_group = {
559566
.name = "caps",
560567
.attrs = attrs_empty,
561568
};
562569

563-
static const struct attribute_group *empty_attr_groups[] = {
564-
&empty_format_group,
565-
&empty_caps_group,
566-
NULL,
567-
};
568-
569570
PMU_FORMAT_ATTR(rand_en, "config:57");
570571
PMU_FORMAT_ATTR(cnt_ctl, "config:19");
572+
PMU_FORMAT_ATTR(swfilt, "config2:0");
571573
PMU_EVENT_ATTR_STRING(l3missonly, fetch_l3missonly, "config:59");
572574
PMU_EVENT_ATTR_STRING(l3missonly, op_l3missonly, "config:16");
573575
PMU_EVENT_ATTR_STRING(zen4_ibs_extensions, zen4_ibs_extensions, "1");
@@ -578,8 +580,9 @@ zen4_ibs_extensions_is_visible(struct kobject *kobj, struct attribute *attr, int
578580
return ibs_caps & IBS_CAPS_ZEN4 ? attr->mode : 0;
579581
}
580582

581-
static struct attribute *rand_en_attrs[] = {
583+
static struct attribute *fetch_attrs[] = {
582584
&format_attr_rand_en.attr,
585+
&format_attr_swfilt.attr,
583586
NULL,
584587
};
585588

@@ -593,9 +596,9 @@ static struct attribute *zen4_ibs_extensions_attrs[] = {
593596
NULL,
594597
};
595598

596-
static struct attribute_group group_rand_en = {
599+
static struct attribute_group group_fetch_formats = {
597600
.name = "format",
598-
.attrs = rand_en_attrs,
601+
.attrs = fetch_attrs,
599602
};
600603

601604
static struct attribute_group group_fetch_l3missonly = {
@@ -611,7 +614,7 @@ static struct attribute_group group_zen4_ibs_extensions = {
611614
};
612615

613616
static const struct attribute_group *fetch_attr_groups[] = {
614-
&group_rand_en,
617+
&group_fetch_formats,
615618
&empty_caps_group,
616619
NULL,
617620
};
@@ -628,6 +631,11 @@ cnt_ctl_is_visible(struct kobject *kobj, struct attribute *attr, int i)
628631
return ibs_caps & IBS_CAPS_OPCNT ? attr->mode : 0;
629632
}
630633

634+
static struct attribute *op_attrs[] = {
635+
&format_attr_swfilt.attr,
636+
NULL,
637+
};
638+
631639
static struct attribute *cnt_ctl_attrs[] = {
632640
&format_attr_cnt_ctl.attr,
633641
NULL,
@@ -638,6 +646,11 @@ static struct attribute *op_l3missonly_attrs[] = {
638646
NULL,
639647
};
640648

649+
static struct attribute_group group_op_formats = {
650+
.name = "format",
651+
.attrs = op_attrs,
652+
};
653+
641654
static struct attribute_group group_cnt_ctl = {
642655
.name = "format",
643656
.attrs = cnt_ctl_attrs,
@@ -650,6 +663,12 @@ static struct attribute_group group_op_l3missonly = {
650663
.is_visible = zen4_ibs_extensions_is_visible,
651664
};
652665

666+
static const struct attribute_group *op_attr_groups[] = {
667+
&group_op_formats,
668+
&empty_caps_group,
669+
NULL,
670+
};
671+
653672
static const struct attribute_group *op_attr_update[] = {
654673
&group_cnt_ctl,
655674
&group_op_l3missonly,
@@ -667,7 +686,6 @@ static struct perf_ibs perf_ibs_fetch = {
667686
.start = perf_ibs_start,
668687
.stop = perf_ibs_stop,
669688
.read = perf_ibs_read,
670-
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
671689
},
672690
.msr = MSR_AMD64_IBSFETCHCTL,
673691
.config_mask = IBS_FETCH_CONFIG_MASK,
@@ -691,7 +709,6 @@ static struct perf_ibs perf_ibs_op = {
691709
.start = perf_ibs_start,
692710
.stop = perf_ibs_stop,
693711
.read = perf_ibs_read,
694-
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
695712
},
696713
.msr = MSR_AMD64_IBSOPCTL,
697714
.config_mask = IBS_OP_CONFIG_MASK,
@@ -1111,6 +1128,12 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
11111128
regs.flags |= PERF_EFLAGS_EXACT;
11121129
}
11131130

1131+
if ((event->attr.config2 & IBS_SW_FILTER_MASK) &&
1132+
perf_exclude_event(event, &regs)) {
1133+
throttle = perf_event_account_interrupt(event);
1134+
goto out;
1135+
}
1136+
11141137
if (event->attr.sample_type & PERF_SAMPLE_RAW) {
11151138
raw = (struct perf_raw_record){
11161139
.frag = {
@@ -1227,7 +1250,7 @@ static __init int perf_ibs_op_init(void)
12271250
if (ibs_caps & IBS_CAPS_ZEN4)
12281251
perf_ibs_op.config_mask |= IBS_OP_L3MISSONLY;
12291252

1230-
perf_ibs_op.pmu.attr_groups = empty_attr_groups;
1253+
perf_ibs_op.pmu.attr_groups = op_attr_groups;
12311254
perf_ibs_op.pmu.attr_update = op_attr_update;
12321255

12331256
return perf_ibs_pmu_init(&perf_ibs_op, "ibs_op");

0 commit comments

Comments
 (0)