Skip to content

Commit 6978160

Browse files
carlocaionenashif
authored andcommitted
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 <[email protected]>
1 parent 6cf0d00 commit 6978160

File tree

6 files changed

+57
-2
lines changed

6 files changed

+57
-2
lines changed

arch/arm/core/aarch64/thread.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
5252
} else {
5353
pInitCtx->elr = (uint64_t)z_thread_entry;
5454
}
55+
56+
pInitCtx->tpidrro_el0 = 0x0;
5557
#else
5658
pInitCtx->elr = (uint64_t)z_thread_entry;
5759
#endif
@@ -95,6 +97,9 @@ FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
9597
pInitCtx->spsr = DAIF_FIQ_BIT | SPSR_MODE_EL0T;
9698
pInitCtx->elr = (uint64_t)z_thread_entry;
9799

100+
/* The thread will be in user context */
101+
pInitCtx->tpidrro_el0 = 0x1;
102+
98103
pInitCtx->x0 = (uint64_t)user_entry;
99104
pInitCtx->x1 = (uint64_t)p1;
100105
pInitCtx->x2 = (uint64_t)p2;

arch/arm/core/aarch64/vector_table.S

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ _ASM_FILE_PROLOGUE
5555
mrs \xreg1, elr_el1
5656
stp \xreg0, \xreg1, [sp, ___esf_t_spsr_elr_OFFSET]
5757

58+
#ifdef CONFIG_USERSPACE
59+
/* Save the current kernel/user mode in the context */
60+
mrs \xreg0, tpidrro_el0
61+
str \xreg0, [sp, ___esf_t_tpidrro_el0_OFFSET]
62+
63+
/* Switch TPIDRRO_EL0 to kernel mode */
64+
msr tpidrro_el0, xzr
65+
#endif
66+
5867
.endm
5968

6069
/*
@@ -201,6 +210,12 @@ SECTION_FUNC(TEXT, z_arm64_exit_exc)
201210
msr spsr_el1, x0
202211
msr elr_el1, x1
203212

213+
#ifdef CONFIG_USERSPACE
214+
/* Restore the kernel/user mode flag */
215+
ldr x0, [sp, ___esf_t_tpidrro_el0_OFFSET]
216+
msr tpidrro_el0, x0
217+
#endif
218+
204219
ldp x0, x1, [sp, ___esf_t_x0_x1_OFFSET]
205220
ldp x2, x3, [sp, ___esf_t_x2_x3_OFFSET]
206221
ldp x4, x5, [sp, ___esf_t_x4_x5_OFFSET]

arch/arm/core/offsets/offsets_aarch64.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ GEN_NAMED_OFFSET_SYM(_callee_saved_t, x29, x29_sp);
3939
GEN_ABSOLUTE_SYM(___callee_saved_t_SIZEOF, sizeof(struct _callee_saved));
4040

4141
GEN_NAMED_OFFSET_SYM(_esf_t, spsr, spsr_elr);
42+
#ifdef CONFIG_USERSPACE
43+
GEN_NAMED_OFFSET_SYM(_esf_t, tpidrro_el0, tpidrro_el0);
44+
#endif
4245
GEN_NAMED_OFFSET_SYM(_esf_t, x18, x18_x30);
4346
GEN_NAMED_OFFSET_SYM(_esf_t, x16, x16_x17);
4447
GEN_NAMED_OFFSET_SYM(_esf_t, x14, x14_x15);

include/arch/arm/aarch64/exc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ struct __esf {
4747
uint64_t x30;
4848
uint64_t spsr;
4949
uint64_t elr;
50+
#ifdef CONFIG_USERSPACE
51+
uint64_t tpidrro_el0;
52+
#endif
5053
};
5154

5255
typedef struct __esf z_arch_esf_t;

include/arch/arm/aarch64/syscall.h

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
/**
88
* @file
9-
* @brief ARM specific syscall header
9+
* @brief ARM64 specific syscall header
1010
*
11-
* This header contains the ARM specific syscall interface. It is
11+
* This header contains the ARM64 specific syscall interface. It is
1212
* included by the syscall interface architecture-abstraction header
1313
* (include/arch/aarch64/syscall.h)
1414
*/
@@ -20,4 +20,31 @@
2020
#define _SVC_CALL_IRQ_OFFLOAD 1
2121
#define _SVC_CALL_RUNTIME_EXCEPT 2
2222

23+
#ifdef CONFIG_USERSPACE
24+
#ifndef _ASMLANGUAGE
25+
26+
#include <zephyr/types.h>
27+
#include <stdbool.h>
28+
#include <arch/arm/aarch64/cpu.h>
29+
30+
#ifdef __cplusplus
31+
extern "C" {
32+
#endif
33+
34+
static inline bool arch_is_user_context(void)
35+
{
36+
uint64_t tpidrro_el0;
37+
38+
__asm__ volatile("mrs %0, tpidrro_el0" : "=r" (tpidrro_el0));
39+
40+
return (tpidrro_el0 != 0x0);
41+
}
42+
43+
#ifdef __cplusplus
44+
}
45+
#endif
46+
47+
#endif /* _ASMLANGUAGE */
48+
#endif /* CONFIG_USERSPACE */
49+
2350
#endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH64_SYSCALL_H_ */

include/arch/syscall.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#else
1616
#include <arch/x86/ia32/syscall.h>
1717
#endif
18+
#elif defined(CONFIG_ARM64)
19+
#include <arch/arm/aarch64/syscall.h>
1820
#elif defined(CONFIG_ARM)
1921
#include <arch/arm/aarch32/syscall.h>
2022
#elif defined(CONFIG_ARC)

0 commit comments

Comments
 (0)