RE: [RFC PATCH 31/56] x86/alternative: Prepend nops with retpolines

Kaplan, David
2025-10-16T13:27:57Z

[AMD Official Use Only - AMD Internal Distribution Only]

> -----Original Message-----
> From: Peter Zijlstra <peterz@infradead.org>
> Sent: Thursday, October 16, 2025 6:23 AM
> To: Kaplan, David <David.Kaplan@amd.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>; Borislav Petkov <bp@alien8.de>; Josh
> Poimboeuf <jpoimboe@kernel.org>; Pawan Gupta
> <pawan.kumar.gupta@linux.intel.com>; Ingo Molnar <mingo@redhat.com>; Dave
> Hansen <dave.hansen@linux.intel.com>; x86@kernel.org; H . Peter Anvin
> <hpa@zytor.com>; Alexander Graf <graf@amazon.com>; Boris Ostrovsky
> <boris.ostrovsky@oracle.com>; linux-kernel@vger.kernel.org
> Subject: Re: [RFC PATCH 31/56] x86/alternative: Prepend nops with retpolines
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> On Thu, Oct 16, 2025 at 01:07:17PM +0200, Peter Zijlstra wrote:
> > On Mon, Oct 13, 2025 at 09:34:19AM -0500, David Kaplan wrote:
> > > When patching retpolines, nops may be required for padding such as when
> > > turning a 5-byte direct call into a 2-byte indirect call. Previously,
> > > these were appended at the end so the code becomes "call *reg;nop;nop;nop"
> > > for example. This was fine because it's always going from a larger
> > > instruction to a smaller one.
> > >
> > > But this is a problem if the sequence is transformed from a 2-byte indirect
> > > to the 5-byte direct call version at runtime because when the called
> > > function returns, it will be in the middle of the 5-byte call instruction.
> > >
> > > To fix this, prepend the nops instead of appending them. Consequently, the
> > > return site of the called function is always the same.
> > >
> >
> > So this results in:
> >
> > NOP3; call *%r11
> >
> > And you're saying a task can be on the other side of that call and then
> > return lines up. But what if the task is preempted right after that
> > NOP3?
> >
> > Same for all the alternative patching; what ensures no task is currently
> > having a register state that is in the middle of things?
>
> Ah, I found it, you freeze everything, which puts it at safe points.

Yes. In fact, I think you were the one who pointed me in that direction :)

Despite the freezer though, this patch is necessary in particular because stop_machine_nmi() uses an indirect branch to run the handler. Which means that while patching is going on, all cores are inside a function which is going to return to after the indirect call site. And so that needs to be the end of the 5 (or 6) byte sequence.

--David Kaplan