Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interrupt nesting #10057

Merged
merged 9 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions arch/arm/include/armv6-m/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,9 @@
#define REG_R9 (7) /* R9 */
#define REG_R10 (8) /* R10 */
#define REG_R11 (9) /* R11 */

/* In the kernel build, we may return to either privileged or unprivileged
* modes.
*/

#ifdef CONFIG_BUILD_PROTECTED
# define REG_EXC_RETURN (10) /* EXC_RETURN */
# define SW_XCPT_REGS (11)
#else
# define SW_XCPT_REGS (10)
#endif
#define REG_CONTROL (10) /* CONTROL */
#define REG_EXC_RETURN (11) /* EXC_RETURN */
#define SW_XCPT_REGS (12)

/* The total number of registers saved by software */

Expand Down
5 changes: 3 additions & 2 deletions arch/arm/include/armv7-m/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@
#define REG_R9 (7) /* R9 */
#define REG_R10 (8) /* R10 */
#define REG_R11 (9) /* R11 */
#define REG_EXC_RETURN (10) /* EXC_RETURN */
#define SW_INT_REGS (11)
#define REG_CONTROL (10) /* CONTROL */
#define REG_EXC_RETURN (11) /* EXC_RETURN */
#define SW_INT_REGS (12)

#ifdef CONFIG_ARCH_FPU

Expand Down
5 changes: 3 additions & 2 deletions arch/arm/include/armv8-m/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@
#define REG_R9 (7) /* R9 */
#define REG_R10 (8) /* R10 */
#define REG_R11 (9) /* R11 */
#define REG_EXC_RETURN (10) /* EXC_RETURN */
#define SW_INT_REGS (11)
#define REG_CONTROL (10) /* CONTROL */
#define REG_EXC_RETURN (11) /* EXC_RETURN */
#define SW_INT_REGS (12)

#ifdef CONFIG_ARCH_FPU

Expand Down
5 changes: 5 additions & 0 deletions arch/arm/include/tlsr82/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ static inline void up_enable_irq(int irq)
_IRQ_MASK_REG |= (1 << irq);
}

static inline uint32_t getcontrol(void)
{
return 0;
}

#endif /* __ASSEMBLY__ */

/****************************************************************************
Expand Down
18 changes: 4 additions & 14 deletions arch/arm/src/armv6-m/arm_doirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <sched/sched.h>

#include "arm_internal.h"
#include "exc_return.h"

/****************************************************************************
* Public Functions
Expand All @@ -46,20 +47,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
PANIC();
#else

/* Nested interrupts are not supported in this implementation. If you
* want to implement nested interrupts, you would have to (1) change the
* way that CURRENT_REGS is handled and (2) the design associated with
* CONFIG_ARCH_INTERRUPTSTACK.
*/

/* Current regs non-zero indicates that we are processing an interrupt;
* CURRENT_REGS is also used to manage interrupt level context switches.
*/

if (CURRENT_REGS == NULL)
if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
{
CURRENT_REGS = regs;
regs = NULL;
}

/* Acknowledge the interrupt */
Expand All @@ -68,15 +58,15 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)

/* Deliver the IRQ */

irq_dispatch(irq, (uint32_t *)CURRENT_REGS);
irq_dispatch(irq, regs);

/* If a context switch occurred while processing the interrupt then
* CURRENT_REGS may have change value. If we return any value different
* from the input regs, then the lower level will know that a context
* switch occurred during interrupt processing.
*/

if (regs == NULL)
if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
{
/* Restore the cpu lock */

Expand Down
74 changes: 19 additions & 55 deletions arch/arm/src/armv6-m/arm_exception.S
Original file line number Diff line number Diff line change
Expand Up @@ -58,26 +58,6 @@
.globl exception_common
.file "arm_exception.S"

/****************************************************************************
* Macro Definitions
****************************************************************************/

/****************************************************************************
* Name: setintstack
*
* Description:
* Set the current stack pointer to the "top" the interrupt stack. Single CPU
* case. Must be provided by MCU-specific logic in the SMP case.
*
****************************************************************************/

#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 3
.macro setintstack, tmp1, tmp2
ldr \tmp1, =g_intstacktop
mov sp, \tmp1
.endm
#endif

/****************************************************************************
* .text
****************************************************************************/
Expand Down Expand Up @@ -114,18 +94,17 @@ exception_common:
* the context is on the MSP or PSP.
*/

#ifdef CONFIG_BUILD_PROTECTED
mov r0, r14 /* Copy high register to low register */
lsls r0, #(31 - EXC_RETURN_PROCESS_BITNO) /* Move to bit 31 */
bmi 1f /* Test bit 31 */
mrs r1, msp /* R1=The main stack pointer */
subs r1, #SW_XCPT_SIZE /* R1=Beginning of context array on the stack */
msr msp, r1 /* Reserved stack space */
b 2f

1:
mrs r1, psp /* R1=The process stack pointer */
#else
mrs r1, msp /* R1=The main stack pointer */
#endif
subs r1, #SW_XCPT_SIZE /* R1=Beginning of context array on the stack */

/* R1 is the current stack pointer. HW_XCPT_REGS were pushed onto the stack
* when the interrupt was taken so (R1)+HW_XCPT_SIZE is the value of the
Expand All @@ -137,26 +116,22 @@ exception_common:
2:
/* Save SP, PRIMASK, and R4-R7 in the context array */

subs r1, #SW_XCPT_SIZE /* R1=Beginning of context array on the stack */
movs r2, #XCPTCONTEXT_SIZE /* R2=Size of the context array */
add r2, r1 /* R2=MSP/PSP before the interrupt was taken */
/* (ignoring the xPSR[9] alignment bit) */
mrs r3, primask /* R3=Current PRIMASK setting */
mov r0, r1 /* Copy the context array pointer */
stmia r0!, {r2-r7} /* Save the SP, PRIMASK, and R4-R7 in the context array */

/* Save R8-R11 and the EXEC_RETURN value in the context array */
/* Save R8-R11 control and the EXEC_RETURN value in the context array */

mov r2, r8 /* Copy high registers to low */
mov r3, r9
mov r4, r10
mov r5, r11
#ifdef CONFIG_BUILD_PROTECTED
mov r6, r14
stmia r0!, {r2-r6} /* Save the high registers r8-r11 and r14 */
#else
stmia r0!, {r2-r5} /* Save the high registers r8-r11 */
#endif
mrs r6, control /* R6=control */
mov r7, r14
stmia r0!, {r2-r7} /* Save the high registers r8-r11 control and r14 */

/* Get the exception number in R0=IRQ, R1=register save area on stack */

Expand All @@ -167,9 +142,7 @@ exception_common:
* Otherwise, we will use the stack that was current when the interrupt was taken.
*/

#if CONFIG_ARCH_INTERRUPTSTACK > 3
setintstack r7, r6 /* SP = IRQ stack top */
#else
#if CONFIG_ARCH_INTERRUPTSTACK < 3
/* If the interrupt stack is disabled, reserve xcpcontext to ensure
* that signal processing can have a separate xcpcontext to handle
* signal context (reference: arm_schedulesigaction.c):
Expand All @@ -181,9 +154,13 @@ exception_common:
* also the sp should be restore after arm_doirq()
*/

mov r2, r14
lsls r2, #(31 - EXC_RETURN_THREAD_BITNO) /* Move to bit 31 */
bpl 3f /* Test bit 31 */
mov r2, r1 /* Reserve signal context */
subs r2, r2, #XCPTCONTEXT_SIZE
msr msp, r2 /* We are using the main stack pointer */
3:
#endif

bl arm_doirq /* R0=IRQ, R1=register save area on stack */
Expand All @@ -196,20 +173,13 @@ exception_common:

movs r2, #(4*REG_R8) /* R2=Offset to R8 storage */
adds r1, r0, r2 /* R1=Address of R8 storage */
#ifdef CONFIG_BUILD_PROTECTED
ldmia r1!, {r2-r6} /* Recover R8-R11 and R14 (5 registers)*/
mov r8, r2 /* Move to position in high registers */
mov r9, r3
mov r10, r4
mov r11, r5
mov r14, r6 /* EXEC_RETURN */
#else
ldmia r1!, {r2-r5} /* Recover R8-R11 (4 registers)*/
ldmia r1!, {r2-r7} /* Recover R8-R11 control and R14 (6 registers)*/
mov r8, r2 /* Move to position in high registers */
mov r9, r3
mov r10, r4
mov r11, r5
#endif
msr control, r6
mov r14, r7 /* EXEC_RETURN */

/* Recover SP (R2), PRIMASK (R3), and R4-R7. Determine the value of
* the stack pointer as it was on entry to the exception handler.
Expand All @@ -223,22 +193,16 @@ exception_common:
* context is on the MSP or PSP.
*/

#ifdef CONFIG_BUILD_PROTECTED
mov r0, r14 /* Copy high register to low register */
lsls r0, #(31 - EXC_RETURN_PROCESS_BITNO) /* Move to bit 31 */
bmi 3f /* Test bit 31 */
bmi 4f /* Test bit 31 */
msr msp, r1 /* R1=The main stack pointer */
b 4f
b 5f

3:
4:
msr psp, r1 /* R1=The process stack pointer */

4:
#else
msr msp, r1 /* R1=The main stack pointer */
ldr r0, =EXC_RETURN_PRIVTHR /* R0=EXC_RETURN to privileged mode */
mov r14, r0 /* R14=EXC_RETURN to privileged mode */
#endif
5:

/* Restore the interrupt state */

Expand Down
49 changes: 46 additions & 3 deletions arch/arm/src/armv6-m/arm_initialstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,19 +129,62 @@ void up_initial_state(struct tcb_s *tcb)
#endif
#endif /* CONFIG_PIC */

#ifdef CONFIG_BUILD_PROTECTED
/* All tasks start via a stub function in kernel space. So all
* tasks must start in privileged thread mode. If CONFIG_BUILD_PROTECTED
* is defined, then that stub function will switch to unprivileged
* mode before transferring control to the user task.
*/

xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
#endif
xcp->regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;

xcp->regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;

/* Enable or disable interrupts, based on user configuration */

#ifdef CONFIG_SUPPRESS_INTERRUPTS
xcp->regs[REG_PRIMASK] = 1;
#endif /* CONFIG_SUPPRESS_INTERRUPTS */
}

#if CONFIG_ARCH_INTERRUPTSTACK > 3
/****************************************************************************
* Name: arm_initialize_stack
*
* Description:
* If interrupt stack is defined, the PSP and MSP need to be reinitialized.
*
****************************************************************************/

noinline_function void arm_initialize_stack(void)
{
#ifdef CONFIG_SMP
uint32_t stack = (uint32_t)arm_intstack_top();
#else
uint32_t stack = (uint32_t)g_intstacktop;
#endif
uint32_t tempa = 0;
uint32_t tempb = 2;

__asm__ __volatile__
(

/* Initialize PSP */

"mov %1, sp\n"
"msr psp, %1\n"

/* Select PSP */

"mrs %1, CONTROL\n"
"orr %1, %2\n"
"msr CONTROL, %1\n"
"isb sy\n"

/* Initialize MSP */

"msr msp, %0\n"
:
: "r" (stack), "r" (tempa), "r" (tempb)
: "memory");
}
#endif
8 changes: 3 additions & 5 deletions arch/arm/src/armv6-m/arm_saveusercontext.S
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,12 @@ up_saveusercontext:
/* Save r11 and EXC_RETURN */

mov r1, r11
#ifdef CONFIG_BUILD_PROTECTED

/* Save EXC_RETURN to 0xffffffff */

movs r2, #-1
movs r2, #0
subs r2, #1
stmia r0!, {r1-r2}
#else
stmia r0!, {r1}
#endif

movs r0, #0
bx lr
Expand Down
17 changes: 11 additions & 6 deletions arch/arm/src/armv6-m/arm_schedulesigaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
CURRENT_REGS[REG_PRIMASK] = 1;
CURRENT_REGS[REG_XPSR] = ARMV6M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD;
CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_THREAD;
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}
}
Expand Down Expand Up @@ -199,7 +200,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_PRIMASK] = 1;
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}
}
Expand Down Expand Up @@ -305,7 +307,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_PRIMASK] = 1;
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}
else
Expand Down Expand Up @@ -347,7 +350,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
CURRENT_REGS[REG_PRIMASK] = 1;
CURRENT_REGS[REG_XPSR] = ARMV6M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD;
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}

Expand Down Expand Up @@ -405,7 +409,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_PRIMASK] = 1;
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
#ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
#endif
}
}
Expand Down
Loading
Loading