Repository navigation
arch/arm: Tell the compiler which registers a system call changes. - #20873
Merged
Merged
Conversation
casaroli
requested review from
GUIDINGLI,
pussuw and
xiaoxiang781216
as code owners
October 21, 2026 14:30
|
A system call returns from dispatch_syscall() with R1-R3 and R12 of the kernel: R2 holds the return value, and the stub function may change R1, R3 and R12. The sys_call macros gave R1-R3 to the compiler as inputs only and did not clobber R12, so the compiler kept values in them across the SVC. With CONFIG_LTO_FULL, posix_spawnattr_init() inlines two system calls and gives the second one the pid that it set for the first one in R1; sched_getscheduler() then gets another pid and fails with ESRCH, and no program starts on qemu-armv7a:knsh. The same happens without LTO when one function makes two system calls with the macros: on qemu-armv7a:knsh, sched_getparam(0) and then sched_getscheduler(0) give 0 and -1 (ESRCH). The GCC form now gives R0-R3 as in and out operands where they carry a parameter and clobbers the others and R12, and the GHS form clobbers them too. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
On armv7-a, armv7-r and armv8-r, dispatch_syscall() reads g_stublookup only in its inline assembly. LTO does not see that reference, so with CONFIG_LTO_FULL the link of a protected or kernel build does not take syscall_stublookup.o from libstubs.a, or makes the table local: arm_syscall.c:144:(.text.dispatch_syscall+0x24): undefined reference to `g_stublookup' The assembly now gets the table as an "i" operand. The compiler then sees the reference: the link takes the table, and the assembly uses the name that LTO gives to it. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
casaroli
force-pushed
the
arm-syscall-clobbers
branch
from
October 22, 2026 07:33
69fec63 to
be31bce
Compare
xiaoxiang781216
approved these changes
Oct 22, 2026
acassis
approved these changes
Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A system call returns from
dispatch_syscall()with R1-R3 and R12 of the kernel (R2 holds the return value). Thesys_callmacros ofarch/arm/include/syscall.hgave R1-R3 to the compiler as inputs only and did not clobber R12, so the compiler could keep a value in them across the SVC.A function with two system calls then passes a wrong parameter to the second one. On
qemu-armv7a:knsh,sched_getparam(0)followed bysched_getscheduler(0)gives 0 and -1 (ESRCH). WithCONFIG_LTO_FULL,posix_spawnattr_init()inlines exactly these two calls, so no program starts.The GCC form now gives R0-R3 as in and out operands where they carry a parameter and clobbers the others and R12. The GHS form clobbers them too.
A second commit keeps the stub table in an LTO link. On armv7-a, armv7-r and armv8-r,
dispatch_syscall()readsg_stublookuponly in assembly, which LTO does not see, so the link fails withundefined reference to 'g_stublookup'. The assembly now gets the table as an"i"operand, so the compiler sees the reference.Impact
arm protected and kernel builds (the code that calls the
sys_callmacros). The compiler saves values that it keeps across a system call; no other change.Testing
qemu-armv7a:knsh(kernel build, Arm GNU 15.3, QEMU), a program that callssched_getparam(0)andsched_getscheduler(0)with the macros in one function, thenostest:getparam 0 getscheduler -1: FAILostestExiting with status 0With #20846 and
CONFIG_LTO_FULL,qemu-armv7a:knshlinks, the same program passes, andostestexits with status 0.qemu-armv7r:pnsh(protected build, armv7-r) builds; upstream QEMU cannot run it.mps2-an500:knsh(protected build, armv7-m, QEMU): the same program passes.tools/checkpatch.sh -c -u -m -gpasses. The GHS form is not built here.