[PATCH v2 6/7] ARM: entry: rework stack realignment code in svc_entry
Nicolas Pitre
nico at fluxnic.net
Mon Oct 18 08:40:10 PDT 2021
On Mon, 18 Oct 2021, Ard Biesheuvel wrote:
> The original Thumb-2 enablement patches updated the stack realignment
> code in svc_entry to work around the lack of a STMIB instruction in
> Thumb-2, by subtracting 4 from the frame size, inverting the sense of
> the misaligment check, and changing to a STMIA instruction and a final
> stack push of a 4 byte quantity that results in the stack becoming
> aligned at the end of the sequence. It also pushes and pops R0 to the
> stack in order to have a temp register that Thumb-2 allows in general
> purpose ALU instructions, as TST using SP is not permitted.
>
> Both are a bit problematic for vmap'ed stacks, as using the stack is
> only permitted after we decide that we did not overflow the stack, or
> have already switched to the overflow stack.
>
> As for the alignment check: the current approach creates a corner case
> where, if the initial SUB of SP ends up right at the start of the stack,
> we will end up subtracting another 8 bytes and overflowing it. This
> means we would need to add the overflow check *after* the SUB that
> deliberately misaligns the stack. However, this would require us to keep
> local state (i.e., whether we performed the subtract or not) across the
> overflow check, but without any GPRs or stack available.
>
> So let's switch to an approach where we don't use the stack, and where
> the alignment check of the stack pointer occurs in the usual way, as
> this is guaranteed not to result in overflow. This means we will be able
> to do the overflow check first.
>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
Nice! I like it.
Acked-by: Nicolas Pitre <nico at fluxnic.net>
> ---
> arch/arm/kernel/entry-armv.S | 25 +++++++++++---------
> 1 file changed, 14 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> index 18504d7b4d15..80afab1c344b 100644
> --- a/arch/arm/kernel/entry-armv.S
> +++ b/arch/arm/kernel/entry-armv.S
> @@ -192,24 +192,27 @@ ENDPROC(__und_invalid)
> .macro svc_entry, stack_hole=0, trace=1, uaccess=1
> UNWIND(.fnstart )
> UNWIND(.save {r0 - pc} )
> - sub sp, sp, #(SVC_REGS_SIZE + \stack_hole - 4)
> + sub sp, sp, #(SVC_REGS_SIZE + \stack_hole)
> #ifdef CONFIG_THUMB2_KERNEL
> - SPFIX( str r0, [sp] ) @ temporarily saved
> - SPFIX( mov r0, sp )
> - SPFIX( tst r0, #4 ) @ test original stack alignment
> - SPFIX( ldr r0, [sp] ) @ restored
> + add sp, r0 @ get SP in a GPR without
> + sub r0, sp, r0 @ using a temp register
> + tst r0, #4 @ test stack pointer alignment
> + sub r0, sp, r0 @ restore original R0
> + sub sp, r0 @ restore original SP
> #else
> SPFIX( tst sp, #4 )
> #endif
> - SPFIX( subeq sp, sp, #4 )
> - stmia sp, {r1 - r12}
> + SPFIX( subne sp, sp, #4 )
> +
> + ARM( stmib sp, {r1 - r12} )
> + THUMB( stmia sp, {r0 - r12} ) @ No STMIB in Thumb-2
>
> ldmia r0, {r3 - r5}
> - add r7, sp, #S_SP - 4 @ here for interlock avoidance
> + add r7, sp, #S_SP @ here for interlock avoidance
> mov r6, #-1 @ "" "" "" ""
> - add r2, sp, #(SVC_REGS_SIZE + \stack_hole - 4)
> - SPFIX( addeq r2, r2, #4 )
> - str r3, [sp, #-4]! @ save the "real" r0 copied
> + add r2, sp, #(SVC_REGS_SIZE + \stack_hole)
> + SPFIX( addne r2, r2, #4 )
> + str r3, [sp] @ save the "real" r0 copied
> @ from the exception stack
>
> mov r3, lr
> --
> 2.30.2
>
>
More information about the linux-arm-kernel
mailing list