[PATCH] x86/mm: fix objtool failure with KMSAN enabled

1 view
Skip to first unread message

Dmitry Voytik

unread,
Jul 1, 2026, 8:51:57 AMJul 1
to Alexander Potapenko, Borislav Petkov, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev, Dmitry Voytik
This patch fixes broken builds with defconfig + CONFIG_KMSAN +
CONFIG_DEBUG_INFO_*.

To reproduce the issue before the fix:
make mrproper
make LLVM=1 defconfig
./scripts/config -e CONFIG_KMSAN \
-e CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
make LLVM=1 olddefconfig
make LLVM=1 -j(nproc) vmlinux
...
LD vmlinux.o
vmlinux.o: warning: objtool: folio_zero_user+0x801: undefined stack state
vmlinux.o: error: objtool: folio_zero_user+0x801: unknown CFA base reg -1
make[2]: *** [scripts/Makefile.vmlinux_o:76: vmlinux.o] Error 255

objtool in verbose mode shows how the frame pointer is omitted:
make LLVM=1 OBJTOOL_VERBOSE=1 -j(nproc) vmlinux
...
b15a2c: folio_zero_user+0x7fc xor %eax,%eax
b15a2e: folio_zero_user+0x7fe mov %rcx,%rsp
b15a31: folio_zero_user+0x801 mov %r14,%rdi
b15a34: folio_zero_user+0x804 mov %rbx,%rcx
b15a37: folio_zero_user+0x807 call 0xb15a3c <__clear_pages_unrol

After the fix, the frame pointer is back:
b15a37: 31 c0 xor %eax,%eax
b15a39: 48 89 ec mov %rbp,%rsp
b15a3c: 4c 89 f7 mov %r14,%rdi
b15a3f: 48 89 d9 mov %rbx,%rcx
b15a42: e8 00 00 00 00 call b15a47 <folio_zero_user+0x817>

It seems the issue was introduced by
commit 54a6b89a3db2 ("x86/mm: simplify clear_page_*")

The actual fix is to revert the change how ASM_CALL_CONSTRAINT is
positioned.
Additionally, reintroduce asm_inline to prevent potential compiler
rejection of inlining.

Link: https://lore.kernel.org/CAAX90H2_RPnZL_dFYN7cQF6yt-wAweKKSx2=6e2aZ0k...@mail.gmail.com
Signed-off-by: Dmitry Voytik <voy...@gmail.com>
---
arch/x86/include/asm/page_64.h | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h
index 1895c207f629..de8604f0a3a1 100644
--- a/arch/x86/include/asm/page_64.h
+++ b/arch/x86/include/asm/page_64.h
@@ -100,12 +100,13 @@ static inline void clear_pages(void *addr, unsigned int npages)
* __clear_pages_unrolled() are part of the inline asm register
* specification.
*/
- asm volatile(ALTERNATIVE_2("call __clear_pages_unrolled",
- "shrq $3, %%rcx; rep stosq", X86_FEATURE_REP_GOOD,
- "rep stosb", X86_FEATURE_ERMS)
- : "+c" (len), "+D" (addr), ASM_CALL_CONSTRAINT
- : "a" (0)
- : "cc", "memory");
+ asm_inline volatile(
+ ALTERNATIVE_2("call __clear_pages_unrolled",
+ "shrq $3, %%rcx; rep stosq", X86_FEATURE_REP_GOOD,
+ "rep stosb", X86_FEATURE_ERMS)
+ : ASM_CALL_CONSTRAINT, "+c"(len), "+D"(addr)
+ : "a"(0)
+ : "cc", "memory");
}
#define clear_pages clear_pages

--
2.54.0

Alexander Potapenko

unread,
Jul 1, 2026, 9:18:56 AMJul 1
to Dmitry Voytik, Thomas Gleixner, Borislav Petkov, Peter Zijlstra, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
Have you tried running KMSAN with this fix?

I tried running with the config that Thomas posted at
https://lore.kernel.org/all/87tsqjq3i3.ffs@fw13/
(https://tglx.de/~tglx/config.fail), and it still hangs for me.

Dmitry Voytik

unread,
Jul 1, 2026, 10:45:47 AMJul 1
to Alexander Potapenko, Thomas Gleixner, Borislav Petkov, Peter Zijlstra, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
Hi Alexander,
I only tested the fix with defconfig + CONFIG_KMSAN +
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT + olddefconfig.

qemu-system-x86_64 \
-kernel arch/x86/boot/bzImage \
-append "console=ttyS0" \
-nographic \
-m 8G -smp 4 \
-serial file:serial_output.log

Booting from ROM..
[ 0.000000] Linux version 7.1.0-14280-g3dd2bc904bda
(voyt@voyt-laptop-dell) (clang version 22.1.6, LLD 22.1.6) #2 SMP
PREEMPT_DYNAMIC Wed Jul 1 16:25:28 CEST 2026
...
[ 2.274314] Starting KernelMemorySanitizer
[ 2.274356] ATTENTION: KMSAN is a debugging tool! Do not use it on
production machines!
[ 2.357699] Dynamic Preempt: lazy
[ 2.390793] rcu: Preemptible hierarchical RCU implementation.
[ 2.391032] rcu: RCU event tracing is enabled.
[ 2.391256] rcu: RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=4.
...
[ 53.009112] /dev/root: Can't open blockdev
[ 53.012357] VFS: Cannot open root device "" or unknown-block(0,0): error -6
[ 53.013186] Please append a correct "root=" boot option; here are
the available partitions:
...

Alexander Potapenko

unread,
Jul 1, 2026, 11:16:19 AMJul 1
to Dmitry Voytik, Thomas Gleixner, Borislav Petkov, Peter Zijlstra, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
In fact I think the hangs are being caused by CONFIG_UNWINDER_ORC=y,
sorry for the noise.

Dmitry Voytik

unread,
Jul 1, 2026, 6:48:30 PMJul 1
to Alexander Potapenko, Thomas Gleixner, Borislav Petkov, Peter Zijlstra, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
On Wed, Jul 1, 2026 at 5:16 PM Alexander Potapenko <gli...@google.com> wrote:

> In fact I think the hangs are being caused by CONFIG_UNWINDER_ORC=y,
> sorry for the noise.

No worries!
Just in case, I double checked with current Linus' tree, defconfig +
KMSAN + DEBUG_INFO_* ,
and it looks like CONFIG_UNWINDER_ORC gets enabled:

git pull -r
make mrproper
make LLVM=1 defconfig
./scripts/config -e CONFIG_KMSAN \
-e CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
make LLVM=1 olddefconfig
make LLVM=1 W=ce -j(nproc) bzImage

grep CONFIG_UNWINDER_ORC .config
CONFIG_UNWINDER_ORC=y

and the kernel boots in qemu, so maybe something else is causing
(another?) issue?

Borislav Petkov

unread,
Jul 1, 2026, 10:54:22 PMJul 1
to Dmitry Voytik, linux-to...@vger.kernel.org, Alexander Potapenko, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
Why?

Where does it say that the current stack ptr dependency needs to be the first
asm input operand?

If that were the case, we have a bunch more of those bugs around the tree.

Anyway, + linux-toolchains.
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette

Dmitry Voytik

unread,
Jul 2, 2026, 6:41:39 AMJul 2
to Borislav Petkov, linux-to...@vger.kernel.org, Alexander Potapenko, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
Hi Borislav,
Very good question. My uneducated guess - bugs in clang.
Out of curiosity, I compared (see below) what clang and gcc do when
ASM_CALL_CONSTRAINT moves around, and it indeed affects generated
code, which is weird.
I might just be holding it wrong, like optimization must be on, etc.

> If that were the case, we have a bunch more of those bugs around the tree.

At least, it makes objtool happy for the defconfig + KMSAN.

> Anyway, + linux-toolchains.

Thanks for looking into this.

Comparing clang and gcc:

// clang asm_clang.c -o out
// gcc asm_clang.c -o out
// objdump -d --disassemble=main out

#include <stdio.h>

int func() {
return 42;
}

#define __stringify_1(x...) #x
#define __stringify(x...) __stringify_1(x)
# define __ASM_FORM_RAW(x, ...) __stringify(x,##__VA_ARGS__)
# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
#define __ASM_REG(reg) __ASM_SEL_RAW(e##reg, r##reg)
#define _ASM_SP __ASM_REG(sp)
register unsigned long current_stack_pointer asm(_ASM_SP);
#define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer)

int main() {
int output_val = 0;

__asm__ __volatile__ ( "call func\n\t" : "=a" (output_val) : :);
// clang v22.1.6
// 1142: e8 d9 ff ff ff call 1120 <func>
// 1147: 89 45 f8 mov %eax,-0x8(%rbp)
// gcc:
// 112f: e8 e5 ff ff ff call 1119 <func>
// 1134: 89 45 fc mov %eax,-0x4(%rbp)

__asm__ __volatile__ (
"call func\n\t" : ASM_CALL_CONSTRAINT, "=a" (output_val) : :);
// clang v22.1.6
// 114a: 48 89 e0 mov %rsp,%rax
// 114d: 48 89 c4 mov %rax,%rsp
// 1150: e8 cb ff ff ff call 1120 <func>
// 1155: 48 89 e1 mov %rsp,%rcx
// 1158: 48 89 cc mov %rcx,%rsp
// 115b: 89 45 f8 mov %eax,-0x8(%rbp)
// gcc:
// 1137: e8 dd ff ff ff call 1119 <func>
// 113c: 89 45 fc mov %eax,-0x4(%rbp)

__asm__ __volatile__ (
"call func\n\t" : "=a" (output_val), ASM_CALL_CONSTRAINT : :);
// clang v22.1.6
// 115e: 48 89 e0 mov %rsp,%rax
// 1161: 48 89 c4 mov %rax,%rsp
// 1164: e8 b7 ff ff ff call 1120 <func>
// 1169: 89 c1 mov %eax,%ecx
// 116b: 48 89 e0 mov %rsp,%rax
// 116e: 89 4d f8 mov %ecx,-0x8(%rbp)
// 1171: 48 89 c4 mov %rax,%rsp
// gcc:
// 113f: e8 d5 ff ff ff call 1119 <func>
// 1144: 89 45 fc mov %eax,-0x4(%rbp)
return 0;

Peter Zijlstra

unread,
Jul 2, 2026, 7:16:00 AMJul 2
to Dmitry Voytik, Borislav Petkov, linux-to...@vger.kernel.org, Alexander Potapenko, Thomas Gleixner, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
Yeah, for all the wrong reasons. AFAICT it is one clang bug causing
another clang bug to manifest less onerous.

This ASM_CALL_CONSTRAINT placement is, for some reason, forcing a stack
frame (which is not in fact required), but having a stack frame then
avoids the absolutely retarded:

mov %rsp, %rcx;
1: mov %rcx, %rsp
...
mov %rsp, disp(%rsp)
call __msam_foo
mov disp(%rsp), %rcx
test
je 1b

construct. Becaus having the stack frame (rbp) then makes all the rsp
juggling less of a problem.

So on the one hand the __msan 'functions' are special annotated in clang
to force re-align the stack. Then it notices the stack is already
properly aligned and the actual stack alignment code goes missing, BUT
it keeps the save/restore rsp (for raisins). It then furher compounds
the failure by spilling the RSP copy onto the stack, and voila, total
and utter insanity.

I suspect you can simply remove that magic annotate for KMSAM, kernel
stacks are always aligned, there no point, what-so-ever, to do the whole
save/align/restore thing.

There is also this thread from last year, which looks to be a
similar/same problem:

https://lore.kernel.org/174108458405.14745.4864877018394987266.tip-bot2@tip-bot2

those patches never made it in, Josh was going to rework, but that never
quite happened either.

And I think we need to, at least temporarily, deal with this, until a
fixed clang is released and we can make KMSAN depend on that version,
but I worry about the impact of this change on !KMSAN builds.

A quick test with folio_zero_user() seems to suggest the
ASM_CALL_CONSTRAINT movement (your patch) generates the same code for
defconfg as does the unmodified code. The change from the thread linked
above (input constraint on __builtin_frame_address(0)) generates
different code.

A third option is to force FRAME_POINTER=y for KMSAN builds -- for now,
until clang is taught to be less insane.

Thomas Gleixner

unread,
Jul 2, 2026, 3:46:39 PMJul 2
to Peter Zijlstra, Dmitry Voytik, Borislav Petkov, linux-to...@vger.kernel.org, Alexander Potapenko, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
On Thu, Jul 02 2026 at 13:15, Peter Zijlstra wrote:
> A quick test with folio_zero_user() seems to suggest the
> ASM_CALL_CONSTRAINT movement (your patch) generates the same code for
> defconfg as does the unmodified code. The change from the thread linked
> above (input constraint on __builtin_frame_address(0)) generates
> different code.
>
> A third option is to force FRAME_POINTER=y for KMSAN builds -- for now,
> until clang is taught to be less insane.

With FRAME_POINTER=y I get now with clang-22

vmlinux.o: warning: objtool: folio_zero_user+0xa7b: stack state mismatch: reg1[4]=-1+0 reg2[4]=-2-336
vmlinux.o: warning: objtool: set_ftrace_ops_ro+0x64: relocation to !ENDBR: machine_kexec_prepare+0x8f0

That's with your objtool patch applied. When I remove that then the
folio_zero_user one goes away. The relocation to !ENDBR stays.

Oh well...


Thomas Gleixner

unread,
Jul 2, 2026, 4:05:09 PMJul 2
to Peter Zijlstra, Dmitry Voytik, Borislav Petkov, linux-to...@vger.kernel.org, Alexander Potapenko, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
And none of this boots when KMSAN=y ....

Dmitry Voytik

unread,
Jul 3, 2026, 6:34:45 AMJul 3
to Thomas Gleixner, Peter Zijlstra, Borislav Petkov, linux-to...@vger.kernel.org, Alexander Potapenko, Ingo Molnar, Dave Hansen, Josh Poimboeuf, Dmitry Vyukov, Andrew Morton, Ankur Arora, H . Peter Anvin, Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt, Marco Elver, x...@kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, ll...@lists.linux.dev
Hi Thomas,
Thanks for checking this!
I wonder if we are debugging clang here because I just retested the patch with
CONFIG_FRAME_POINTER on the current Linus' tree and it works in my env:

clang --version
clang version 22.1.6

git pull -r
git show -s --oneline -2
21f3d2b2069e (HEAD -> master) x86/mm: fix objtool failure with KMSAN enabled
d2c9a99135da (origin/master, origin/HEAD) Merge tag 'device-id-rework'
of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux

make mrproper
make LLVM=1 defconfig
./scripts/config \
-e CONFIG_KMSAN \
-e CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT \
-e UNWINDER_FRAME_POINTER
make LLVM=1 olddefconfig
make LLVM=1 W=ce -j(nproc) bzImage

grep -e CONFIG_KMSAN= -e CONFIG_FRAME_POINTER \
-e CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT .config

CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_FRAME_POINTER=y
CONFIG_KMSAN=y

qemu-system-x86_64 \
-kernel arch/x86/boot/bzImage \
-accel kvm \
-append "console=ttyS0" \
-nographic \
-m 8G -smp 4 \
-serial file:serial_out.log

grep -e 'Linux version' -A1 -e KernelMemorySanitizer -e 'append a
correct' serial_out.log

[ 0.000000] Linux version 7.2.0-rc1-00009-gb0b29f0286be
(voyt@voyt-laptop-dell) (clang version 22.1.6, LLD 22.1.6) #1 SMP
PREEMPT_DYNAMIC Fri Jul 3 11:55:02 CEST 2026
[ 0.000000] Command line: console=ttyS0
--
[ 0.218380] Starting KernelMemorySanitizer
[ 0.218382] ATTENTION: KMSAN is a debugging tool! Do not use it on
production machines!
--
[ 4.037384] Please append a correct "root=" boot option; here are
the available partitions:
[ 4.037772] 0b00 1048575 sr0


Could another CONFIG_ be the culprit on your side? Or, has your clang
version some different (buggy?) behaviour?
Reply all
Reply to author
Forward
0 new messages