Skip to content

Commit 599d0d8

Browse files
authored
Improve register utilization in PendSV when ARM TrustZone is enabled.
2 parents 053f4b3 + 35e026f commit 599d0d8

1 file changed

Lines changed: 52 additions & 52 deletions

File tree

stk/src/arch/arm/cortex-m/stk_arch_arm-cortex-m.cpp

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -170,19 +170,19 @@ enum class ERegMask : Word
170170
};
171171

172172
//! Make unprivileged.
173-
static inline Word SetUnprivileged(Word REG_CONTROL) noexcept
173+
__stk_attr_unused static inline Word SetUnprivileged(Word REG_CONTROL) noexcept
174174
{
175175
return (REG_CONTROL | static_cast<Word>(ERegMask::MASK_nPRIV));
176176
}
177177

178178
//! Make privileged.
179-
static inline Word SetPrivileged(Word REG_CONTROL) noexcept
179+
__stk_attr_unused static inline Word SetPrivileged(Word REG_CONTROL) noexcept
180180
{
181181
return (REG_CONTROL & ~static_cast<Word>(ERegMask::MASK_nPRIV));
182182
}
183183

184184
//! Set Stack Pointer selection to PSP.
185-
static inline Word SetSPSelectionToPSP(Word REG_CONTROL) noexcept
185+
__stk_attr_unused static inline Word SetSPSelectionToPSP(Word REG_CONTROL) noexcept
186186
{
187187
return (REG_CONTROL | static_cast<Word>(ERegMask::MASK_SPSEL));
188188
}
@@ -1529,13 +1529,8 @@ extern "C" void STK_SYSTICK_HANDLER()
15291529
__set_CONTROL(__get_CONTROL() | CONTROL_nPRIV_Msk)
15301530
*/
15311531

1532-
#ifdef __ICCARM__
1533-
#define STK_ASM_BLOCK_PRIVILEGE_MODE_LOAD_ACTIVE_STACK\
1532+
#define STK_ASM_BLOCK_PRIVILEGE_MODE_LOAD_ACTIVE_STACK\
15341533
"MOV r1, %[st_active]\n" /* r1 = Stack* (already in register) */
1535-
#else
1536-
#define STK_ASM_BLOCK_PRIVILEGE_MODE_LOAD_ACTIVE_STACK\
1537-
"LDR r1, %[st_active]\n" /* r1 = Stack* (m_stack_active) */
1538-
#endif
15391534

15401535
#define STK_ASM_BLOCK_PRIVILEGE_MODE\
15411536
STK_ASM_BLOCK_PRIVILEGE_MODE_LOAD_ACTIVE_STACK\
@@ -1556,6 +1551,22 @@ extern "C" void STK_SYSTICK_HANDLER()
15561551

15571552
extern "C" __stk_attr_naked void STK_PENDSV_HANDLER()
15581553
{
1554+
#if (STK_ARCH_CPU_COUNT > 1U)
1555+
// Optimize register utilization and prevent compiler from using r4-r11
1556+
// registers before they are saved. Use r12 IPC scratch register for that
1557+
// and calculate offset for p_ctx only once. Instruct assembler to use
1558+
// r3, r2 for holding pointers to Idle and Active stacks.
1559+
#ifdef __ICCARM__
1560+
register Context *p_ctx = &GetContext();
1561+
register Stack *p_st_idle = p_ctx->m_stack_idle;
1562+
register Stack *p_st_active = p_ctx->m_stack_active;
1563+
#else
1564+
register Context *p_ctx __asm("r12") = &GetContext();
1565+
register Stack *p_st_idle __asm("r3") = p_ctx->m_stack_idle;
1566+
register Stack *p_st_active __asm("r2") = p_ctx->m_stack_active;
1567+
#endif
1568+
#endif
1569+
15591570
__asm volatile(
15601571
STK_ASM_SYNTAX_UNIFIED
15611572

@@ -1574,7 +1585,7 @@ extern "C" __stk_attr_naked void STK_PENDSV_HANDLER()
15741585
"TST LR, #16 \n" /* test LR for 0xffffffe_, e.g. Thread mode with FP data */
15751586

15761587
"IT EQ \n" /* if result is positive */
1577-
"VMOVEQ s0, s0 \n" /* force hardware lazy state preservation */
1588+
"VMOVEQ.F32 s0, s0 \n" /* force hardware lazy state preservation */
15781589

15791590
"IT EQ \n" /* if result is positive */
15801591
"VSTMDBEQ r0!, {s16-s31} \n" /* store 16 SP registers */
@@ -1607,35 +1618,29 @@ extern "C" __stk_attr_naked void STK_PENDSV_HANDLER()
16071618
// PSP_NS captures the task's Non-Secure stack mid-execution (may be inside an
16081619
// NS call that was interrupted); CONTROL_NS preserves NS privilege / stack-select.
16091620
#if STK_CORTEX_M_TRUSTZONE_FRAME
1610-
"MRS r2, PSPLIM \n" /* Secure PSPLIM */
1611-
"MRS r3, PSPLIM_NS \n" /* Non-Secure PSPLIM */
1612-
"STMDB r0!, {r2, r3} \n" /* push PSPLIM, PSPLIM_NS */
1621+
// push PSPLIM, PSPLIM_NS (equivalent to STMDB r0!, {PSPLIM, PSPLIM_NS})
1622+
"MRS r12, PSPLIM_NS \n"
1623+
"STR r12, [r0, #-4]! \n"
1624+
"MRS r12, PSPLIM \n"
1625+
"STR r12, [r0, #-4]! \n"
16131626

1614-
"MRS r2, PSP_NS \n" /* Non-Secure PSP (mid-execution value) */
1615-
"MRS r3, CONTROL_NS \n" /* Non-Secure CONTROL (nPRIV, SPSEL) */
1616-
"STMDB r0!, {r2, r3} \n" /* push PSP_NS, CONTROL_NS */
1627+
// push PSP_NS, CONTROL_NS (equivalent to STMDB r0!, {PSP_NS, CONTROL_NS})
1628+
"MRS r12, CONTROL_NS \n"
1629+
"STR r12, [r0, #-4]! \n"
1630+
"MRS r12, PSP_NS \n"
1631+
"STR r12, [r0, #-4]! \n"
16171632
#endif
16181633

16191634
// Store in GetContext().m_stack_idle.
1620-
#ifdef __ICCARM__
16211635
"STR r0, [%[st_idle]] \n" /* store the first member (Stack::SP) from r0 */
1622-
#else
1623-
"LDR r1, %[st_idle] \n"
1624-
"STR r0, [r1] \n" /* store the first member (Stack::SP) from r0 */
1625-
#endif
16261636

16271637
// Set privileged/unprivileged mode for the active stack.
16281638
#ifdef CONTROL_nPRIV_Msk
16291639
STK_ASM_BLOCK_PRIVILEGE_MODE
16301640
#endif
16311641

16321642
// Load stack of the active task from GetContext().m_stack_active (note: keep in sync with OnTaskStart).
1633-
#ifdef __ICCARM__
16341643
"LDR r0, [%[st_active]]\n" /* load the first member of Stack (Stack::SP) into r0 */
1635-
#else
1636-
"LDR r1, %[st_active] \n"
1637-
"LDR r0, [r1] \n" /* load the first member of Stack (Stack::SP) into r0 */
1638-
#endif
16391644

16401645
// ARMv8-M TrustZone: restore TrustZoneFrame fields in reverse push order.
16411646
// Pop order: PSP_NS + CONTROL_NS first (pushed last), then PSPLIM + PSPLIM_NS.
@@ -1646,13 +1651,15 @@ extern "C" __stk_attr_naked void STK_PENDSV_HANDLER()
16461651
// EXC_RETURN in LR (restored by LDMIA below) carries the S-bit that tells
16471652
// the CPU which world to return to on "BX LR" - no explicit branch needed.
16481653
#if STK_CORTEX_M_TRUSTZONE_FRAME
1649-
"LDMIA r0!, {r2, r3} \n" /* pop PSP_NS, CONTROL_NS */
1650-
"MSR PSP_NS, r2 \n" /* restore Non-Secure PSP */
1651-
"MSR CONTROL_NS, r3 \n" /* restore Non-Secure CONTROL */
1654+
"LDR r12, [r0], #4 \n" /* PSP_NS */
1655+
"MSR PSP_NS, r12 \n"
1656+
"LDR r12, [r0], #4 \n" /* CONTROL_NS */
1657+
"MSR CONTROL_NS, r12 \n"
16521658

1653-
"LDMIA r0!, {r2, r3} \n" /* pop PSPLIM, PSPLIM_NS */
1654-
"MSR PSPLIM, r2 \n" /* restore Secure PSPLIM */
1655-
"MSR PSPLIM_NS, r3 \n" /* restore Non-Secure PSPLIM */
1659+
"LDR r12, [r0], #4 \n" /* PSPLIM */
1660+
"MSR PSPLIM, r12 \n"
1661+
"LDR r12, [r0], #4 \n" /* PSPLIM_NS */
1662+
"MSR PSPLIM_NS, r12 \n"
16561663
#endif
16571664

16581665
// Restore registers of active task's CPU context:
@@ -1685,28 +1692,30 @@ extern "C" __stk_attr_naked void STK_PENDSV_HANDLER()
16851692
STK_ASM_EXIT_FROM_HANDLER " \n"
16861693

16871694
: /* output: none */
1695+
#if (STK_ARCH_CPU_COUNT > 1U)
16881696
#ifdef __ICCARM__
1697+
: [st_idle] "r3" (p_st_idle),
1698+
[st_active] "r2" (p_st_active),
1699+
#else
1700+
: [st_idle] "r" (p_st_idle),
1701+
[st_active] "r" (p_st_active),
1702+
#endif
1703+
#else
16891704
: [st_idle] "r" (GetContext().m_stack_idle),
16901705
[st_active] "r" (GetContext().m_stack_active),
1691-
#else
1692-
: [st_idle] "m" (GetContext().m_stack_idle),
1693-
[st_active] "m" (GetContext().m_stack_active),
16941706
#endif
16951707
[priv_val] "i" (ACCESS_PRIVILEGED)
1696-
: "r0", "r1" /* used as a scratchpad */
1708+
: "r0", "r1" /* used as a scratchpad */, "memory"
16971709
#if STK_CORTEX_M_TRUSTZONE_FRAME
1698-
, "r2", "r3"
1699-
#endif
1700-
#if defined(__ICCARM__)
1701-
, "memory"
1710+
, "cc", "r12"
17021711
#endif
17031712
);
17041713
}
17051714

17061715
__stk_attr_naked void OnTaskStart()
17071716
{
17081717
// Note: HW_DisableInterrupts() must be called prior calling this function.
1709-
1718+
17101719
__asm volatile(
17111720
STK_ASM_SYNTAX_UNIFIED
17121721

@@ -1717,12 +1726,7 @@ __stk_attr_naked void OnTaskStart()
17171726

17181727
// Load stack of the active task from GetContext().m_stack_active (Note: keep
17191728
// in sync with OnTaskStart).
1720-
#ifdef __ICCARM__
1721-
"LDR r0, [%[st_active]]\n" /* IAR: load the first member of Stack (Stack::SP) into r0, %[st_active] is a pointer value register */
1722-
#else
1723-
"LDR r1, %[st_active] \n" /* GCC: %[st_active] is a memory address pointing to Stack* */
1724-
"LDR r0, [r1] \n" /* GCC: load the first member of Stack (Stack::SP) into r0 */
1725-
#endif
1729+
"LDR r0, [%[st_active]]\n" /* load the first member of Stack (Stack::SP) into r0, %[st_active] is a pointer value register */
17261730

17271731
// ARMv8-M TrustZone: restore TrustZoneFrame fields in reverse push order (see STK_PENDSV_HANDLER).
17281732
// Pop order: PSP_NS + CONTROL_NS first, then PSPLIM + PSPLIM_NS.
@@ -1772,18 +1776,14 @@ __stk_attr_naked void OnTaskStart()
17721776
STK_ASM_EXIT_FROM_HANDLER " \n"
17731777

17741778
: /* output: none */
1775-
#ifdef __ICCARM__
17761779
: [st_active] "r" (GetContext().m_stack_active),
1777-
#else
1778-
: [st_active] "m" (GetContext().m_stack_active),
1779-
#endif
17801780
[priv_val] "i" (ACCESS_PRIVILEGED)
17811781
#if !STK_CORTEX_M_MANAGE_LR
17821782
, [exc_ret] "i" (STK_CORTEX_M_EXC_RETURN_THREAD_PSP)
17831783
#endif
17841784
: "r0", "r1" /* used as a scratchpad */
17851785
#if STK_CORTEX_M_TRUSTZONE_FRAME
1786-
, "r2", "r3"
1786+
, "cc", "r2", "r3"
17871787
#endif
17881788
#if defined(__ICCARM__)
17891789
, "memory"

0 commit comments

Comments
 (0)