arm64: add up_this_task and up_change_task macro impl

Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
hujun5 2024-07-23 21:11:45 +08:00 committed by GUIDINGLI
parent a567148888
commit 948ac9b4cc
6 changed files with 34 additions and 52 deletions

View file

@ -55,7 +55,7 @@
/****************************************************************************
* Name:
* read_/write_/zero_ sysreg
* read_/write_/zero_/modify_ sysreg
*
* Description:
*
@ -84,6 +84,10 @@
::: "memory"); \
})
#define modify_sysreg(v,m,a) \
write_sysreg((read_sysreg(a) & ~(m)) | \
((uintptr_t)(v) & (m)), a)
/****************************************************************************
* Inline functions
****************************************************************************/

View file

@ -387,31 +387,17 @@ static inline void up_irq_restore(irqstate_t flags)
#endif /* CONFIG_ARCH_HAVE_MULTICPU */
/****************************************************************************
* Name:
* up_current_regs/up_set_current_regs
*
* Description:
* We use the following code to manipulate the tpidr_el1 register,
* which exists uniquely for each CPU and is primarily designed to store
* current thread information. Currently, we leverage it to store interrupt
* information, with plans to further optimize its use for storing both
* thread and interrupt information in the future.
* Schedule acceleration macros
*
* The lsbit of tpidr_el1 stores information about whether the current
* execution is in an interrupt context, where 1 indicates being in an
* interrupt context and 0 indicates being in a thread context.
****************************************************************************/
noinstrument_function
static inline_function uint64_t *up_current_regs(void)
{
uint64_t *regs;
__asm__ volatile ("mrs %0, " "tpidr_el1" : "=r" (regs));
return regs;
}
noinstrument_function
static inline_function void up_set_current_regs(uint64_t *regs)
{
__asm__ volatile ("msr " "tpidr_el1" ", %0" : : "r" (regs));
}
#define up_current_regs() (this_task()->xcp.regs)
#define up_this_task() ((struct tcb_s *)(read_sysreg(tpidr_el1) & ~1ul))
#define up_update_task(t) modify_sysreg(t, ~1ul, tpidr_el1)
#define up_interrupt_context() (read_sysreg(tpidr_el1) & 1)
#define up_switch_context(tcb, rtcb) \
do { \
@ -422,19 +408,6 @@ static inline_function void up_set_current_regs(uint64_t *regs)
} \
} while (0)
/****************************************************************************
* Name: up_interrupt_context
*
* Description: Return true is we are currently executing in
* the interrupt handler context.
*
****************************************************************************/
static inline bool up_interrupt_context(void)
{
return up_current_regs() != NULL;
}
/****************************************************************************
* Name: up_getusrpc
****************************************************************************/

View file

@ -113,7 +113,11 @@ static inline void local_delay(void)
static void arm64_smp_init_top(void)
{
struct tcb_s *tcb = this_task();
struct tcb_s *tcb = current_task(this_cpu());
/* Init idle task to percpu reg */
up_update_task(tcb);
#ifndef CONFIG_SUPPRESS_INTERRUPTS
/* And finally, enable interrupts */

View file

@ -61,13 +61,12 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
/* Nested interrupts are not supported */
DEBUGASSERT(up_current_regs() == NULL);
DEBUGASSERT(!up_interrupt_context());
/* Current regs non-zero indicates that we are processing an interrupt;
* current_regs is also used to manage interrupt level context switches.
*/
/* Set irq flag */
write_sysreg((uintptr_t)tcb | 1, tpidr_el1);
up_set_current_regs(regs);
tcb->xcp.regs = regs;
/* Deliver the IRQ */
@ -110,11 +109,9 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
regs = tcb->xcp.regs;
}
/* Set current_regs to NULL to indicate that we are no longer in an
* interrupt handler.
*/
/* Clear irq flag */
up_set_current_regs(NULL);
write_sysreg((uintptr_t)tcb & ~1ul, tpidr_el1);
return regs;
}

View file

@ -541,13 +541,18 @@ static int arm64_exception_handler(uint64_t *regs)
void arm64_fatal_handler(uint64_t *regs)
{
struct tcb_s *tcb = this_task();
int ret;
/* Nested exception are not supported */
DEBUGASSERT(up_current_regs() == NULL);
DEBUGASSERT(!up_interrupt_context());
up_set_current_regs((uint64_t *)regs);
tcb->xcp.regs = (uint64_t *)regs;
/* Set irq flag */
write_sysreg((uintptr_t)tcb | 1, tpidr_el1);
ret = arm64_exception_handler(regs);
@ -558,11 +563,9 @@ void arm64_fatal_handler(uint64_t *regs)
PANIC_WITH_REGS("panic", regs);
}
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
* Exception handler.
*/
/* Clear irq flag */
up_set_current_regs(NULL);
write_sysreg((uintptr_t)tcb & ~1ul, tpidr_el1);
}
void arm64_register_debug_hook(int nr, fatal_handle_func_t fn)

View file

@ -31,6 +31,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include "sched/sched.h"
#include "arm64_arch.h"
#include "arm64_internal.h"
#include "chip.h"