Re: [PATCH v2 5/7] perf/amd/ibs: Enable RIP bit63 hardware filtering
From: Ian Rogers
Date: Tue Feb 24 2026 - 12:47:26 EST
On Sun, Feb 15, 2026 at 8:26 PM Ravi Bangoria <ravi.bangoria@xxxxxxx> wrote:
>
> IBS on future hardware adds the ability to filter IBS events by examining
> RIP bit 63. Because Linux kernel addresses always have bit 63 set while
> user-space addresses never do, this capability can be used as a privilege
> filter.
Since x86's top-byte-ignore/linear-address-masking leaves bit 63 could
this break in the future if the kernel later ignores all bits,
including bit 63, and user space wants to use bit 63 of the pointer
for metadata? Does the bit 63 assumption hold for guest operating
systems?
Thanks,
Ian
> So far, IBS supports privilege filtering in software (swfilt=1), where
> samples are dropped in the NMI handler. The RIP bit63 hardware filter
> enables IBS to be usable by unprivileged users without passing swfilt
> flag. So, swfilt flag will silently be ignored when the hardware
> filtering capability is present.
>
> Example (non-root user):
> $ perf record -e ibs_op//u -- <workload>
>
> Signed-off-by: Ravi Bangoria <ravi.bangoria@xxxxxxx>
> ---
> arch/x86/events/amd/ibs.c | 46 ++++++++++++++++++++++++++++++++-------
> 1 file changed, 38 insertions(+), 8 deletions(-)
>
> diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
> index cb3ae4e4744c..13ecc8d92b23 100644
> --- a/arch/x86/events/amd/ibs.c
> +++ b/arch/x86/events/amd/ibs.c
> @@ -321,11 +321,6 @@ static int perf_ibs_init(struct perf_event *event)
> event->attr.exclude_idle)
> return -EINVAL;
>
> - if (!(event->attr.config2 & IBS_SW_FILTER_MASK) &&
> - (event->attr.exclude_kernel || event->attr.exclude_user ||
> - event->attr.exclude_hv))
> - return -EINVAL;
> -
> ret = validate_group(event);
> if (ret)
> return ret;
> @@ -338,6 +333,32 @@ static int perf_ibs_init(struct perf_event *event)
> hwc->extra_reg.reg = perf_ibs->msr2;
> }
>
> + if (ibs_caps & IBS_CAPS_BIT63_FILTER) {
> + if (perf_ibs == &perf_ibs_fetch) {
> + if (event->attr.exclude_kernel) {
> + hwc->extra_reg.config |= IBS_FETCH_2_EXCL_RIP_63_EQ_1;
> + hwc->extra_reg.reg = perf_ibs->msr2;
> + }
> + if (event->attr.exclude_user) {
> + hwc->extra_reg.config |= IBS_FETCH_2_EXCL_RIP_63_EQ_0;
> + hwc->extra_reg.reg = perf_ibs->msr2;
> + }
> + } else {
> + if (event->attr.exclude_kernel) {
> + hwc->extra_reg.config |= IBS_OP_2_EXCL_RIP_63_EQ_1;
> + hwc->extra_reg.reg = perf_ibs->msr2;
> + }
> + if (event->attr.exclude_user) {
> + hwc->extra_reg.config |= IBS_OP_2_EXCL_RIP_63_EQ_0;
> + hwc->extra_reg.reg = perf_ibs->msr2;
> + }
> + }
> + } else if (!(event->attr.config2 & IBS_SW_FILTER_MASK) &&
> + (event->attr.exclude_kernel || event->attr.exclude_user ||
> + event->attr.exclude_hv)) {
> + return -EINVAL;
> + }
> +
> if (hwc->sample_period) {
> if (config & perf_ibs->cnt_mask)
> /* raw max_cnt may not be set */
> @@ -1280,7 +1301,7 @@ static bool perf_ibs_is_kernel_br_target(struct perf_event *event,
> op_data.op_brn_ret && kernel_ip(br_target));
> }
>
> -static bool perf_ibs_swfilt_discard(struct perf_ibs *perf_ibs, struct perf_event *event,
> +static bool perf_ibs_discard_sample(struct perf_ibs *perf_ibs, struct perf_event *event,
> struct pt_regs *regs, struct perf_ibs_data *ibs_data,
> int br_target_idx)
> {
> @@ -1435,8 +1456,9 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
> regs.flags |= PERF_EFLAGS_EXACT;
> }
>
> - if ((event->attr.config2 & IBS_SW_FILTER_MASK) &&
> - perf_ibs_swfilt_discard(perf_ibs, event, ®s, &ibs_data, br_target_idx)) {
> + if (((ibs_caps & IBS_CAPS_BIT63_FILTER) ||
> + (event->attr.config2 & IBS_SW_FILTER_MASK)) &&
> + perf_ibs_discard_sample(perf_ibs, event, ®s, &ibs_data, br_target_idx)) {
> throttle = perf_event_account_interrupt(event);
> goto out;
> }
> @@ -1899,6 +1921,14 @@ static __init int amd_ibs_init(void)
>
> perf_ibs_pm_init();
>
> +#ifdef CONFIG_X86_32
> + /*
> + * IBS_CAPS_BIT63_FILTER is used for exclude_kernel/user filtering,
> + * which obviously won't work for 32 bit kernel.
> + */
> + caps &= ~IBS_CAPS_BIT63_FILTER;
> +#endif
> +
> ibs_caps = caps;
> /* make ibs_caps visible to other cpus: */
> smp_mb();
> --
> 2.43.0
>