From fc59e5b584d72687d4684563cf09c531f234c1f6 Mon Sep 17 00:00:00 2001 From: Benjamin Walsh Date: Sat, 1 Oct 2016 18:49:36 -0400 Subject: [PATCH] unified/arm: fix saving of registers in __pendsv() The unified kernel calls a function (_get_next_ready_thread) to fetch the next thread to run: it thus must save caller-saved registers that are expected to hold a value before calling such function. The callee-saved registers are available after saving them in the outgoing thread's stack, so use some of those instead to reduce the number of registers to save before calling _get_next_ready_thread. Also, save caller-saved registers in callee-saved registers instead of on the stack to reduce memory accesses. This issue did not show up previously, probably because _get_next_ready_thread did not use the regsiters that had to be saved, but an upcoming optimization to that function stomps on them. Change-Id: I27dcededace846e623c3870d907f0d4c464173bf Signed-off-by: Benjamin Walsh --- arch/arm/core/swap.S | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/core/swap.S b/arch/arm/core/swap.S index 8762dce3fe5..9f061e81dba 100644 --- a/arch/arm/core/swap.S +++ b/arch/arm/core/swap.S @@ -92,8 +92,8 @@ SECTION_FUNC(TEXT, __pendsv) * to pend PendSV have been taken with the current kernel * state and this is what we're handling currently. */ - ldr ip, =_SCS_ICSR - ldr r3, =_SCS_ICSR_UNPENDSV + ldr v4, =_SCS_ICSR + ldr v3, =_SCS_ICSR_UNPENDSV /* protect the kernel state while we play with the thread lists */ movs.n r0, #_EXC_IRQ_DEFAULT_PRIO @@ -102,9 +102,11 @@ SECTION_FUNC(TEXT, __pendsv) /* find out incoming thread (fiber or task) */ #ifdef CONFIG_KERNEL_V2 - push {lr} + mov.n v2, lr + movs.n v1, r1 blx _get_next_ready_thread - pop {lr} + movs.n r1, v1 + mov.n lr, v2 movs.n r2, r0 #else /* is there a fiber ready ? */ @@ -137,8 +139,8 @@ SECTION_FUNC(TEXT, __pendsv) * has been handled. */ - /* _SCS_ICSR is still in ip and _SCS_ICSR_UNPENDSV in r3 */ - str r3, [ip, #0] + /* _SCS_ICSR is still in v4 and _SCS_ICSR_UNPENDSV in v3 */ + str v3, [v4, #0] /* restore BASEPRI for the incoming thread */ ldr r0, [r2, #__tTCS_basepri_OFFSET]