All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Matt Turner" <mattst88@gmail.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH 3/5] alpha/perf: implement ProfileMe sampling
Date: Wed, 28 Oct 2026 18:28:48 +0000	[thread overview]
Message-ID: <sashiko-outbox-188288@kernel.org> (raw)
In-Reply-To: <20261028-alpha-profileme-v1-3-d44b52bf2500@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] alpha/perf: wrong register and stack state in alpha_perf_event_profileme()
--

commit 4ba1c82f19c556ae6c582ff386ff198b05c6a1eb
Author: Matt Turner <mattst88@gmail.com>

alpha/perf: implement ProfileMe sampling

This commit implements ProfileMe performance counter sampling on Alpha
EV67 and later processors, selecting it via the profileme config attribute
or precise_ip and attributing samples to the PC latched in PMPC.

> diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
> index 70840c05d39bf..24c96feda9424 100644
> --- a/arch/alpha/kernel/perf_event.c
> +++ b/arch/alpha/kernel/perf_event.c

[ ... ]

> @@ -832,6 +904,61 @@ void perf_event_print_debug(void)
>  }
>  
>  
> +/*
> + * Handle the close of a ProfileMe window on PCTR0.
> + *
> + * PCTR0 stops counting when the window closes and does not start again
> + * until PCTR_CTL is written, so the status must be read first and the
> + * counters then rearmed unconditionally.
> + */
> +static void alpha_perf_event_profileme(struct perf_event *event,
> +				       struct hw_perf_event *hwc,
> +				       struct pt_regs *regs)
> +{
> +	struct perf_sample_data data;
> +	struct pt_regs pm_regs;
> +	unsigned long i_stat, pmpc, ovr;
> +
> +	i_stat = wrperfmon(PERFMON_CMD_I_STAT, 0);
> +	pmpc = wrperfmon(PERFMON_CMD_PMPC, 0);
> +
> +	alpha_perf_event_update(event, hwc, 0, alpha_pmu->pmc_max_period[0]+1);
> +
> +	/*
> +	 * When PCTR0 counts instructions, up to 7 of them are counted after
> +	 * the overflow but before the window opens. I_STAT reports how many.
> +	 */
> +	if (!(hwc->config_base & EV67_PCTR_PCTR0_CYCLES)) {
> +		ovr = (i_stat >> EV67_I_STAT_OVR_SHIFT) & EV67_I_STAT_OVR_MASK;
> +		local64_sub(ovr, &event->count);
> +		local64_add(ovr, &hwc->period_left);
> +	}
> +
> +	/*
> +	 * Attribute the sample to the profiled instruction rather than to
> +	 * wherever the interrupt landed, including the user/kernel mode that
> +	 * perf derives from regs. A PALmode PMPC is a physical address that
> +	 * perf cannot resolve. That happens for ITB miss, Istream access
> +	 * violation and interrupt redirects, and for instructions inside
> +	 * PALcode. Keep the interrupted PC, which for redirects is the
> +	 * instruction that trapped.
> +	 */
> +	pm_regs = *regs;
> +	if (!(pmpc & EV67_PMPC_PAL)) {
> +		pm_regs.pc = pmpc & EV67_PMPC_PC_MASK;
> +		/* PS bit 3 is the mode bit that user_mode() tests. */
> +		if (pm_regs.pc < TASK_SIZE)
> +			pm_regs.ps |= 8UL;
> +		else
> +			pm_regs.ps &= ~8UL;
> +	}
> +
> +	perf_sample_data_init(&data, 0, hwc->last_period);
> +
> +	if (alpha_perf_event_set_period(event, hwc, 0))
> +		perf_event_overflow(event, &data, &pm_regs);
> +}

[Severity: High]
When a user-mode instruction is profiled (pm_regs.pc < TASK_SIZE), but the
PMI is delivered after the CPU has entered kernel mode (!user_mode(regs)),
regs is the kernel interrupt trap frame containing live kernel GPRs, while
the user task's registers live in task_pt_regs(current).

By copying *regs into pm_regs and setting pm_regs.ps |= 8UL before calling
perf_event_overflow(), user_mode(&pm_regs) evaluates to true in
kernel/events/core.c:perf_sample_regs_user():

	if (user_mode(regs)) {
		regs_user->abi = perf_reg_abi(current);
		regs_user->regs = regs;
	} else if (is_user_task(current)) {
		perf_get_regs_user(regs_user, regs);
	}

and in kernel/events/core.c:perf_sample_regs_intr():

	if (exclude_kernel && !user_mode(regs)) {
		regs_intr->abi = PERF_SAMPLE_REGS_ABI_NONE;
		regs_intr->regs = NULL;
	} else {
		regs_intr->regs = regs;
		regs_intr->abi = perf_reg_abi(current);
	}

Doesn't this cause PERF_SAMPLE_REGS_USER and PERF_SAMPLE_REGS_INTR (even
when attr.exclude_kernel is set) to record live kernel registers from the
kernel interrupt trap frame into the user-visible perf ring buffer instead
of fetching task_pt_regs(current), while also corrupting user DWARF
callgraph unwinding?

Additionally, if current is a kernel thread when this happens,
perf_sample_regs_user() sets regs_user->regs = &pm_regs while
perf_sample_ustack_size() returns 0 (since current->mm is NULL), which
causes perf_prepare_sample() and perf_output_sample_ustack() to disagree
on the PERF_SAMPLE_STACK_USER record size.

Similarly, when !user_mode(&pm_regs) is true (pm_regs.pc >= TASK_SIZE),
passing the stack-local &pm_regs to perf_event_overflow() affects
arch/alpha/kernel/perf_regs.c:perf_reg_value():

	if (idx == PERF_REG_ALPHA_SP) {
		if (user_mode(regs))
			return user_stack_pointer(regs);
		if (!object_is_on_stack(regs))
			return 0;
		/* Same kernel sp approximation as stacktrace.c. */
		return (unsigned long)(regs + 1);
	}

and arch/alpha/kernel/stacktrace.c:arch_stack_walk():

	if (regs && task == current) {
		ksp = (unsigned long)(regs + 1);
	}

Because pm_regs is a local variable on the stack, object_is_on_stack(&pm_regs)
is true, so &pm_regs + 1 points inside alpha_perf_event_profileme()'s own
stack frame rather than the end of the interrupted trap frame (regs + 1).
And if the PMI landed in user mode after a profiled kernel instruction,
clearing bit 3 of pm_regs.ps causes perf_callchain_kernel() and
PERF_SAMPLE_REGS_INTR to treat the user register frame as a kernel frame
and unwind the kernel stack starting from &pm_regs + 1.

Could the PC and PS adjustments be made in-place on regs (and restored
after perf_event_overflow()) only when the PMPC mode matches the
interrupted mode in regs, or how should mode-mismatched samples handle register
and stack sampling?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261028-alpha-profileme-v1-0-d44b52bf2500@gmail.com?part=3

  reply	other threads:[~2026-10-28 18:28 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-28 18:09 [PATCH 0/5] alpha/perf: add ProfileMe sampling Matt Turner
2026-10-28 18:09 ` [PATCH 1/5] alpha/perf: pass PERFMON_CMD_LOGGING_ALL to the logging options call Matt Turner
2026-10-28 18:12   ` sashiko-bot
2026-10-29 17:38   ` Magnus Lindholm
2026-10-28 18:09 ` [PATCH 2/5] alpha/perf: add sysfs format and event attributes Matt Turner
2026-10-28 18:13   ` sashiko-bot
2026-10-28 18:09 ` [PATCH 3/5] alpha/perf: implement ProfileMe sampling Matt Turner
2026-10-28 18:28   ` sashiko-bot [this message]
2026-10-29 15:18   ` Magnus Lindholm
2026-10-28 18:09 ` [PATCH 4/5] alpha/perf: attach ProfileMe status as PERF_SAMPLE_RAW data Matt Turner
2026-10-28 18:26   ` sashiko-bot
2026-10-28 18:09 ` [PATCH 5/5] alpha/perf: optionally randomize the ProfileMe sampling interval Matt Turner
2026-10-28 18:21   ` sashiko-bot
2026-10-29 15:01   ` Magnus Lindholm
2026-10-29  9:11 ` [PATCH 0/5] alpha/perf: add ProfileMe sampling Peter Zijlstra
2026-10-29 15:34   ` Matt Turner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-188288@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mattst88@gmail.com \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.