[PATCH v4 4/5] ARM: smp: Store current pointer in TPIDRURO register if available
Ard Biesheuvel
ardb at kernel.org
Mon Sep 13 05:52:46 PDT 2021
Hi Russell,
Thanks for taking a look.
On Mon, 13 Sept 2021 at 13:22, Russell King (Oracle)
<linux at armlinux.org.uk> wrote:
>
> On Mon, Sep 13, 2021 at 12:40:00PM +0200, Ard Biesheuvel wrote:
> > @@ -767,13 +769,18 @@ ENTRY(__switch_to)
> > mcr p15, 0, r6, c3, c0, 0 @ Set domain register
> > #endif
> > mov r5, r0
> > - add r4, r2, #TI_CPU_SAVE
> > + mov r4, r2
> > ldr r0, =thread_notify_head
> > mov r1, #THREAD_NOTIFY_SWITCH
> > bl atomic_notifier_call_chain
> > #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
> > str r7, [r8]
> > #endif
> > +#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
> > + ldr ip, [r4, #TI_TASK]
> > + set_current ip
> > +#endif
> > + add r4, r4, #TI_CPU_SAVE
> > THUMB( mov ip, r4 )
> > mov r0, r5
> > ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously
>
> I would like to keep this as optimal as possible, and the setting of
> TPIDRURO to be as close to the stack pointer change too, so I'd
> suggest a slightly different approach:
>
> switch_tls r1, r4, r5, r3, r7
> +#if (defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)) || \
> + defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO)
> + ldr r9, [r2, #TI_TASK]
> +#endif
> #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
> - ldr r7, [r2, #TI_TASK]
> ldr r8, =__stack_chk_guard
> .if (TSK_STACK_CANARY > IMM12_MASK)
> - add r7, r7, #TSK_STACK_CANARY & ~IMM12_MASK
> - .endif
> + add r7, r9, #TSK_STACK_CANARY & ~IMM12_MASK
> ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK]
> + .else
> + ldr r7, [r9, #TSK_STACK_CANARY & IMM12_MASK]
> + .endif
> #endif
> ...
> mov r0, r5
> +#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
> + set_current r9
> +#endif
> ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously
>
> It's a slightly more complex change, but one I think we should do.
>
Fair enough.
However, the next patch drops the 'ldr ip, [r4, #TI_TASK]' I am adding
here, so I won't be able to use this as-is.
I could just split the ldr/set_current sequence into two, and change
the first one into a mov in the following patch, and move the
set_current to right before where sp is updated.
I.e., in this patch
@@ -762,6 +764,8 @@ ENTRY(__switch_to)
add r7, r7, #TSK_STACK_CANARY & ~IMM12_MASK
.endif
ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK]
+#elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO)
+ ldr r7, [r2, #TI_TASK]
#endif
#ifdef CONFIG_CPU_USE_DOMAINS
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
@@ -776,6 +780,7 @@ ENTRY(__switch_to)
#endif
THUMB( mov ip, r4 )
mov r0, r5
+ set_current r7
ARM( ldmia r4, {r4 - sl, fp, sp, pc} )
THUMB( ldmia ip!, {r4 - sl, fp} )
THUMB( ldr sp, [ip], #4 )
and in the next one
@@ -765,7 +765,7 @@ ENTRY(__switch_to)
.endif
ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK]
#elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO)
- ldr r7, [r2, #TI_TASK]
+ mov r7, r2 @ Preserve 'next'
#endif
#ifdef CONFIG_CPU_USE_DOMAINS
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
Would that work for you?
More information about the linux-arm-kernel
mailing list