Skip to content

Commit

Permalink
arch: use up_current_regs/up_set_current_regs replace CURRENT_REGS
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
hujun260 committed Sep 13, 2024
1 parent 512a496 commit 60a17a2
Show file tree
Hide file tree
Showing 207 changed files with 1,306 additions and 1,123 deletions.
19 changes: 14 additions & 5 deletions arch/arm/include/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,16 @@ 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
* such value for each processor that can receive an interrupt.
*/

EXTERN volatile uint32_t *g_current_regs[CONFIG_SMP_NCPUS];
#define CURRENT_REGS (g_current_regs[up_cpu_index()])

/****************************************************************************
* Public Function Prototypes
Expand All @@ -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
*
Expand All @@ -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);
Expand Down
14 changes: 7 additions & 7 deletions arch/arm/src/arm/arm_dataabort.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -153,11 +153,11 @@ void arm_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr)

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. */

Expand Down
16 changes: 8 additions & 8 deletions arch/arm/src/arm/arm_doirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand All @@ -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
Expand All @@ -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;
Expand Down
10 changes: 5 additions & 5 deletions arch/arm/src/arm/arm_prefetchabort.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
23 changes: 11 additions & 12 deletions arch/arm/src/arm/arm_schedulesigaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ 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())
{
/* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
*/

if (!CURRENT_REGS)
if (!up_current_regs())
{
/* In this case just deliver the signal now. */

Expand All @@ -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
Expand All @@ -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
}
}
Expand Down
24 changes: 12 additions & 12 deletions arch/arm/src/arm/arm_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand All @@ -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,
Expand All @@ -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.
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion arch/arm/src/arm/arm_undefinedinsn.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
13 changes: 6 additions & 7 deletions arch/arm/src/armv6-m/arm_doirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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.
*/
Expand All @@ -70,21 +70,20 @@ 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
* crashes.
*/

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

Expand Down
Loading

0 comments on commit 60a17a2

Please sign in to comment.