aarch64: userspace: Introduce arch_is_user_context
The arch_is_user_context() function is relying on the content of the tpidrro_el0 register to determine whether we are in user context or not. This register is set to '1' when in EL1 and set back to '0' when user threads are running in userspace. Signed-off-by: Carlo Caione <ccaione@baylibre.com>
This commit is contained in:
parent
6cf0d000e8
commit
6978160427
6 changed files with 57 additions and 2 deletions
|
@ -52,6 +52,8 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
|||
} else {
|
||||
pInitCtx->elr = (uint64_t)z_thread_entry;
|
||||
}
|
||||
|
||||
pInitCtx->tpidrro_el0 = 0x0;
|
||||
#else
|
||||
pInitCtx->elr = (uint64_t)z_thread_entry;
|
||||
#endif
|
||||
|
@ -95,6 +97,9 @@ FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
|
|||
pInitCtx->spsr = DAIF_FIQ_BIT | SPSR_MODE_EL0T;
|
||||
pInitCtx->elr = (uint64_t)z_thread_entry;
|
||||
|
||||
/* The thread will be in user context */
|
||||
pInitCtx->tpidrro_el0 = 0x1;
|
||||
|
||||
pInitCtx->x0 = (uint64_t)user_entry;
|
||||
pInitCtx->x1 = (uint64_t)p1;
|
||||
pInitCtx->x2 = (uint64_t)p2;
|
||||
|
|
|
@ -55,6 +55,15 @@ _ASM_FILE_PROLOGUE
|
|||
mrs \xreg1, elr_el1
|
||||
stp \xreg0, \xreg1, [sp, ___esf_t_spsr_elr_OFFSET]
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
/* Save the current kernel/user mode in the context */
|
||||
mrs \xreg0, tpidrro_el0
|
||||
str \xreg0, [sp, ___esf_t_tpidrro_el0_OFFSET]
|
||||
|
||||
/* Switch TPIDRRO_EL0 to kernel mode */
|
||||
msr tpidrro_el0, xzr
|
||||
#endif
|
||||
|
||||
.endm
|
||||
|
||||
/*
|
||||
|
@ -201,6 +210,12 @@ SECTION_FUNC(TEXT, z_arm64_exit_exc)
|
|||
msr spsr_el1, x0
|
||||
msr elr_el1, x1
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
/* Restore the kernel/user mode flag */
|
||||
ldr x0, [sp, ___esf_t_tpidrro_el0_OFFSET]
|
||||
msr tpidrro_el0, x0
|
||||
#endif
|
||||
|
||||
ldp x0, x1, [sp, ___esf_t_x0_x1_OFFSET]
|
||||
ldp x2, x3, [sp, ___esf_t_x2_x3_OFFSET]
|
||||
ldp x4, x5, [sp, ___esf_t_x4_x5_OFFSET]
|
||||
|
|
|
@ -39,6 +39,9 @@ GEN_NAMED_OFFSET_SYM(_callee_saved_t, x29, x29_sp);
|
|||
GEN_ABSOLUTE_SYM(___callee_saved_t_SIZEOF, sizeof(struct _callee_saved));
|
||||
|
||||
GEN_NAMED_OFFSET_SYM(_esf_t, spsr, spsr_elr);
|
||||
#ifdef CONFIG_USERSPACE
|
||||
GEN_NAMED_OFFSET_SYM(_esf_t, tpidrro_el0, tpidrro_el0);
|
||||
#endif
|
||||
GEN_NAMED_OFFSET_SYM(_esf_t, x18, x18_x30);
|
||||
GEN_NAMED_OFFSET_SYM(_esf_t, x16, x16_x17);
|
||||
GEN_NAMED_OFFSET_SYM(_esf_t, x14, x14_x15);
|
||||
|
|
|
@ -47,6 +47,9 @@ struct __esf {
|
|||
uint64_t x30;
|
||||
uint64_t spsr;
|
||||
uint64_t elr;
|
||||
#ifdef CONFIG_USERSPACE
|
||||
uint64_t tpidrro_el0;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct __esf z_arch_esf_t;
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARM specific syscall header
|
||||
* @brief ARM64 specific syscall header
|
||||
*
|
||||
* This header contains the ARM specific syscall interface. It is
|
||||
* This header contains the ARM64 specific syscall interface. It is
|
||||
* included by the syscall interface architecture-abstraction header
|
||||
* (include/arch/aarch64/syscall.h)
|
||||
*/
|
||||
|
@ -20,4 +20,31 @@
|
|||
#define _SVC_CALL_IRQ_OFFLOAD 1
|
||||
#define _SVC_CALL_RUNTIME_EXCEPT 2
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <arch/arm/aarch64/cpu.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline bool arch_is_user_context(void)
|
||||
{
|
||||
uint64_t tpidrro_el0;
|
||||
|
||||
__asm__ volatile("mrs %0, tpidrro_el0" : "=r" (tpidrro_el0));
|
||||
|
||||
return (tpidrro_el0 != 0x0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH64_SYSCALL_H_ */
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#else
|
||||
#include <arch/x86/ia32/syscall.h>
|
||||
#endif
|
||||
#elif defined(CONFIG_ARM64)
|
||||
#include <arch/arm/aarch64/syscall.h>
|
||||
#elif defined(CONFIG_ARM)
|
||||
#include <arch/arm/aarch32/syscall.h>
|
||||
#elif defined(CONFIG_ARC)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue