arch: use up_current_regs/up_set_current_regs replace CURRENT_REGS
reason: 1 On different architectures, we can utilize more optimized strategies to implement up_current_regs/up_set_current_regs. eg. use interrupt registersor percpu registers. code size before text data bss dec hex filename 262848 49985 63893 376726 5bf96 nuttx after text data bss dec hex filename 262844 49985 63893 376722 5bf92 nuttx size change -4 Configuring NuttX and compile: $ ./tools/configure.sh -l qemu-armv8a:nsh_smp $ make Running with qemu $ qemu-system-aarch64 -cpu cortex-a53 -smp 4 -nographic \ -machine virt,virtualization=on,gic-version=3 \ -net none -chardev stdio,id=con,mux=on -serial chardev:con \ -mon chardev=con,mode=readline -kernel ./nuttx Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
parent
222840e135
commit
908df725ad
@ -89,9 +89,9 @@ extern "C"
|
||||
****************************************************************************/
|
||||
|
||||
/* g_current_regs[] holds a references to the current interrupt level
|
||||
* register storage structure. It is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the macro
|
||||
* CURRENT_REGS for portability.
|
||||
* register storage structure. If is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the
|
||||
* [get/set]_current_regs for portability.
|
||||
*/
|
||||
|
||||
/* For the case of architectures with multiple CPUs, then there must be one
|
||||
@ -99,7 +99,6 @@ extern "C"
|
||||
*/
|
||||
|
||||
EXTERN volatile uint32_t *g_current_regs[CONFIG_SMP_NCPUS];
|
||||
#define CURRENT_REGS (g_current_regs[up_cpu_index()])
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
@ -109,6 +108,16 @@ EXTERN volatile uint32_t *g_current_regs[CONFIG_SMP_NCPUS];
|
||||
* Inline functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline_function uint32_t *up_current_regs(void)
|
||||
{
|
||||
return (uint32_t *)g_current_regs[up_cpu_index()];
|
||||
}
|
||||
|
||||
static inline_function void up_set_current_regs(uint32_t *regs)
|
||||
{
|
||||
g_current_regs[up_cpu_index()] = regs;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_interrupt_context
|
||||
*
|
||||
@ -125,7 +134,7 @@ static inline bool up_interrupt_context(void)
|
||||
irqstate_t flags = up_irq_save();
|
||||
#endif
|
||||
|
||||
bool ret = CURRENT_REGS != NULL;
|
||||
bool ret = up_current_regs() != NULL;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
up_irq_restore(flags);
|
||||
|
@ -72,13 +72,13 @@ void arm_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr)
|
||||
#ifdef CONFIG_LEGACY_PAGING
|
||||
uint32_t *savestate;
|
||||
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
savestate = (uint32_t *)CURRENT_REGS;
|
||||
savestate = up_current_regs();
|
||||
#endif
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
#ifdef CONFIG_LEGACY_PAGING
|
||||
/* In the NuttX on-demand paging implementation, only the read-only, .text
|
||||
@ -133,12 +133,12 @@ void arm_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr)
|
||||
|
||||
pg_miss();
|
||||
|
||||
/* Restore the previous value of CURRENT_REGS. NULL would indicate that
|
||||
/* Restore the previous value of current_regs. NULL would indicate that
|
||||
* we are no longer in an interrupt handler. It will be non-NULL if we
|
||||
* are returning from a nested interrupt.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = savestate;
|
||||
up_set_current_regs(savestate);
|
||||
return;
|
||||
|
||||
segfault:
|
||||
@ -153,11 +153,11 @@ segfault:
|
||||
|
||||
void arm_dataabort(uint32_t *regs)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Crash -- possibly showing diagnost debug information. */
|
||||
|
||||
|
@ -64,13 +64,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
#else
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
|
||||
@ -81,13 +81,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
irq_dispatch(irq, regs);
|
||||
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* CURRENT_REGS will have a different value than it did on entry. If an
|
||||
* current_regs will have a different value than it did on entry. If an
|
||||
* interrupt level context switch has occurred, then restore the floating
|
||||
* point state and the establish the correct address environment before
|
||||
* returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Make sure that the address environment for the previously
|
||||
@ -106,14 +106,14 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
#endif
|
||||
board_autoled_off(LED_INIRQ);
|
||||
return regs;
|
||||
|
@ -68,13 +68,13 @@ void arm_prefetchabort(uint32_t *regs)
|
||||
#ifdef CONFIG_LEGACY_PAGING
|
||||
uint32_t *savestate;
|
||||
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
savestate = (uint32_t *)CURRENT_REGS;
|
||||
savestate = up_current_regs();
|
||||
#endif
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
#ifdef CONFIG_LEGACY_PAGING
|
||||
/* Get the (virtual) address of instruction that caused the prefetch
|
||||
@ -114,12 +114,12 @@ void arm_prefetchabort(uint32_t *regs)
|
||||
|
||||
pg_miss();
|
||||
|
||||
/* Restore the previous value of CURRENT_REGS. NULL would indicate
|
||||
/* Restore the previous value of current_regs. NULL would indicate
|
||||
* that we are no longer in an interrupt handler. It will be non-NULL
|
||||
* if we are returning from a nested interrupt.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = savestate;
|
||||
up_set_current_regs(savestate);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -89,7 +89,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -97,7 +97,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* a task is signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
@ -114,7 +114,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* logic would fail in the strange case where we are in an
|
||||
* interrupt handler, the thread is signalling itself, but
|
||||
* a context switch to another task has occurred so that
|
||||
* CURRENT_REGS does not refer to the thread of this_task()!
|
||||
* current_regs does not refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
else
|
||||
@ -135,23 +135,22 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT;
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT;
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -60,13 +60,13 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* The SYSCALL command is in R0 on entry. Parameters follow in R1..R7 */
|
||||
|
||||
@ -94,8 +94,8 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
* set will determine the restored context.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R1];
|
||||
DEBUGASSERT(CURRENT_REGS);
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
DEBUGASSERT(up_current_regs());
|
||||
}
|
||||
break;
|
||||
|
||||
@ -120,7 +120,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R2];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -135,12 +135,12 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* CURRENT_REGS will have a different value than it did on entry. If an
|
||||
* current_regs will have a different value than it did on entry. If an
|
||||
* interrupt level context switch has occurred, then establish the correct
|
||||
* address environment before returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Make sure that the address environment for the previously
|
||||
* running task is closed down gracefully (data caches dump,
|
||||
@ -154,7 +154,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task. g_running_tasks[] is only used by
|
||||
* assertion logic for reporting crashes.
|
||||
@ -167,14 +167,14 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
/* Restore the cpu lock */
|
||||
|
||||
restore_critical_section(tcb, cpu);
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
/* Return the last value of curent_regs. This supports context switches
|
||||
* on return from the exception. That capability is only used with the
|
||||
|
@ -43,6 +43,7 @@
|
||||
void arm_undefinedinsn(uint32_t *regs)
|
||||
{
|
||||
_alert("Undefined instruction at 0x%" PRIx32 "\n", regs[REG_PC]);
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
PANIC_WITH_REGS("panic", regs);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
|
||||
if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
|
||||
{
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
@ -61,7 +61,7 @@ uint32_t *arm_doirq(int irq, uint32_t *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
|
||||
* 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.
|
||||
*/
|
||||
@ -70,7 +70,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
@ -78,13 +78,12 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Update the CURRENT_REGS to NULL. */
|
||||
/* Update the current_regs to NULL. */
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -94,7 +94,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -102,7 +102,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handle will run in a critical section!
|
||||
@ -137,27 +137,26 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_PRIMASK] = 1;
|
||||
CURRENT_REGS[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
up_current_regs()[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD;
|
||||
CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -226,7 +225,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
@ -237,7 +236,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !CURRENT_REGS)
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
@ -326,26 +325,25 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_PRIMASK] = 1;
|
||||
CURRENT_REGS[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
up_current_regs()[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD;
|
||||
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
uint32_t *regs = (uint32_t *)context;
|
||||
uint32_t cmd;
|
||||
|
||||
DEBUGASSERT(regs && regs == CURRENT_REGS);
|
||||
DEBUGASSERT(regs && regs == up_current_regs());
|
||||
cmd = regs[REG_R0];
|
||||
|
||||
/* The SVCall software interrupt is called with R0 = system call command
|
||||
@ -158,16 +158,16 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
* R0 = SYS_restore_context
|
||||
* R1 = restoreregs
|
||||
*
|
||||
* In this case, we simply need to set CURRENT_REGS to restore register
|
||||
* area referenced in the saved R1. context == CURRENT_REGS is the
|
||||
* normal exception return. By setting CURRENT_REGS = context[R1], we
|
||||
* In this case, we simply need to set current_regs to restore register
|
||||
* area referenced in the saved R1. context == current_regs is the
|
||||
* normal exception return. By setting current_regs = context[R1], we
|
||||
* force the return to the saved context referenced in R1.
|
||||
*/
|
||||
|
||||
case SYS_restore_context:
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0);
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R1];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -184,7 +184,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
*
|
||||
* In this case, we do both: We save the context registers to the save
|
||||
* register area reference by the saved contents of R1 and then set
|
||||
* CURRENT_REGS to the save register area referenced by the saved
|
||||
* current_regs to the save register area referenced by the saved
|
||||
* contents of R2.
|
||||
*/
|
||||
|
||||
@ -192,7 +192,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R2];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -450,23 +450,23 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
# ifndef CONFIG_DEBUG_SVCALL
|
||||
if (cmd > SYS_switch_context)
|
||||
# else
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
# endif
|
||||
{
|
||||
svcinfo("SVCall Return:\n");
|
||||
svcinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
CURRENT_REGS[REG_R0], CURRENT_REGS[REG_R1],
|
||||
CURRENT_REGS[REG_R2], CURRENT_REGS[REG_R3],
|
||||
CURRENT_REGS[REG_R4], CURRENT_REGS[REG_R5],
|
||||
CURRENT_REGS[REG_R6], CURRENT_REGS[REG_R7]);
|
||||
up_current_regs()[REG_R0], up_current_regs()[REG_R1],
|
||||
up_current_regs()[REG_R2], up_current_regs()[REG_R3],
|
||||
up_current_regs()[REG_R4], up_current_regs()[REG_R5],
|
||||
up_current_regs()[REG_R6], up_current_regs()[REG_R7]);
|
||||
svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
CURRENT_REGS[REG_R8], CURRENT_REGS[REG_R9],
|
||||
CURRENT_REGS[REG_R10], CURRENT_REGS[REG_R11],
|
||||
CURRENT_REGS[REG_R12], CURRENT_REGS[REG_R13],
|
||||
CURRENT_REGS[REG_R14], CURRENT_REGS[REG_R15]);
|
||||
up_current_regs()[REG_R8], up_current_regs()[REG_R9],
|
||||
up_current_regs()[REG_R10], up_current_regs()[REG_R11],
|
||||
up_current_regs()[REG_R12], up_current_regs()[REG_R13],
|
||||
up_current_regs()[REG_R14], up_current_regs()[REG_R15]);
|
||||
svcinfo(" PSR: %08x PRIMASK: %08x EXC_RETURN: %08x\n",
|
||||
CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_PRIMASK],
|
||||
CURRENT_REGS[REG_EXC_RETURN]);
|
||||
up_current_regs()[REG_XPSR], up_current_regs()[REG_PRIMASK],
|
||||
up_current_regs()[REG_EXC_RETURN]);
|
||||
}
|
||||
# ifdef CONFIG_DEBUG_SVCALL
|
||||
else
|
||||
@ -476,7 +476,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
restore_critical_section(this_task(), this_cpu());
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ int up_cpu_paused_save(void)
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
|
@ -70,12 +70,12 @@ uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
|
||||
struct tcb_s *tcb = this_task();
|
||||
uint32_t *savestate;
|
||||
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
savestate = (uint32_t *)CURRENT_REGS;
|
||||
CURRENT_REGS = regs;
|
||||
savestate = up_current_regs();
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* In the NuttX on-demand paging implementation, only the read-only, .text
|
||||
* section is paged. However, the ARM compiler generated PC-relative data
|
||||
@ -129,12 +129,12 @@ uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
|
||||
|
||||
pg_miss();
|
||||
|
||||
/* Restore the previous value of CURRENT_REGS. NULL would indicate that
|
||||
/* Restore the previous value of current_regs. NULL would indicate that
|
||||
* we are no longer in an interrupt handler. It will be non-NULL if we
|
||||
* are returning from a nested interrupt.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = savestate;
|
||||
up_set_current_regs(savestate);
|
||||
return regs;
|
||||
|
||||
segfault:
|
||||
@ -148,11 +148,11 @@ segfault:
|
||||
|
||||
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Crash -- possibly showing diagnostic debug information. */
|
||||
|
||||
|
@ -59,13 +59,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
#else
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
@ -73,7 +73,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Make sure that the address environment for the previously
|
||||
@ -91,15 +91,14 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
#endif
|
||||
|
||||
board_autoled_off(LED_INIRQ);
|
||||
|
@ -56,12 +56,12 @@ uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
|
||||
{
|
||||
uint32_t *savestate;
|
||||
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
savestate = (uint32_t *)CURRENT_REGS;
|
||||
CURRENT_REGS = regs;
|
||||
savestate = up_current_regs();
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Get the (virtual) address of instruction that caused the prefetch
|
||||
* abort. When the exception occurred, this address was provided in the
|
||||
@ -100,12 +100,12 @@ uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
|
||||
|
||||
pg_miss();
|
||||
|
||||
/* Restore the previous value of CURRENT_REGS.
|
||||
/* Restore the previous value of current_regs.
|
||||
* NULL would indicate thatwe are no longer in an interrupt handler.
|
||||
* It will be non-NULL if we are returning from a nested interrupt.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = savestate;
|
||||
up_set_current_regs(savestate);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -121,11 +121,11 @@ uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
|
||||
|
||||
uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Crash -- possibly showing diagnostic debug information. */
|
||||
|
||||
|
@ -92,7 +92,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to task that is currently executing on this CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -100,7 +100,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
@ -118,7 +118,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signaling itself, but a context switch
|
||||
* to another task has occurred so that CURRENT_REGS does not
|
||||
* to another task has occurred so that current_regs does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
@ -140,24 +140,23 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -223,7 +222,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
@ -234,7 +233,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !CURRENT_REGS)
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
@ -321,25 +320,23 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -169,13 +169,13 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* The SYSCALL command is in R0 on entry. Parameters follow in R1..R7 */
|
||||
|
||||
@ -272,8 +272,8 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
* set will determine the restored context.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R1];
|
||||
DEBUGASSERT(CURRENT_REGS);
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
DEBUGASSERT(up_current_regs());
|
||||
}
|
||||
break;
|
||||
|
||||
@ -298,7 +298,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R2];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -567,12 +567,12 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* CURRENT_REGS will have a different value than it did on entry. If an
|
||||
* current_regs will have a different value than it did on entry. If an
|
||||
* interrupt level context switch has occurred, then establish the correct
|
||||
* address environment before returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Make sure that the address environment for the previously
|
||||
* running task is closed down gracefully (data caches dump,
|
||||
@ -586,7 +586,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task. g_running_tasks[] is only used by
|
||||
* assertion logic for reporting crashes.
|
||||
@ -599,18 +599,18 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
/* Restore the cpu lock */
|
||||
|
||||
restore_critical_section(tcb, cpu);
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Report what happened */
|
||||
|
||||
dump_syscall("Exit", cmd, regs);
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
/* Return the last value of curent_regs. This supports context switches
|
||||
* on return from the exception. That capability is only used with the
|
||||
|
@ -43,7 +43,8 @@
|
||||
uint32_t *arm_undefinedinsn(uint32_t *regs)
|
||||
{
|
||||
_alert("Undefined instruction at 0x%" PRIx32 "\n", regs[REG_PC]);
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
PANIC_WITH_REGS("panic", regs);
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
|
||||
if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
|
||||
{
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
@ -61,7 +61,7 @@ uint32_t *arm_doirq(int irq, uint32_t *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
|
||||
* 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.
|
||||
*/
|
||||
@ -70,7 +70,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
@ -78,13 +78,12 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Update the CURRENT_REGS to NULL. */
|
||||
/* Update the current_regs to NULL. */
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -95,7 +95,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -103,7 +103,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handle will run in a critical section!
|
||||
@ -138,31 +138,31 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||
CURRENT_REGS[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
up_current_regs()[REG_BASEPRI] =
|
||||
NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
CURRENT_REGS[REG_PRIMASK] = 1;
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
CURRENT_REGS[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
up_current_regs()[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD;
|
||||
CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -235,7 +235,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
@ -246,7 +246,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !CURRENT_REGS)
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
@ -339,30 +339,30 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||
CURRENT_REGS[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
up_current_regs()[REG_BASEPRI] =
|
||||
NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
CURRENT_REGS[REG_PRIMASK] = 1;
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
CURRENT_REGS[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
up_current_regs()[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD;
|
||||
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
uint32_t *regs = (uint32_t *)context;
|
||||
uint32_t cmd;
|
||||
|
||||
DEBUGASSERT(regs && regs == CURRENT_REGS);
|
||||
DEBUGASSERT(regs && regs == up_current_regs());
|
||||
cmd = regs[REG_R0];
|
||||
|
||||
/* The SVCall software interrupt is called with R0 = system call command
|
||||
@ -166,9 +166,9 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
* R0 = SYS_restore_context
|
||||
* R1 = restoreregs
|
||||
*
|
||||
* In this case, we simply need to set CURRENT_REGS to restore
|
||||
* register area referenced in the saved R1. context == CURRENT_REGS
|
||||
* is the normal exception return. By setting CURRENT_REGS =
|
||||
* In this case, we simply need to set current_regs to restore
|
||||
* register area referenced in the saved R1. context == current_regs
|
||||
* is the normal exception return. By setting current_regs =
|
||||
* context[R1], we force the return to the saved context referenced
|
||||
* in R1.
|
||||
*/
|
||||
@ -176,7 +176,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
case SYS_restore_context:
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0);
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R1];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -193,7 +193,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
*
|
||||
* In this case, we do both: We save the context registers to the save
|
||||
* register area reference by the saved contents of R1 and then set
|
||||
* CURRENT_REGS to the save register area referenced by the saved
|
||||
* current_regs to the save register area referenced by the saved
|
||||
* contents of R2.
|
||||
*/
|
||||
|
||||
@ -201,7 +201,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R2];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -459,23 +459,24 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
# ifndef CONFIG_DEBUG_SVCALL
|
||||
if (cmd > SYS_switch_context)
|
||||
# else
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
# endif
|
||||
{
|
||||
svcinfo("SVCall Return:\n");
|
||||
svcinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
CURRENT_REGS[REG_R0], CURRENT_REGS[REG_R1],
|
||||
CURRENT_REGS[REG_R2], CURRENT_REGS[REG_R3],
|
||||
CURRENT_REGS[REG_R4], CURRENT_REGS[REG_R5],
|
||||
CURRENT_REGS[REG_R6], CURRENT_REGS[REG_R7]);
|
||||
up_current_regs()[REG_R0], up_current_regs()[REG_R1],
|
||||
up_current_regs()[REG_R2], up_current_regs()[REG_R3],
|
||||
up_current_regs()[REG_R4], up_current_regs()[REG_R5],
|
||||
up_current_regs()[REG_R6], up_current_regs()[REG_R7]);
|
||||
svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
CURRENT_REGS[REG_R8], CURRENT_REGS[REG_R9],
|
||||
CURRENT_REGS[REG_R10], CURRENT_REGS[REG_R11],
|
||||
CURRENT_REGS[REG_R12], CURRENT_REGS[REG_R13],
|
||||
CURRENT_REGS[REG_R14], CURRENT_REGS[REG_R15]);
|
||||
up_current_regs()[REG_R8], up_current_regs()[REG_R9],
|
||||
up_current_regs()[REG_R10], up_current_regs()[REG_R11],
|
||||
up_current_regs()[REG_R12], up_current_regs()[REG_R13],
|
||||
up_current_regs()[REG_R14], up_current_regs()[REG_R15]);
|
||||
svcinfo(" PSR: %08x EXC_RETURN: %08x, CONTROL: %08x\n",
|
||||
CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_EXC_RETURN],
|
||||
CURRENT_REGS[REG_CONTROL]);
|
||||
up_current_regs()[REG_XPSR],
|
||||
up_current_regs()[REG_EXC_RETURN],
|
||||
up_current_regs()[REG_CONTROL]);
|
||||
}
|
||||
# ifdef CONFIG_DEBUG_SVCALL
|
||||
else
|
||||
@ -485,7 +486,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
restore_critical_section(this_task(), this_cpu());
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ int up_cpu_paused_save(void)
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
|
@ -53,11 +53,11 @@
|
||||
|
||||
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Crash -- possibly showing diagnostic debug information. */
|
||||
|
||||
|
@ -48,13 +48,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
#else
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
@ -62,7 +62,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
@ -70,15 +70,14 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
board_autoled_off(LED_INIRQ);
|
||||
#endif
|
||||
|
@ -49,11 +49,11 @@
|
||||
|
||||
uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Crash -- possibly showing diagnostic debug information. */
|
||||
|
||||
|
@ -90,7 +90,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -98,7 +98,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
@ -114,7 +114,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signalling itself, but a context switch
|
||||
* to another task has occurred so that CURRENT_REGS does not
|
||||
* to another task has occurred so that current_regs does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
@ -136,28 +136,26 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_E_BIT;
|
||||
up_current_regs()[REG_CPSR] |= PSR_E_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -226,7 +224,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
@ -237,7 +235,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !CURRENT_REGS)
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
@ -324,25 +322,23 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -165,13 +165,13 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* The SYSCALL command is in R0 on entry. Parameters follow in R1..R7 */
|
||||
|
||||
@ -268,8 +268,8 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
* set will determine the restored context.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R1];
|
||||
DEBUGASSERT(CURRENT_REGS);
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
DEBUGASSERT(up_current_regs());
|
||||
}
|
||||
break;
|
||||
|
||||
@ -294,7 +294,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R2];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -563,7 +563,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task. g_running_tasks[] is only used by
|
||||
* assertion logic for reporting crashes.
|
||||
@ -576,18 +576,18 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
/* Restore the cpu lock */
|
||||
|
||||
restore_critical_section(tcb, cpu);
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Report what happened */
|
||||
|
||||
dump_syscall("Exit", cmd, regs);
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
/* Return the last value of curent_regs. This supports context switches
|
||||
* on return from the exception. That capability is only used with the
|
||||
|
@ -43,7 +43,8 @@
|
||||
uint32_t *arm_undefinedinsn(uint32_t *regs)
|
||||
{
|
||||
_alert("Undefined instruction at 0x%" PRIx32 "\n", regs[REG_PC]);
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
PANIC_WITH_REGS("panic", regs);
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
|
||||
if (arm_from_thread(regs[REG_EXC_RETURN]))
|
||||
{
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
@ -110,7 +110,7 @@ uint32_t *arm_doirq(int irq, uint32_t *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
|
||||
* 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.
|
||||
*/
|
||||
@ -119,7 +119,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
@ -127,13 +127,12 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Update the CURRENT_REGS to NULL. */
|
||||
/* Update the current_regs to NULL. */
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -95,7 +95,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -103,7 +103,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handle will run in a critical section!
|
||||
@ -138,31 +138,31 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV8M_USEBASEPRI
|
||||
CURRENT_REGS[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
up_current_regs()[REG_BASEPRI] =
|
||||
NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
CURRENT_REGS[REG_PRIMASK] = 1;
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
CURRENT_REGS[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
up_current_regs()[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD;
|
||||
CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -235,7 +235,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
@ -246,7 +246,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !CURRENT_REGS)
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
@ -339,30 +339,30 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV8M_USEBASEPRI
|
||||
CURRENT_REGS[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
up_current_regs()[REG_BASEPRI] =
|
||||
NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
CURRENT_REGS[REG_PRIMASK] = 1;
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
CURRENT_REGS[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
up_current_regs()[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
CURRENT_REGS[REG_LR] = EXC_RETURN_THREAD;
|
||||
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
uint32_t *regs = (uint32_t *)context;
|
||||
uint32_t cmd;
|
||||
|
||||
DEBUGASSERT(regs && regs == CURRENT_REGS);
|
||||
DEBUGASSERT(regs && regs == up_current_regs());
|
||||
cmd = regs[REG_R0];
|
||||
|
||||
/* The SVCall software interrupt is called with R0 = system call command
|
||||
@ -165,9 +165,9 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
* R0 = SYS_restore_context
|
||||
* R1 = restoreregs
|
||||
*
|
||||
* In this case, we simply need to set CURRENT_REGS to restore
|
||||
* register area referenced in the saved R1. context == CURRENT_REGS
|
||||
* is the normal exception return. By setting CURRENT_REGS =
|
||||
* In this case, we simply need to set current_regs to restore
|
||||
* register area referenced in the saved R1. context == current_regs
|
||||
* is the normal exception return. By setting current_regs =
|
||||
* context[R1], we force the return to the saved context referenced
|
||||
* in R1.
|
||||
*/
|
||||
@ -175,7 +175,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
case SYS_restore_context:
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0);
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R1];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -192,7 +192,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
*
|
||||
* In this case, we do both: We save the context registers to the save
|
||||
* register area reference by the saved contents of R1 and then set
|
||||
* CURRENT_REGS to the save register area referenced by the saved
|
||||
* current_regs to the save register area referenced by the saved
|
||||
* contents of R2.
|
||||
*/
|
||||
|
||||
@ -200,7 +200,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R2];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -460,23 +460,24 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
# ifndef CONFIG_DEBUG_SVCALL
|
||||
if (cmd > SYS_switch_context)
|
||||
# else
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
# endif
|
||||
{
|
||||
svcinfo("SVCall Return:\n");
|
||||
svcinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
CURRENT_REGS[REG_R0], CURRENT_REGS[REG_R1],
|
||||
CURRENT_REGS[REG_R2], CURRENT_REGS[REG_R3],
|
||||
CURRENT_REGS[REG_R4], CURRENT_REGS[REG_R5],
|
||||
CURRENT_REGS[REG_R6], CURRENT_REGS[REG_R7]);
|
||||
up_current_regs()[REG_R0], up_current_regs()[REG_R1],
|
||||
up_current_regs()[REG_R2], up_current_regs()[REG_R3],
|
||||
up_current_regs()[REG_R4], up_current_regs()[REG_R5],
|
||||
up_current_regs()[REG_R6], up_current_regs()[REG_R7]);
|
||||
svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
CURRENT_REGS[REG_R8], CURRENT_REGS[REG_R9],
|
||||
CURRENT_REGS[REG_R10], CURRENT_REGS[REG_R11],
|
||||
CURRENT_REGS[REG_R12], CURRENT_REGS[REG_R13],
|
||||
CURRENT_REGS[REG_R14], CURRENT_REGS[REG_R15]);
|
||||
up_current_regs()[REG_R8], up_current_regs()[REG_R9],
|
||||
up_current_regs()[REG_R10], up_current_regs()[REG_R11],
|
||||
up_current_regs()[REG_R12], up_current_regs()[REG_R13],
|
||||
up_current_regs()[REG_R14], up_current_regs()[REG_R15]);
|
||||
svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n",
|
||||
CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_EXC_RETURN],
|
||||
CURRENT_REGS[REG_CONTROL]);
|
||||
up_current_regs()[REG_XPSR],
|
||||
up_current_regs()[REG_EXC_RETURN],
|
||||
up_current_regs()[REG_CONTROL]);
|
||||
}
|
||||
# ifdef CONFIG_DEBUG_SVCALL
|
||||
else
|
||||
@ -486,7 +487,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
restore_critical_section(this_task(), this_cpu());
|
||||
}
|
||||
|
@ -53,11 +53,11 @@
|
||||
|
||||
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Crash -- possibly showing diagnostic debug information. */
|
||||
|
||||
|
@ -49,13 +49,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
#else
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
@ -63,7 +63,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
@ -71,14 +71,14 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
board_autoled_off(LED_INIRQ);
|
||||
#endif
|
||||
|
@ -49,11 +49,11 @@
|
||||
|
||||
uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Crash -- possibly showing diagnostic debug information. */
|
||||
|
||||
|
@ -90,7 +90,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -98,7 +98,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
@ -114,7 +114,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signalling itself, but a context switch
|
||||
* to another task has occurred so that CURRENT_REGS does not
|
||||
* to another task has occurred so that current_regs does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
@ -136,28 +136,26 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_E_BIT;
|
||||
up_current_regs()[REG_CPSR] |= PSR_E_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -226,7 +224,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
@ -237,7 +235,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !CURRENT_REGS)
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
@ -324,25 +322,23 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -165,13 +165,13 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* The SYSCALL command is in R0 on entry. Parameters follow in R1..R7 */
|
||||
|
||||
@ -268,8 +268,8 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
* set will determine the restored context.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R1];
|
||||
DEBUGASSERT(CURRENT_REGS);
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
DEBUGASSERT(up_current_regs());
|
||||
}
|
||||
break;
|
||||
|
||||
@ -294,7 +294,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_R2];
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -563,7 +563,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task. g_running_tasks[] is only used by
|
||||
* assertion logic for reporting crashes.
|
||||
@ -576,18 +576,18 @@ uint32_t *arm_syscall(uint32_t *regs)
|
||||
/* Restore the cpu lock */
|
||||
|
||||
restore_critical_section(tcb, cpu);
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Report what happened */
|
||||
|
||||
dump_syscall("Exit", cmd, regs);
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
/* Return the last value of curent_regs. This supports context switches
|
||||
* on return from the exception. That capability is only used with the
|
||||
|
@ -43,7 +43,8 @@
|
||||
uint32_t *arm_undefinedinsn(uint32_t *regs)
|
||||
{
|
||||
_alert("Undefined instruction at 0x%" PRIx32 "\n", regs[REG_PC]);
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
PANIC_WITH_REGS("panic", regs);
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
|
@ -141,8 +141,8 @@ int up_backtrace(struct tcb_s *tcb,
|
||||
{
|
||||
ret += backtrace(rtcb->stack_base_ptr,
|
||||
rtcb->stack_base_ptr + rtcb->adj_stack_size,
|
||||
(void *)CURRENT_REGS[REG_FP],
|
||||
(void *)CURRENT_REGS[REG_PC],
|
||||
(void *)up_current_regs()[REG_FP],
|
||||
(void *)up_current_regs()[REG_PC],
|
||||
&buffer[ret], size - ret, &skip);
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ int up_backtrace(struct tcb_s *tcb,
|
||||
ret += backtrace_branch((unsigned long)
|
||||
rtcb->stack_base_ptr +
|
||||
rtcb->adj_stack_size,
|
||||
CURRENT_REGS[REG_SP],
|
||||
up_current_regs()[REG_SP],
|
||||
&buffer[ret],
|
||||
size - ret, &skip);
|
||||
}
|
||||
|
@ -743,10 +743,10 @@ int up_backtrace(struct tcb_s *tcb,
|
||||
ret = backtrace_unwind(&frame, buffer, size, &skip);
|
||||
if (ret < size)
|
||||
{
|
||||
frame.fp = CURRENT_REGS[REG_FP];
|
||||
frame.sp = CURRENT_REGS[REG_SP];
|
||||
frame.pc = CURRENT_REGS[REG_PC];
|
||||
frame.lr = CURRENT_REGS[REG_LR];
|
||||
frame.fp = up_current_regs()[REG_FP];
|
||||
frame.sp = up_current_regs()[REG_SP];
|
||||
frame.pc = up_current_regs()[REG_PC];
|
||||
frame.lr = up_current_regs()[REG_LR];
|
||||
frame.stack_base = (unsigned long)rtcb->stack_base_ptr;
|
||||
frame.stack_top = frame.stack_base + rtcb->adj_stack_size;
|
||||
ret += backtrace_unwind(&frame, &buffer[ret],
|
||||
|
@ -33,9 +33,9 @@
|
||||
****************************************************************************/
|
||||
|
||||
/* g_current_regs[] holds a references to the current interrupt level
|
||||
* register storage structure. It is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the macro
|
||||
* CURRENT_REGS for portability.
|
||||
* register storage structure. If is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the
|
||||
* [get/set]_current_regs for portability.
|
||||
*/
|
||||
|
||||
volatile uint32_t *g_current_regs[CONFIG_SMP_NCPUS];
|
||||
|
@ -98,8 +98,8 @@
|
||||
|
||||
/* Macros to handle saving and restoring interrupt state. */
|
||||
|
||||
#define arm_savestate(regs) (regs = (uint32_t *)CURRENT_REGS)
|
||||
#define arm_restorestate(regs) (CURRENT_REGS = regs)
|
||||
#define arm_savestate(regs) (regs = up_current_regs())
|
||||
#define arm_restorestate(regs) up_set_current_regs(regs)
|
||||
|
||||
/* Toolchain dependent, linker defined section addresses */
|
||||
|
||||
|
@ -57,7 +57,7 @@ uintptr_t up_getusrsp(void *regs)
|
||||
|
||||
void up_dump_register(void *dumpregs)
|
||||
{
|
||||
volatile uint32_t *regs = dumpregs ? dumpregs : CURRENT_REGS;
|
||||
volatile uint32_t *regs = dumpregs ? dumpregs : up_current_regs();
|
||||
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
|
@ -61,10 +61,10 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||
|
||||
/* Are we in an interrupt handler? */
|
||||
|
||||
if (CURRENT_REGS)
|
||||
if (up_current_regs())
|
||||
{
|
||||
/* Yes, then we have to do things differently.
|
||||
* Just copy the CURRENT_REGS into the OLD rtcb.
|
||||
* Just copy the current_regs into the OLD rtcb.
|
||||
*/
|
||||
|
||||
arm_savestate(rtcb->xcp.regs);
|
||||
|
@ -199,7 +199,7 @@ int up_cpu_paused_save(void)
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
{
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
err("ERROR: Unexpected IRQ\n");
|
||||
PANIC();
|
||||
return NULL;
|
||||
@ -71,14 +71,14 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an
|
||||
* interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context
|
||||
* current_regs is also used to manage interrupt level context
|
||||
* switches.
|
||||
*
|
||||
* Nested interrupts are not supported.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
CURRENT_REGS = regs;
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
@ -86,13 +86,13 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* CURRENT_REGS will have a different value than it did on entry.
|
||||
* current_regs will have a different value than it did on entry.
|
||||
* If an interrupt level context switch has occurred, then
|
||||
* establish the correct address environment before returning
|
||||
* from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Make sure that the address environment for the previously
|
||||
* running task is closed down gracefully (data caches dump,
|
||||
@ -104,11 +104,11 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in
|
||||
/* Set current_regs to NULL to indicate that we are no longer in
|
||||
* an interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -58,7 +58,7 @@
|
||||
uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
{
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
err("ERROR: Unexpected IRQ\n");
|
||||
PANIC();
|
||||
return NULL;
|
||||
@ -67,13 +67,13 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
int irq;
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*
|
||||
* Nested interrupts are not supported.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
CURRENT_REGS = regs;
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Loop while there are pending interrupts to be processed */
|
||||
|
||||
@ -102,13 +102,13 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* CURRENT_REGS will have a different value than it did on entry.
|
||||
* current_regs will have a different value than it did on entry.
|
||||
* If an interrupt level context switch has occurred, then
|
||||
* establish the correct address environment before returning
|
||||
* from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Make sure that the address environment for the previously
|
||||
* running task is closed down gracefully (data caches dump,
|
||||
@ -123,11 +123,11 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
}
|
||||
while (irq < NR_IRQS);
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in
|
||||
/* Set current_regs to NULL to indicate that we are no longer in
|
||||
* an interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
return NULL; /* Return not used in this architecture */
|
||||
#endif
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ int up_cpu_paused_save(void)
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
|
@ -82,7 +82,7 @@ static uint32_t *lpc214x_decodeirq(uint32_t *regs)
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
err("ERROR: Unexpected IRQ\n");
|
||||
PANIC();
|
||||
return NULL;
|
||||
@ -119,23 +119,23 @@ static uint32_t *lpc214x_decodeirq(uint32_t *regs)
|
||||
uint32_t *savestate;
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context
|
||||
* current_regs is also used to manage interrupt level context
|
||||
* switches.
|
||||
*/
|
||||
|
||||
savestate = (uint32_t *)CURRENT_REGS;
|
||||
CURRENT_REGS = regs;
|
||||
savestate = up_current_regs();
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
|
||||
/* Restore the previous value of CURRENT_REGS. NULL would indicate
|
||||
/* Restore the previous value of current_regs. NULL would indicate
|
||||
* that we are no longer in an interrupt handler. It will be non-NULL
|
||||
* if we are returning from a nested interrupt.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = savestate;
|
||||
up_set_current_regs(savestate);
|
||||
}
|
||||
|
||||
return NULL; /* Return not used in this architecture */
|
||||
|
@ -93,7 +93,7 @@ static uint32_t *lpc23xx_decodeirq(uint32_t *regs)
|
||||
{
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
err("ERROR: Unexpected IRQ\n");
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
PANIC();
|
||||
return NULL;
|
||||
#else
|
||||
@ -118,12 +118,12 @@ static uint32_t *lpc23xx_decodeirq(uint32_t *regs)
|
||||
uint32_t *savestate;
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an
|
||||
* interrupt; CURRENT_REGS is also used to manage interrupt level
|
||||
* interrupt; current_regs is also used to manage interrupt level
|
||||
* context switches.
|
||||
*/
|
||||
|
||||
savestate = (uint32_t *)CURRENT_REGS;
|
||||
CURRENT_REGS = regs;
|
||||
savestate = up_current_regs();
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
|
||||
@ -133,12 +133,12 @@ static uint32_t *lpc23xx_decodeirq(uint32_t *regs)
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
|
||||
/* Restore the previous value of CURRENT_REGS.
|
||||
/* Restore the previous value of current_regs.
|
||||
* NULL would indicate that we are no longer in an interrupt handler.
|
||||
* It will be non-NULL if we are returning from a nested interrupt.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = savestate;
|
||||
up_set_current_regs(savestate);
|
||||
}
|
||||
|
||||
return NULL; /* Return not used in this architecture */
|
||||
|
@ -44,7 +44,7 @@
|
||||
uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
{
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
err("ERROR: Unexpected IRQ\n");
|
||||
PANIC();
|
||||
return NULL;
|
||||
@ -76,14 +76,14 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
arm_ack_irq(irq);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an
|
||||
* interrupt; CURRENT_REGS is also used to manage interrupt level
|
||||
* interrupt; current_regs is also used to manage interrupt level
|
||||
* context switches.
|
||||
*
|
||||
* Nested interrupts are not supported.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
CURRENT_REGS = regs;
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
@ -91,13 +91,13 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* CURRENT_REGS will have a different value than it did on entry.
|
||||
* current_regs will have a different value than it did on entry.
|
||||
* If an interrupt level context switch has occurred, then
|
||||
* establish the correct address environment before returning
|
||||
* from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Make sure that the address environment for the previously
|
||||
* running task is closed down gracefully (data caches dump,
|
||||
@ -109,11 +109,11 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,11 +276,11 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
num = ffs(status) - 1;
|
||||
arm_ack_irq(num);
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
CURRENT_REGS = regs;
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
irq_dispatch(num, regs);
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
return NULL; /* Return not used in this architecture */
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ int up_cpu_paused_save(void)
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
|
@ -129,7 +129,7 @@ int up_cpu_paused_save(void)
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
|
@ -55,7 +55,7 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
{
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
board_autoled_on(LED_INIRQ);
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
err("ERROR: Unexpected IRQ\n");
|
||||
PANIC();
|
||||
return NULL;
|
||||
@ -76,12 +76,12 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
uint32_t *savestate;
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an
|
||||
* interrupt; CURRENT_REGS is also used to manage interrupt level
|
||||
* interrupt; current_regs is also used to manage interrupt level
|
||||
* context switches.
|
||||
*/
|
||||
|
||||
savestate = (uint32_t *)CURRENT_REGS;
|
||||
CURRENT_REGS = regs;
|
||||
savestate = up_current_regs();
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
|
||||
@ -91,12 +91,12 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
|
||||
/* Restore the previous value of CURRENT_REGS.
|
||||
/* Restore the previous value of current_regs.
|
||||
* NULL would indicate that we are no longer in an interrupt handler.
|
||||
* It will be non-NULL if we are returning from a nested interrupt.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = savestate;
|
||||
up_set_current_regs(savestate);
|
||||
}
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
else
|
||||
|
@ -494,10 +494,10 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size, int skip)
|
||||
#endif
|
||||
if (ret < size)
|
||||
{
|
||||
sp = (void *)CURRENT_REGS[REG_SP];
|
||||
sp = up_current_regs()[REG_SP];
|
||||
ret += backtrace_push(rtcb->stack_base_ptr +
|
||||
rtcb->adj_stack_size, &sp,
|
||||
(void *)CURRENT_REGS[REG_PC],
|
||||
(void *)up_current_regs()[REG_PC],
|
||||
&buffer[ret], size - ret, &skip);
|
||||
}
|
||||
}
|
||||
|
@ -64,17 +64,17 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
|
||||
/* 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
|
||||
* 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.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
if (CURRENT_REGS == NULL)
|
||||
if (up_current_regs() == NULL)
|
||||
{
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
regs = NULL;
|
||||
}
|
||||
|
||||
@ -84,10 +84,10 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
irq_dispatch(irq, (uint32_t *)CURRENT_REGS);
|
||||
irq_dispatch(irq, up_current_regs());
|
||||
|
||||
/* If a context switch occurred while processing the interrupt then
|
||||
* CURRENT_REGS may have change value. If we return any value different
|
||||
* 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.
|
||||
*/
|
||||
@ -96,14 +96,14 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Update the CURRENT_REGS to NULL. */
|
||||
/* Update the current_regs to NULL. */
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -89,7 +89,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -97,7 +97,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* a task is signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
@ -114,7 +114,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* logic would fail in the strange case where we are in an
|
||||
* interrupt handler, the thread is signalling itself, but
|
||||
* a context switch to another task has occurred so that
|
||||
* CURRENT_REGS does not refer to the thread of this_task()!
|
||||
* current_regs does not refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
else
|
||||
@ -135,21 +135,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_LR] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
|
||||
CURRENT_REGS[REG_IRQ_EN] = 0;
|
||||
up_current_regs()[REG_LR] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT;
|
||||
up_current_regs()[REG_IRQ_EN] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,6 @@
|
||||
void arm_syscall(uint32_t *regs)
|
||||
{
|
||||
_alert("Syscall from 0x%" PRIx32 "\n", regs[REG_PC]);
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
PANIC();
|
||||
}
|
||||
|
@ -146,15 +146,16 @@ int tms570_esm_initialize(void)
|
||||
|
||||
int tms570_esm_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
/* Save the saved processor context in current_regs where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (uint32_t *)context;
|
||||
up_set_current_regs((uint32_t *)context);
|
||||
|
||||
/* Crash -- possibly showing diagnostic debug information. */
|
||||
|
||||
_err("ERROR: ESM Interrupt. PC: %08" PRIx32 "\n", CURRENT_REGS[REG_PC]);
|
||||
_err("ERROR: ESM Interrupt. PC: %08" PRIx32 "\n",
|
||||
up_current_regs()[REG_PC]);
|
||||
PANIC();
|
||||
return OK; /* To keep the compiler happy */
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ extern "C"
|
||||
/* g_current_regs[] holds a references to the current interrupt level
|
||||
* register storage structure. It is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the macro
|
||||
* CURRENT_REGS for portability.
|
||||
* current_regs for portability.
|
||||
*/
|
||||
|
||||
/* For the case of architectures with multiple CPUs, then there must be one
|
||||
@ -253,7 +253,6 @@ extern "C"
|
||||
*/
|
||||
|
||||
EXTERN volatile uint64_t *g_current_regs[CONFIG_SMP_NCPUS];
|
||||
#define CURRENT_REGS (g_current_regs[up_cpu_index()])
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
@ -419,6 +418,16 @@ static inline void up_irq_restore(irqstate_t flags)
|
||||
# define up_cpu_index() (0)
|
||||
#endif
|
||||
|
||||
static inline_function uint64_t *up_current_regs(void)
|
||||
{
|
||||
return (uint64_t *)g_current_regs[up_cpu_index()];
|
||||
}
|
||||
|
||||
static inline_function void up_set_current_regs(uint64_t *regs)
|
||||
{
|
||||
g_current_regs[up_cpu_index()] = regs;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_interrupt_context
|
||||
*
|
||||
@ -433,7 +442,7 @@ static inline bool up_interrupt_context(void)
|
||||
irqstate_t flags = up_irq_save();
|
||||
#endif
|
||||
|
||||
bool ret = (CURRENT_REGS != NULL);
|
||||
bool ret = (up_current_regs() != NULL);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
up_irq_restore(flags);
|
||||
|
@ -147,7 +147,7 @@ int up_backtrace(struct tcb_s *tcb,
|
||||
#endif /* CONFIG_ARCH_INTERRUPTSTACK > 7 */
|
||||
if (ret < size)
|
||||
{
|
||||
p_regs = (struct regs_context *)CURRENT_REGS;
|
||||
p_regs = (struct regs_context *)up_current_regs();
|
||||
ret += backtrace(rtcb->stack_base_ptr,
|
||||
rtcb->stack_base_ptr + rtcb->adj_stack_size,
|
||||
(void *)p_regs->regs[REG_X29],
|
||||
|
@ -116,7 +116,7 @@ int up_cpu_paused_save(void)
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at CURRENT_REGS into the TCB at the head
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
|
@ -59,26 +59,26 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
|
||||
{
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* CURRENT_REGS will have a different value than it did on entry. If an
|
||||
* current_regs will have a different value than it did on entry. If an
|
||||
* interrupt level context switch has occurred, then restore the floating
|
||||
* point state and the establish the correct address environment before
|
||||
* returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* need to do a context switch */
|
||||
|
||||
@ -98,15 +98,14 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
|
||||
regs = (uint64_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
return regs;
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ void arm64_fatal_error(unsigned int reason, struct regs_context * reg)
|
||||
|
||||
sinfo("reason = %d\n", reason);
|
||||
|
||||
CURRENT_REGS = (uint64_t *)reg;
|
||||
up_set_current_regs((uint64_t *)reg);
|
||||
|
||||
if (reason != K_ERR_SPURIOUS_IRQ)
|
||||
{
|
||||
|
@ -53,7 +53,7 @@
|
||||
/* g_current_regs[] holds a references to the current interrupt level
|
||||
* register storage structure. It is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the macro
|
||||
* CURRENT_REGS for portability.
|
||||
* current_regs for portability.
|
||||
*/
|
||||
|
||||
/* For the case of configurations with multiple CPUs, then there must be one
|
||||
|
@ -88,8 +88,8 @@
|
||||
* floating point registers as well as normal ARM registers.
|
||||
*/
|
||||
|
||||
#define arm64_savestate(regs) (regs = (uint64_t *)CURRENT_REGS)
|
||||
#define arm64_restorestate(regs) (CURRENT_REGS = regs)
|
||||
#define arm64_savestate(regs) (regs = up_current_regs())
|
||||
#define arm64_restorestate(regs) up_set_current_regs(regs)
|
||||
|
||||
/* This is the value used to mark the stack for subsequent stack monitoring
|
||||
* logic.
|
||||
|
@ -60,7 +60,7 @@ uintptr_t up_getusrsp(void *regs)
|
||||
void up_dump_register(void *dumpregs)
|
||||
{
|
||||
volatile struct regs_context *regs = dumpregs ? dumpregs :
|
||||
(struct regs_context *)CURRENT_REGS;
|
||||
(struct regs_context *)up_current_regs();
|
||||
|
||||
_alert("stack = %p\n", regs);
|
||||
_alert("x0: 0x%-16"PRIx64" x1: 0x%"PRIx64"\n",
|
||||
|
@ -146,7 +146,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
@ -164,7 +164,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signaling itself, but a context switch
|
||||
* to another task has occurred so that CURRENT_REGS does not
|
||||
* to another task has occurred so that current_regs does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
@ -177,16 +177,16 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
|
||||
/* create signal process context */
|
||||
|
||||
tcb->xcp.saved_reg = (uint64_t *)CURRENT_REGS;
|
||||
tcb->xcp.saved_reg = up_current_regs();
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
tcb->xcp.saved_fpu_regs = tcb->xcp.fpu_regs;
|
||||
#endif
|
||||
arm64_init_signal_process(tcb,
|
||||
(struct regs_context *)CURRENT_REGS);
|
||||
(struct regs_context *)up_current_regs());
|
||||
|
||||
/* trigger switch to signal process */
|
||||
|
||||
CURRENT_REGS = tcb->xcp.regs;
|
||||
up_set_current_regs(tcb->xcp.regs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
@ -243,7 +243,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !CURRENT_REGS)
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
@ -300,16 +300,16 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
|
||||
/* create signal process context */
|
||||
|
||||
tcb->xcp.saved_reg = (uint64_t *)CURRENT_REGS;
|
||||
tcb->xcp.saved_reg = up_current_regs();
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
tcb->xcp.saved_fpu_regs = tcb->xcp.fpu_regs;
|
||||
#endif
|
||||
arm64_init_signal_process(tcb,
|
||||
(struct regs_context *)CURRENT_REGS);
|
||||
(struct regs_context *)up_current_regs());
|
||||
|
||||
/* trigger switch to signal process */
|
||||
|
||||
CURRENT_REGS = tcb->xcp.regs;
|
||||
up_set_current_regs(tcb->xcp.regs);
|
||||
}
|
||||
|
||||
/* NOTE: If the task runs on another CPU(cpu), adjusting
|
||||
|
@ -61,10 +61,10 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||
|
||||
/* Are we in an interrupt handler? */
|
||||
|
||||
if (CURRENT_REGS)
|
||||
if (up_current_regs())
|
||||
{
|
||||
/* Yes, then we have to do things differently.
|
||||
* Just copy the CURRENT_REGS into the OLD rtcb.
|
||||
* Just copy the current_regs into the OLD rtcb.
|
||||
*/
|
||||
|
||||
arm64_savestate(rtcb->xcp.regs);
|
||||
|
@ -109,6 +109,28 @@ EXTERN volatile uint8_t *g_current_regs;
|
||||
* Inline functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_FAMILY_AVR32
|
||||
static inline_function uint32_t *up_current_regs(void)
|
||||
{
|
||||
return (uint32_t *)g_current_regs;
|
||||
}
|
||||
|
||||
static inline_function void up_set_current_regs(uint32_t *regs)
|
||||
{
|
||||
g_current_regs = regs;
|
||||
}
|
||||
#else
|
||||
static inline_function FAR uint8_t *up_current_regs(void)
|
||||
{
|
||||
return (FAR uint8_t *)g_current_regs;
|
||||
}
|
||||
|
||||
static inline_function void up_set_current_regs(FAR uint8_t *regs)
|
||||
{
|
||||
g_current_regs = regs;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_interrupt_context
|
||||
*
|
||||
@ -118,7 +140,7 @@ EXTERN volatile uint8_t *g_current_regs;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define up_interrupt_context() (g_current_regs != NULL)
|
||||
#define up_interrupt_context() (up_current_regs() != NULL)
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
|
@ -43,8 +43,8 @@
|
||||
* state from the TCB.
|
||||
*/
|
||||
|
||||
#define avr_savestate(regs) avr_copystate(regs, (uint8_t*)g_current_regs)
|
||||
#define avr_restorestate(regs) (g_current_regs = regs)
|
||||
#define avr_savestate(regs) avr_copystate(regs, up_current_regs())
|
||||
#define avr_restorestate(regs) up_set_current_regs(regs)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
|
@ -75,8 +75,8 @@ uint8_t *avr_doirq(uint8_t irq, uint8_t *regs)
|
||||
* g_current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
savestate = (uint8_t *)g_current_regs; /* Cast removes volatile attribute */
|
||||
g_current_regs = regs;
|
||||
savestate = up_current_regs(); /* Cast removes volatile attribute */
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
@ -88,7 +88,7 @@ uint8_t *avr_doirq(uint8_t irq, uint8_t *regs)
|
||||
* switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
if (regs != (uint8_t *)g_current_regs)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
@ -98,14 +98,14 @@ uint8_t *avr_doirq(uint8_t irq, uint8_t *regs)
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
}
|
||||
|
||||
regs = (uint8_t *)g_current_regs; /* Cast removes volatile attribute */
|
||||
regs = up_current_regs(); /* Cast removes volatile attribute */
|
||||
|
||||
/* Restore the previous value of g_current_regs. NULL would indicate that
|
||||
* we are no longer in an interrupt handler. It will be non-NULL if we
|
||||
* are returning from a nested interrupt.
|
||||
*/
|
||||
|
||||
g_current_regs = savestate;
|
||||
up_set_current_regs(savestate);
|
||||
#endif
|
||||
board_autoled_off(LED_INIRQ);
|
||||
return regs;
|
||||
|
@ -54,7 +54,7 @@ uintptr_t up_getusrsp(void *regs)
|
||||
|
||||
void up_dump_register(void *dumpregs)
|
||||
{
|
||||
volatile uint8_t *regs = dumpregs ? dumpregs : g_current_regs;
|
||||
volatile uint8_t *regs = dumpregs ? dumpregs : up_current_regs();
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
|
@ -91,8 +91,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p g_current_regs=%p\n",
|
||||
this_task(), g_current_regs);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -100,7 +99,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* a task is signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!g_current_regs)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
@ -127,26 +126,26 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* trampoline after the signal(s) have been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.saved_pc0 = g_current_regs[REG_PC0];
|
||||
tcb->xcp.saved_pc1 = g_current_regs[REG_PC1];
|
||||
tcb->xcp.saved_pc0 = up_current_regs()[REG_PC0];
|
||||
tcb->xcp.saved_pc1 = up_current_regs()[REG_PC1];
|
||||
#if defined(REG_PC2)
|
||||
tcb->xcp.saved_pc2 = g_current_regs[REG_PC2];
|
||||
tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2];
|
||||
#endif
|
||||
tcb->xcp.saved_sreg = g_current_regs[REG_SREG];
|
||||
tcb->xcp.saved_sreg = up_current_regs()[REG_SREG];
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
#if !defined(REG_PC2)
|
||||
g_current_regs[REG_PC0] = (uint16_t)reg_ptr >> 8;
|
||||
g_current_regs[REG_PC1] = (uint16_t)reg_ptr & 0xff;
|
||||
up_current_regs()[REG_PC0] = (uint16_t)reg_ptr >> 8;
|
||||
up_current_regs()[REG_PC1] = (uint16_t)reg_ptr & 0xff;
|
||||
#else
|
||||
g_current_regs[REG_PC0] = (uint32_t)reg_ptr >> 16;
|
||||
g_current_regs[REG_PC1] = (uint32_t)reg_ptr >> 8;
|
||||
g_current_regs[REG_PC2] = (uint32_t)reg_ptr & 0xff;
|
||||
up_current_regs()[REG_PC0] = (uint32_t)reg_ptr >> 16;
|
||||
up_current_regs()[REG_PC1] = (uint32_t)reg_ptr >> 8;
|
||||
up_current_regs()[REG_PC2] = (uint32_t)reg_ptr & 0xff;
|
||||
#endif
|
||||
g_current_regs[REG_SREG] &= ~(1 << SREG_I);
|
||||
up_current_regs()[REG_SREG] &= ~(1 << SREG_I);
|
||||
|
||||
/* And make sure that the saved context in the TCB
|
||||
* is the same as the interrupt return context.
|
||||
|
@ -60,7 +60,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||
|
||||
/* Are we in an interrupt handler? */
|
||||
|
||||
if (g_current_regs)
|
||||
if (up_current_regs())
|
||||
{
|
||||
/* Yes, then we have to do things differently.
|
||||
* Just copy the g_current_regs into the OLD rtcb.
|
||||
|
@ -53,8 +53,8 @@
|
||||
* state from the TCB.
|
||||
*/
|
||||
|
||||
#define avr_savestate(regs) avr_copystate(regs, (uint32_t*)g_current_regs)
|
||||
#define avr_restorestate(regs) (g_current_regs = regs)
|
||||
#define avr_savestate(regs) avr_copystate(regs, up_current_regs())
|
||||
#define avr_restorestate(regs) up_set_current_regs(regs)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
|
@ -68,8 +68,8 @@ uint32_t *avr_doirq(int irq, uint32_t *regs)
|
||||
* Nested interrupts are not supported.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(g_current_regs == NULL);
|
||||
g_current_regs = regs;
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
@ -82,12 +82,12 @@ uint32_t *avr_doirq(int irq, uint32_t *regs)
|
||||
* environment before returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != g_current_regs)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
/* Restore floating point registers */
|
||||
|
||||
up_restorefpu((uint32_t *)g_current_regs);
|
||||
up_restorefpu(up_current_regs());
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
@ -114,13 +114,13 @@ uint32_t *avr_doirq(int irq, uint32_t *regs)
|
||||
* switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
regs = (uint32_t *)g_current_regs;
|
||||
regs = up_current_regs();
|
||||
|
||||
/* Set g_current_regs to NULL to indicate that we are no longer in
|
||||
* an interrupt handler.
|
||||
*/
|
||||
|
||||
g_current_regs = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
#endif
|
||||
board_autoled_off(LED_INIRQ);
|
||||
return regs;
|
||||
|
@ -54,7 +54,7 @@ uintptr_t up_getusrsp(void *regs)
|
||||
|
||||
void up_dump_register(void *dumpregs)
|
||||
{
|
||||
volatile uint32_t *regs = dumpregs ? dumpregs : g_current_regs;
|
||||
volatile uint32_t *regs = dumpregs ? dumpregs : up_current_regs();
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
|
@ -89,8 +89,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p g_current_regs=%p\n",
|
||||
this_task(), g_current_regs);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -98,7 +97,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* a task is signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!g_current_regs)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
@ -125,15 +124,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* trampoline after the signal(s) have been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.saved_pc = g_current_regs[REG_PC];
|
||||
tcb->xcp.saved_sr = g_current_regs[REG_SR];
|
||||
tcb->xcp.saved_pc = up_current_regs()[REG_PC];
|
||||
tcb->xcp.saved_sr = up_current_regs()[REG_SR];
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
g_current_regs[REG_PC] = (uint32_t)avr_sigdeliver;
|
||||
g_current_regs[REG_SR] |= AVR32_SR_GM_MASK;
|
||||
up_current_regs()[REG_PC] = (uint32_t)avr_sigdeliver;
|
||||
up_current_regs()[REG_SR] |= AVR32_SR_GM_MASK;
|
||||
|
||||
/* And make sure that the saved context in the TCB
|
||||
* is the same as the interrupt return context.
|
||||
|
@ -62,7 +62,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||
|
||||
/* Are we in an interrupt handler? */
|
||||
|
||||
if (g_current_regs)
|
||||
if (up_current_regs())
|
||||
{
|
||||
/* Yes, then we have to do things differently.
|
||||
* Just copy the g_current_regs into the OLD rtcb.
|
||||
|
@ -94,9 +94,9 @@ extern "C"
|
||||
#endif
|
||||
|
||||
/* g_current_regs[] holds a references to the current interrupt level
|
||||
* register storage structure. It is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the macro
|
||||
* CURRENT_REGS for portability.
|
||||
* register storage structure. If is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the
|
||||
* [get/set]_current_regs for portability.
|
||||
*/
|
||||
|
||||
/* For the case of architectures with multiple CPUs, then there must be one
|
||||
@ -104,7 +104,6 @@ extern "C"
|
||||
*/
|
||||
|
||||
EXTERN uint32_t *volatile g_current_regs[CONFIG_SMP_NCPUS];
|
||||
#define CURRENT_REGS (g_current_regs[up_cpu_index()])
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
@ -136,6 +135,16 @@ int up_cpu_index(void);
|
||||
* Inline functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline_function uint32_t *up_current_regs(void)
|
||||
{
|
||||
return (uint32_t *)g_current_regs[up_cpu_index()];
|
||||
}
|
||||
|
||||
static inline_function void up_set_current_regs(uint32_t *regs)
|
||||
{
|
||||
g_current_regs[up_cpu_index()] = regs;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_interrupt_context
|
||||
*
|
||||
@ -150,7 +159,7 @@ static inline bool up_interrupt_context(void)
|
||||
#ifdef CONFIG_SMP
|
||||
irqstate_t flags = up_irq_save();
|
||||
#endif
|
||||
bool ret = CURRENT_REGS != NULL;
|
||||
bool ret = up_current_regs() != NULL;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
up_irq_restore(flags);
|
||||
|
@ -34,9 +34,9 @@
|
||||
****************************************************************************/
|
||||
|
||||
/* g_current_regs[] holds a references to the current interrupt level
|
||||
* register storage structure. It is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the macro
|
||||
* CURRENT_REGS for portability.
|
||||
* register storage structure. If is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs[] must be through the
|
||||
* [get/set]_current_regs for portability.
|
||||
*/
|
||||
|
||||
uint32_t *volatile g_current_regs[CONFIG_SMP_NCPUS];
|
||||
@ -49,7 +49,7 @@ uint32_t *ceva_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
/* Is it the outermost interrupt? */
|
||||
|
||||
if (CURRENT_REGS != NULL)
|
||||
if (up_current_regs() != NULL)
|
||||
{
|
||||
/* No, simply deliver the IRQ because only the outermost nested
|
||||
* interrupt can result in a context switch.
|
||||
@ -60,23 +60,23 @@ uint32_t *ceva_doirq(int irq, uint32_t *regs)
|
||||
else
|
||||
{
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context
|
||||
* current_regs is also used to manage interrupt level context
|
||||
* switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
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
|
||||
* 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 != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
@ -84,16 +84,15 @@ uint32_t *ceva_doirq(int irq, uint32_t *regs)
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
|
||||
regs = CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
}
|
||||
|
||||
/* Restore the previous value of CURRENT_REGS. NULL would indicate
|
||||
/* Restore the previous value of current_regs. NULL would indicate
|
||||
* that we are no longer in an interrupt handler.
|
||||
* It will be non-NULL if we are returning from a nested interrupt.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
if (regs != (uint32_t *)regs[REG_SP])
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ uintptr_t up_getusrsp(void *regs)
|
||||
|
||||
void up_dump_register(void *dumpregs)
|
||||
{
|
||||
volatile uint32_t *regs = dumpregs ? dumpregs : CURRENT_REGS;
|
||||
volatile uint32_t *regs = dumpregs ? dumpregs : up_current_regs();
|
||||
int rx;
|
||||
|
||||
/* Dump the interrupt registers */
|
||||
|
@ -87,7 +87,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
@ -102,7 +102,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !CURRENT_REGS)
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
@ -137,28 +137,28 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = g_current_regs[cpu];
|
||||
tcb->xcp.saved_regs = up_current_regs();
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
g_current_regs[cpu] -= XCPTCONTEXT_REGS;
|
||||
memcpy(g_current_regs[cpu], g_current_regs[cpu] +
|
||||
up_current_regs() -= XCPTCONTEXT_REGS;
|
||||
memcpy(up_current_regs(), up_current_regs() +
|
||||
XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE);
|
||||
|
||||
g_current_regs[cpu][REG_SP] = (uint32_t)g_current_regs[cpu];
|
||||
up_current_regs()[REG_SP] = (uint32_t)up_current_regs();
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* unchanged. We must already be in privileged thread mode
|
||||
* to be here.
|
||||
*/
|
||||
|
||||
g_current_regs[cpu][REG_PC] = (uint32_t)ceva_sigdeliver;
|
||||
up_current_regs()[REG_PC] = (uint32_t)ceva_sigdeliver;
|
||||
#ifdef REG_OM
|
||||
g_current_regs[cpu][REG_OM] &= ~REG_OM_MASK;
|
||||
g_current_regs[cpu][REG_OM] |= REG_OM_KERNEL;
|
||||
up_current_regs()[REG_OM] &= ~REG_OM_MASK;
|
||||
up_current_regs()[REG_OM] |= REG_OM_KERNEL;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -52,7 +52,7 @@ int ceva_svcall(int irq, void *context, void *arg)
|
||||
uint32_t *regs = (uint32_t *)context;
|
||||
uint32_t cmd;
|
||||
|
||||
DEBUGASSERT(regs && regs == CURRENT_REGS);
|
||||
DEBUGASSERT(regs && regs == up_current_regs());
|
||||
cmd = regs[REG_A0];
|
||||
|
||||
/* The SVCall software interrupt is called with A0 = system call command
|
||||
@ -112,16 +112,16 @@ int ceva_svcall(int irq, void *context, void *arg)
|
||||
* A0 = SYS_restore_context
|
||||
* A1 = restoreregs
|
||||
*
|
||||
* In this case, we simply need to set CURRENT_REGS to restore register
|
||||
* area referenced in the saved A1. context == CURRENT_REGS is the
|
||||
* noraml exception return. By setting CURRENT_REGS = context[A1],
|
||||
* In this case, we simply need to set current_regs to restore register
|
||||
* area referenced in the saved A1. context == current_regs is the
|
||||
* noraml exception return. By setting current_regs = context[A1],
|
||||
* we force the return to the saved context referenced in A1.
|
||||
*/
|
||||
|
||||
case SYS_restore_context:
|
||||
{
|
||||
DEBUGASSERT(regs[REG_A1] != 0);
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_A1];
|
||||
up_set_current_regs((uint32_t *)regs[REG_A1]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -138,7 +138,7 @@ int ceva_svcall(int irq, void *context, void *arg)
|
||||
*
|
||||
* In this case, we do both: We save the context registers to the save
|
||||
* register area reference by the saved contents of A1 and then set
|
||||
* CURRENT_REGS to to the save register area referenced by the saved
|
||||
* current_regs to to the save register area referenced by the saved
|
||||
* contents of A2.
|
||||
*/
|
||||
|
||||
@ -146,7 +146,7 @@ int ceva_svcall(int irq, void *context, void *arg)
|
||||
{
|
||||
DEBUGASSERT(regs[REG_A1] != 0 && regs[REG_A2] != 0);
|
||||
*(uint32_t **)regs[REG_A1] = regs;
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_A2];
|
||||
up_set_current_regs((uint32_t *)regs[REG_A2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -384,20 +384,20 @@ int ceva_svcall(int irq, void *context, void *arg)
|
||||
# ifndef CONFIG_DEBUG_SVCALL
|
||||
if (cmd > SYS_switch_context)
|
||||
# else
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
# endif
|
||||
{
|
||||
svcinfo("SVCall Return:\n");
|
||||
svcinfo("A0: %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
CURRENT_REGS[REG_A0], CURRENT_REGS[REG_A1],
|
||||
CURRENT_REGS[REG_A2], CURRENT_REGS[REG_A3],
|
||||
CURRENT_REGS[REG_A4], CURRENT_REGS[REG_A5],
|
||||
CURRENT_REGS[REG_A6]);
|
||||
up_current_regs()[REG_A0], up_current_regs()[REG_A1],
|
||||
up_current_regs()[REG_A2], up_current_regs()[REG_A3],
|
||||
up_current_regs()[REG_A4], up_current_regs()[REG_A5],
|
||||
up_current_regs()[REG_A6]);
|
||||
svcinfo("FP: %08x LR: %08x PC: %08x IRQ: %08x OM: %08x\n",
|
||||
CURRENT_REGS[REG_FP], CURRENT_REGS[REG_LR],
|
||||
CURRENT_REGS[REG_PC], CURRENT_REGS[REG_IRQ],
|
||||
up_current_regs()[REG_FP], up_current_regs()[REG_LR],
|
||||
up_current_regs()[REG_PC], up_current_regs()[REG_IRQ],
|
||||
# ifdef REG_OM
|
||||
CURRENT_REGS[REG_OM]
|
||||
up_current_regs()[REG_OM]
|
||||
#else
|
||||
0x00000000
|
||||
#endif
|
||||
|
@ -75,13 +75,13 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||
|
||||
/* Are we in an interrupt handler? */
|
||||
|
||||
if (CURRENT_REGS)
|
||||
if (up_current_regs())
|
||||
{
|
||||
/* Yes, then we have to do things differently.
|
||||
* Just copy the CURRENT_REGS into the OLD rtcb.
|
||||
* Just copy the current_regs into the OLD rtcb.
|
||||
*/
|
||||
|
||||
rtcb->xcp.regs = CURRENT_REGS;
|
||||
rtcb->xcp.regs = up_current_regs();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
@ -89,7 +89,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||
|
||||
/* Then switch contexts */
|
||||
|
||||
CURRENT_REGS = tcb->xcp.regs;
|
||||
up_set_current_regs(tcb->xcp.regs);
|
||||
}
|
||||
|
||||
/* No, then we will need to perform the user context switch */
|
||||
|
@ -122,6 +122,16 @@ EXTERN volatile uint8_t *g_current_regs;
|
||||
* Inline functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline_function uint8_t *up_current_regs(void)
|
||||
{
|
||||
return (FAR uint8_t *)g_current_regs;
|
||||
}
|
||||
|
||||
static inline_function void up_set_current_regs(FAR uint8_t *regs)
|
||||
{
|
||||
g_current_regs = regs;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_interrupt_context
|
||||
*
|
||||
@ -131,7 +141,7 @@ EXTERN volatile uint8_t *g_current_regs;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define up_interrupt_context() (g_current_regs != NULL)
|
||||
#define up_interrupt_context() (up_current_regs() != NULL)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
|
@ -68,8 +68,8 @@ uint8_t *hc_doirq(int irq, uint8_t *regs)
|
||||
* Nested interrupts are not supported
|
||||
*/
|
||||
|
||||
DEBUGASSERT(g_current_regs == NULL);
|
||||
g_current_regs = regs;
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
@ -82,12 +82,12 @@ uint8_t *hc_doirq(int irq, uint8_t *regs)
|
||||
* returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != g_current_regs)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
/* Restore floating point registers */
|
||||
|
||||
up_restorefpu((uint32_t *)g_current_regs);
|
||||
up_restorefpu(up_current_regs());
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
@ -114,13 +114,13 @@ uint8_t *hc_doirq(int irq, uint8_t *regs)
|
||||
* switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
regs = (uint8_t *)g_current_regs;
|
||||
regs = up_current_regs();
|
||||
|
||||
/* Set g_current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
g_current_regs = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
#endif
|
||||
board_autoled_off(LED_INIRQ);
|
||||
return regs;
|
||||
|
@ -95,8 +95,8 @@
|
||||
* a referenced is passed to get the state from the TCB.
|
||||
*/
|
||||
|
||||
#define hc_savestate(regs) hc_copystate(regs, (uint8_t*)g_current_regs)
|
||||
#define hc_restorestate(regs) (g_current_regs = regs)
|
||||
#define hc_savestate(regs) hc_copystate(regs, up_current_regs())
|
||||
#define hc_restorestate(regs) up_set_current_regs(regs)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
|
@ -62,7 +62,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||
|
||||
/* Are we in an interrupt handler? */
|
||||
|
||||
if (g_current_regs)
|
||||
if (up_current_regs())
|
||||
{
|
||||
/* Yes, then we have to do things differently.
|
||||
* Just copy the g_current_regs into the OLD rtcb.
|
||||
|
@ -52,7 +52,7 @@ uintptr_t up_getusrsp(void *regs)
|
||||
|
||||
void up_dump_register(void *dumpregs)
|
||||
{
|
||||
volatile uint8_t *regs = dumpregs ? dumpregs : (uint8_t *)g_current_regs;
|
||||
volatile uint8_t *regs = dumpregs ? dumpregs : up_current_regs();
|
||||
|
||||
_alert("A:%02x B:%02x X:%02x%02x Y:%02x%02x PC:%02x%02x CCR:%02x\n",
|
||||
regs[REG_A], regs[REG_B], regs[REG_XH], regs[REG_XL],
|
||||
|
@ -90,8 +90,8 @@ static inline uint32_t up_getsp(void)
|
||||
|
||||
/* g_current_regs holds a references to the current interrupt level
|
||||
* register storage structure. It is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs must be through the macro
|
||||
* CURRENT_REGS for portability.
|
||||
* processing. Access to g_current_regs must be through the
|
||||
* [get/set]_current_regs for portability.
|
||||
*/
|
||||
|
||||
/* For the case of architectures with multiple CPUs, then there must be one
|
||||
@ -99,7 +99,6 @@ static inline uint32_t up_getsp(void)
|
||||
*/
|
||||
|
||||
EXTERN volatile uint32_t *g_current_regs;
|
||||
#define CURRENT_REGS g_current_regs
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
@ -127,6 +126,16 @@ EXTERN volatile uint32_t *g_current_regs;
|
||||
* Inline functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline_function uint32_t *up_current_regs(void)
|
||||
{
|
||||
return (uint32_t *)g_current_regs;
|
||||
}
|
||||
|
||||
static inline_function void up_set_current_regs(uint32_t *regs)
|
||||
{
|
||||
g_current_regs = regs;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_interrupt_context
|
||||
*
|
||||
@ -136,7 +145,7 @@ EXTERN volatile uint32_t *g_current_regs;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define up_interrupt_context() (g_current_regs != NULL)
|
||||
#define up_interrupt_context() (up_current_regs() != NULL)
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
|
@ -34,8 +34,8 @@
|
||||
|
||||
/* g_current_regs holds a references to the current interrupt level
|
||||
* register storage structure. It is non-NULL only during interrupt
|
||||
* processing. Access to g_current_regs must be through the macro
|
||||
* CURRENT_REGS for portability.
|
||||
* processing. Access to g_current_regs must be through the
|
||||
* [get/set]_current_regs for portability.
|
||||
*/
|
||||
|
||||
volatile uint32_t *g_current_regs;
|
||||
|
@ -96,8 +96,8 @@
|
||||
* only a referenced is passed to get the state from the TCB.
|
||||
*/
|
||||
|
||||
#define mips_savestate(regs) mips_copystate(regs, (uint32_t*)CURRENT_REGS)
|
||||
#define mips_restorestate(regs) (CURRENT_REGS = regs)
|
||||
#define mips_savestate(regs) mips_copystate(regs, up_current_regs())
|
||||
#define mips_restorestate(regs) up_set_current_regs(regs)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
|
@ -68,8 +68,8 @@ uint32_t *mips_doirq(int irq, uint32_t *regs)
|
||||
* Nested interrupts are not supported
|
||||
*/
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
CURRENT_REGS = regs;
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Disable further occurrences of this interrupt (until the interrupt
|
||||
* source have been cleared by the driver).
|
||||
@ -88,12 +88,12 @@ uint32_t *mips_doirq(int irq, uint32_t *regs)
|
||||
* returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
/* Restore floating point registers */
|
||||
|
||||
up_restorefpu((uint32_t *)CURRENT_REGS);
|
||||
up_restorefpu(up_current_regs());
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
@ -120,13 +120,13 @@ uint32_t *mips_doirq(int irq, uint32_t *regs)
|
||||
* switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
|
||||
/* Set g_current_regs to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
/* Unmask the last interrupt (global interrupts are still disabled) */
|
||||
|
||||
|
@ -54,7 +54,7 @@ uintptr_t up_getusrsp(void *regs)
|
||||
|
||||
void up_dump_register(void *dumpregs)
|
||||
{
|
||||
volatile uint32_t *regs = dumpregs ? dumpregs : CURRENT_REGS;
|
||||
volatile uint32_t *regs = dumpregs ? dumpregs : up_current_regs();
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
|
@ -92,8 +92,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n",
|
||||
this_task(), CURRENT_REGS);
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
@ -101,7 +100,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* a task is signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
@ -128,18 +127,18 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.saved_epc = CURRENT_REGS[REG_EPC];
|
||||
tcb->xcp.saved_status = CURRENT_REGS[REG_STATUS];
|
||||
tcb->xcp.saved_epc = up_current_regs()[REG_EPC];
|
||||
tcb->xcp.saved_status = up_current_regs()[REG_STATUS];
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_EPC] = (uint32_t)mips_sigdeliver;
|
||||
status = CURRENT_REGS[REG_STATUS];
|
||||
status &= ~CP0_STATUS_INT_MASK;
|
||||
status |= CP0_STATUS_INT_SW0;
|
||||
CURRENT_REGS[REG_STATUS] = status;
|
||||
up_current_regs()[REG_EPC] = (uint32_t)mips_sigdeliver;
|
||||
status = up_current_regs()[REG_STATUS];
|
||||
status &= ~CP0_STATUS_INT_MASK;
|
||||
status |= CP0_STATUS_INT_SW0;
|
||||
up_current_regs()[REG_STATUS] = status;
|
||||
|
||||
/* And make sure that the saved context in the TCB
|
||||
* is the same as the interrupt return context.
|
||||
@ -150,7 +149,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32
|
||||
" New: %08" PRIx32 "/%08" PRIx32 "\n",
|
||||
tcb->xcp.saved_epc, tcb->xcp.saved_status,
|
||||
CURRENT_REGS[REG_EPC], CURRENT_REGS[REG_STATUS]);
|
||||
up_current_regs()[REG_EPC],
|
||||
up_current_regs()[REG_STATUS]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ int mips_swint0(int irq, void *context, void *arg)
|
||||
uint32_t *regs = (uint32_t *)context;
|
||||
uint32_t cause;
|
||||
|
||||
DEBUGASSERT(regs && regs == CURRENT_REGS);
|
||||
DEBUGASSERT(regs && regs == up_current_regs());
|
||||
|
||||
/* Software interrupt 0 is invoked with REG_A0 (REG_R4) = system call
|
||||
* command and REG_A1-3 and REG_T0-2 (REG_R5-10) = variable number of
|
||||
@ -155,7 +155,7 @@ int mips_swint0(int irq, void *context, void *arg)
|
||||
case SYS_restore_context:
|
||||
{
|
||||
DEBUGASSERT(regs[REG_A1] != 0);
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_A1];
|
||||
up_set_current_regs((uint32_t *)regs[REG_A1]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -180,7 +180,7 @@ int mips_swint0(int irq, void *context, void *arg)
|
||||
{
|
||||
DEBUGASSERT(regs[REG_A1] != 0 && regs[REG_A2] != 0);
|
||||
mips_copystate((uint32_t *)regs[REG_A1], regs);
|
||||
CURRENT_REGS = (uint32_t *)regs[REG_A2];
|
||||
up_set_current_regs((uint32_t *)regs[REG_A2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -210,7 +210,7 @@ int mips_swint0(int irq, void *context, void *arg)
|
||||
* the original mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_EPC] = rtcb->xcp.syscall[index].sysreturn;
|
||||
up_current_regs()[REG_EPC] = rtcb->xcp.syscall[index].sysreturn;
|
||||
#error "Missing logic -- need to restore the original mode"
|
||||
rtcb->xcp.nsyscalls = index;
|
||||
|
||||
@ -237,7 +237,7 @@ int mips_swint0(int irq, void *context, void *arg)
|
||||
|
||||
/* Verify that the SYS call number is within range */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS[REG_A0] < SYS_maxsyscall);
|
||||
DEBUGASSERT(up_current_regs()[REG_A0] < SYS_maxsyscall);
|
||||
|
||||
/* Make sure that we got here that there is a no saved syscall
|
||||
* return address. We cannot yet handle nested system calls.
|
||||
@ -256,7 +256,7 @@ int mips_swint0(int irq, void *context, void *arg)
|
||||
|
||||
/* Offset R0 to account for the reserved values */
|
||||
|
||||
CURRENT_REGS[REG_R0] -= CONFIG_SYS_RESERVED;
|
||||
up_current_regs()[REG_R0] -= CONFIG_SYS_RESERVED;
|
||||
|
||||
/* Indicate that we are in a syscall handler. */
|
||||
|
||||
@ -273,10 +273,10 @@ int mips_swint0(int irq, void *context, void *arg)
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DEBUG_SYSCALL_INFO
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
svcinfo("SWInt Return: Context switch!\n");
|
||||
up_dump_register(CURRENT_REGS);
|
||||
up_dump_register(up_current_regs());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -63,7 +63,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||
|
||||
/* Are we in an interrupt handler? */
|
||||
|
||||
if (CURRENT_REGS)
|
||||
if (up_current_regs())
|
||||
{
|
||||
/* Yes, then we have to do things differently.
|
||||
* Just copy the g_current_regs into the OLD rtcb.
|
||||
|
@ -88,11 +88,11 @@ uint32_t *pic32mx_decodeirq(uint32_t *regs)
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PIC32MX_NESTED_INTERRUPTS
|
||||
savestate = (uint32_t *)CURRENT_REGS;
|
||||
savestate = up_current_regs();
|
||||
#else
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
#endif
|
||||
CURRENT_REGS = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* Loop while there are pending interrupts with priority greater than
|
||||
* zero
|
||||
@ -131,7 +131,7 @@ uint32_t *pic32mx_decodeirq(uint32_t *regs)
|
||||
* switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
regs = up_current_regs();
|
||||
|
||||
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
@ -141,12 +141,12 @@ uint32_t *pic32mx_decodeirq(uint32_t *regs)
|
||||
* returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
/* Restore floating point registers */
|
||||
|
||||
up_restorefpu((uint32_t *)CURRENT_REGS);
|
||||
up_restorefpu(up_current_regs());
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
@ -171,13 +171,13 @@ uint32_t *pic32mx_decodeirq(uint32_t *regs)
|
||||
* of fixing nested context switching. The logic here is insufficient.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = savestate;
|
||||
if (CURRENT_REGS == NULL)
|
||||
up_set_current_regs(savestate);
|
||||
if (up_current_regs() == NULL)
|
||||
{
|
||||
board_autoled_off(LED_INIRQ);
|
||||
}
|
||||
#else
|
||||
CURRENT_REGS = NULL;
|
||||
up_set_current_regs(NULL);
|
||||
board_autoled_off(LED_INIRQ);
|
||||
#endif
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user