From: "Mi, Dapeng" <dapeng1.mi@linux.intel.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ian Rogers <irogers@google.com>,
x86@kernel.org
Cc: Vince Weaver <vincent.weaver@maine.edu>,
"Liang, Kan" <kan.liang@linux.intel.com>,
linux-perf-users@vger.kernel.org
Subject: Re: perf_event: avoiding gpf on rdpmc for top-down-events on hybrid
Date: Thu, 5 Nov 2026 14:17:07 +0800 [thread overview]
Message-ID: <569b3882-5862-4f6f-96b7-302910e2cf4e@linux.intel.com> (raw)
In-Reply-To: <20250618084522.GE1613376@noisy.programming.kicks-ass.net>
On 6/18/2025 4:45 PM, Peter Zijlstra wrote:
> On Tue, Jun 17, 2025 at 01:36:40PM -0700, Ian Rogers wrote:
>
>> Thanks Peter, out of curiosity, how does the RDPMC fail? If an event
>> were rescheduled (even with RSEQ assuming the CPU the thread is
>> running on doesn't change) could the RDPMC with the incorrect index
>> also fail?
> So the problem with RDPMC is that it will #GP when used with an invalid
> index.
>
> Normally, when counting using fixed or general purpose events, this is
> not a problem, because every CPU in the machine has those. So while the
> index might not be the event you were after, the instruction doesn't
> trap, we observe the sequence changed and retry the loop. No harm done.
>
> But for the top-down thingies, the P-cores will have a RDPMC idx that
> the E-cores do not support. Using this index on an E-core will #GP.
>
> So the following situation:
>
> CPU-P CPU-E
>
> do {
> seq = pc->lock;
> barrier();
>
> index = pc->index;
> count = pc->count;
> if (index) {
> width = pm->pmc_width;
>
> <migrate task to CPU-E>
>
> rdpmc(index - 1); <-- #GP
> }
>
> barrier();
> } while (pc->lock != seq);
>
> Where the task is migrated from a P to an E core after reading the
> index but before doing RDPMC, turns fatal.
>
> When we use RSEQ, the migration will abort the sequence and the RDPMC
> will not be executed.
>
>
> Aand... while writing this I wondered why we don't simply fix up the
> fault in kernel space. Something like so...
If we silently drop the #GP for invalid rdpmc index, it would make the
kernel's behavior inconsistent with what SDM describes, "Specifying an
unsupported PMC encoding will cause a general protection exception #GP(0)."
It may break users' default assumption and cause some issues.
>
> ---
> diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> index 9f88b8a78e50..90391526acf7 100644
> --- a/arch/x86/kernel/traps.c
> +++ b/arch/x86/kernel/traps.c
> @@ -677,6 +677,43 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
>
> #define GPFSTR "general protection fault"
>
> +static bool fixup_rdpmc_exception(struct pt_regs *regs)
> +{
> + struct mm_struct *mm = current->mm;
> + u8 buf[MAX_INSN_SIZE];
> + struct insn insn;
> + int len;
> +
> + len = insn_fetch_from_user(regs, buf);
> + if (len <= 0)
> + return false;
> +
> + if (!insn_decode_from_regs(&insn, regs, buf, len))
> + return false;
> +
> + /* RDPMC */
> + if (insn.opcode.bytes[0] != 0x0f || insn.opcode.bytes[1] != 0x33)
> + return false;
> +
> + if (!atomic_read(&mm->context.perf_rdpmc_allowed))
> + return false;
> +
> + /*
> + * So userspace RDPMC is allowed and took #GP.
> + *
> + * This means they got the index wrong. But per the ABI described in
> + * struct perf_event_mmap_page; this means they'll also fail the
> + * sequence lock and will retry the operation after re-reading the
> + * index.
> + *
> + * Fake out the RDPMC by returning all zeros and continue.
> + */
> + regs->ax = 0;
> + regs->dx = 0;
> + regs->ip += insn.length;
> + return true;
> +}
> +
> static bool fixup_iopl_exception(struct pt_regs *regs)
> {
> struct thread_struct *t = ¤t->thread;
> @@ -812,6 +849,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
> }
>
> if (user_mode(regs)) {
> + if (fixup_rdpmc_exception(regs))
> + goto exit;
> +
> if (fixup_iopl_exception(regs))
> goto exit;
>
prev parent reply other threads:[~2026-11-05 6:17 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-04 21:20 perf_event: avoiding gpf on rdpmc for top-down-events on hybrid Vince Weaver
2024-12-05 0:57 ` Ian Rogers
2025-06-15 23:23 ` Ian Rogers
2025-06-16 19:34 ` Vince Weaver
2025-06-17 4:36 ` Ian Rogers
2025-06-17 16:37 ` Ian Rogers
2025-06-17 18:17 ` Peter Zijlstra
2025-06-17 20:36 ` Ian Rogers
2025-06-18 8:45 ` Peter Zijlstra
2025-06-18 11:55 ` Peter Zijlstra
2025-06-18 13:57 ` Vince Weaver
2026-11-05 6:17 ` Mi, Dapeng [this message]
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=569b3882-5862-4f6f-96b7-302910e2cf4e@linux.intel.com \
--to=dapeng1.mi@linux.intel.com \
--cc=irogers@google.com \
--cc=kan.liang@linux.intel.com \
--cc=linux-perf-users@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=vincent.weaver@maine.edu \
--cc=x86@kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox