Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions
From: Jürgen Groß
Date: Fri Aug 14 2026 - 06:16:02 EST
On 13.08.26 21:57, 李则良 wrote:
I am currently testing the more general approach shown below. Your
review is also appreciated.
on vmlinux-O1:
0xffffffff82f447de <+126>: ff 15 a4 a9 cf ff call QWORD PTR
[rip+0xffffffffffcfa9a4] # 0xffffffff82c3f188 <pv_ops+8>
0xffffffff82f447e4 <+132>: eb f8 jmp
0xffffffff82f447de <early_fixup_exception+126>
0xffffffff82f447e6 <+134>: 5b pop rbx
0xffffffff82f447e7 <+135>: 41 5c pop r12
0xffffffff82f447e9 <+137>: 5d pop rbp
on vmlinux-O2:
0xffffffff82f3bf4f <+127>: ff 15 33 32 d0 ff call QWORD PTR
[rip+0xffffffffffd03233] # 0xffffffff82c3f188 <pv_ops+8>
0xffffffff82f3bf55 <+133>: eb f8 jmp
0xffffffff82f3bf4f <early_fixup_exception+127>
0xffffffff82f3bf57 <+135>: 5b pop rbx
0xffffffff82f3bf58 <+136>: 41 5c pop r12
0xffffffff82f3bf5a <+138>: 5d pop rbp
This is an early draft – please review. Thanks in advance.
From 5989dcf448e4d23ea4f3a0f91fec34f3dd25d26c Mon Sep 17 00:00:00 2001
From: Zeliang Li <lizeliang.linux@xxxxxxxxx>
Date: Fri, 14 Aug 2026 03:17:38 +0800
Subject: [PATCH] x86/paravirt: Force RIP-relative paravirt calls under low
optimization levels
When compiling the kernel with non-standard lower optimization levels like
-O1 (e.g., during specific debugging or framework testing setups) using
newer toolchains like GCC 15.2.0, the compiler exhibits passive register
hoisting. In complex code paths like early_fixup_exception(), it caches the
base address of the global 'pv_ops' structure into a general-purpose register
instead of issuing direct RIP-relative memory loads, producing:
mov $0xffffffff82c3f180, %rbx
call *0x8(%rbx)
While this behavior is bypassed under aggressive -O2 optimizations, under -O1
it leaves a register-relative indirect call. This violates the strict format
assertion in the x86 alternative text-patching engine (alt_replace_call),
which expects an 'ALT_FLAG_DIRECT_CALL' site to be a standard 6-byte
RIP-relative indirect call (ff 15), leading to a boot-time kernel BUG.
Fix this by changing the x86_64 paravirt inline assembly to use an "i"
(immediate) constraint for the function pointer address, and explicitly
reference it via (%rip) in the assembly template. This removes the
toolchain's ability to select any other addressing mode, guaranteeing the
emission of compliant 'call *pv_ops+offset(%rip)' sequences on x86_64
regardless of the active compiler -O flag.
For i386, the original "m" constraint is retained since RIP-relative
addressing does not exist on 32-bit x86.
Signed-off-by: Zeliang Li <lizeliang.linux@xxxxxxxxx>
---
arch/x86/include/asm/paravirt_types.h | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/paravirt_types.h
b/arch/x86/include/asm/paravirt_types.h
index b4c4a23e77a1..e8047bdbed3a 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -184,8 +184,6 @@ struct paravirt_patch_template {
extern struct paravirt_patch_template pv_ops;
-#define paravirt_ptr(array, op) [paravirt_opptr] "m" (array.op)
-
/*
* This generates an indirect call based on the operation type number.
*
@@ -197,9 +195,20 @@ extern struct paravirt_patch_template pv_ops;
* OTOH since this is effectively a __nocfi indirect call, the paravirt stubs
* don't need to bother with CFI prefixes.
*/
+#ifdef CONFIG_X86_64
+
+#define paravirt_ptr(array, op) [paravirt_opptr] "i" (&(array.op))
#define PARAVIRT_CALL \
ANNOTATE_RETPOLINE_SAFE "\n\t" \
- "call *%[paravirt_opptr]"
+ "call *%c[paravirt_opptr](%%rip);"
+#else /* CONFIG_X86_32 */
+
+#define paravirt_ptr(array, op) [paravirt_opptr] "m" (array.op)
+#define PARAVIRT_CALL \
+ ANNOTATE_RETPOLINE_SAFE "\n\t" \
+ "call *%[paravirt_opptr];"
+
+#endif /* CONFIG_X86_64 */
/*
* These macros are intended to wrap calls through one of the paravirt
Thanks for this solution. I like it much more, especially as it will avoid
any nasty compiler optimizations as the one you have observed.
When sending this as a proper patch you can add my:
Reviewed-by: Juergen Gross <jgross@xxxxxxxx>
Juergen
Attachment:
OpenPGP_0xB0DE9DD628BF132F.asc
Description: OpenPGP public key
Attachment:
OpenPGP_signature.asc
Description: OpenPGP digital signature