Skip to content

Commit 8847790

Browse files
Nicolas Pitrenashif
authored andcommitted
arm64: hold curr_cpu instance in tpidrro_el0
Let's fully exploit tpidrro_el0 by storing in it the current CPU's struct _cpu instance alongside the userspace mode flag bit. This greatly simplifies the code needed to get at the cpu structure, and this paves the way to much simpler multi cluster support, as there is no longer the need to decode MPIDR all the time. The same code is used in the !SMP case as there are benefits there too such as avoiding the literal pool, and it looks cleaner. The tpidrro_el0 value is no longer stored in the exception stack frame. Instead, we simply restore the user mode flag based on the SPSR value. This way, more flag bits could be used independently in the future. Signed-off-by: Nicolas Pitre <[email protected]>
1 parent 2bed37e commit 8847790

File tree

13 files changed

+55
-64
lines changed

13 files changed

+55
-64
lines changed

arch/arm64/core/macro_priv.inc

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
#ifndef _MACRO_PRIV_INC_
88
#define _MACRO_PRIV_INC_
99

10-
#ifdef _ASMLANGUAGE
10+
#include <arch/arm64/tpidrro_el0.h>
1111

12-
GDATA(_kernel)
12+
#ifdef _ASMLANGUAGE
1313

1414
/*
1515
* Get CPU id
@@ -25,48 +25,31 @@ GDATA(_kernel)
2525
* Get CPU pointer
2626
*/
2727

28-
.macro get_cpu xreg0, xreg1
29-
get_cpu_id \xreg1
30-
mov \xreg0, #___cpu_t_SIZEOF
31-
mul \xreg0, \xreg0, \xreg1
32-
ldr \xreg1, =(_kernel + ___kernel_t_cpus_OFFSET)
33-
add \xreg0, \xreg0, \xreg1
28+
.macro get_cpu xreg0
29+
mrs \xreg0, tpidrro_el0
30+
and \xreg0, \xreg0, #TPIDRROEL0_CURR_CPU
3431
.endm
3532

3633
/*
3734
* Increment nested counter
3835
*/
3936

4037
.macro inc_nest_counter xreg0, xreg1
41-
#ifdef CONFIG_SMP
42-
get_cpu \xreg0, \xreg1
38+
get_cpu \xreg0
4339
ldr \xreg1, [\xreg0, #___cpu_t_nested_OFFSET]
4440
add \xreg1, \xreg1, #1
4541
str \xreg1, [\xreg0, #___cpu_t_nested_OFFSET]
46-
#else
47-
ldr \xreg0, =_kernel
48-
ldr \xreg1, [\xreg0, #_kernel_offset_to_nested]
49-
add \xreg1, \xreg1, #1
50-
str \xreg1, [\xreg0, #_kernel_offset_to_nested]
51-
#endif
5242
.endm
5343

5444
/*
5545
* Decrement nested counter and update condition flags
5646
*/
5747

5848
.macro dec_nest_counter xreg0, xreg1
59-
#ifdef CONFIG_SMP
60-
get_cpu \xreg0, \xreg1
49+
get_cpu \xreg0
6150
ldr \xreg1, [\xreg0, #___cpu_t_nested_OFFSET]
6251
subs \xreg1, \xreg1, #1
6352
str \xreg1, [\xreg0, #___cpu_t_nested_OFFSET]
64-
#else
65-
ldr \xreg0, =_kernel
66-
ldr \xreg1, [\xreg0, #_kernel_offset_to_nested]
67-
subs \xreg1, \xreg1, #1
68-
str \xreg1, [\xreg0, #_kernel_offset_to_nested]
69-
#endif
7053
.endm
7154

7255
#endif /* _ASMLANGUAGE */

arch/arm64/core/offsets/offsets.c

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

4646
GEN_NAMED_OFFSET_SYM(_esf_t, spsr, spsr_elr);
47-
#ifdef CONFIG_USERSPACE
48-
GEN_NAMED_OFFSET_SYM(_esf_t, tpidrro_el0, tpidrro_el0);
49-
#endif
5047
GEN_NAMED_OFFSET_SYM(_esf_t, x18, x18_x30);
5148
GEN_NAMED_OFFSET_SYM(_esf_t, x16, x16_x17);
5249
GEN_NAMED_OFFSET_SYM(_esf_t, x14, x14_x15);

arch/arm64/core/prep_c.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ static inline void z_arm64_bss_zero(void)
4545
*/
4646
void z_arm64_prep_c(void)
4747
{
48+
/* Initialize tpidrro_el0 with our struct _cpu instance address */
49+
write_tpidrro_el0((uintptr_t)&_kernel.cpus[0]);
50+
4851
z_arm64_bss_zero();
4952
#ifdef CONFIG_XIP
5053
z_data_copy();

arch/arm64/core/smp.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ void z_arm64_secondary_start(void)
6565
arch_cpustart_t fn;
6666
int cpu_num = MPIDR_TO_CORE(GET_MPIDR());
6767

68+
/* Initialize tpidrro_el0 with our struct _cpu instance address */
69+
write_tpidrro_el0((uintptr_t)&_kernel.cpus[cpu_num]);
70+
6871
z_arm64_mmu_init();
6972

7073
#ifdef CONFIG_SMP

arch/arm64/core/thread.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
5353
pInitCtx->elr = (uint64_t)z_thread_entry;
5454
}
5555

56-
pInitCtx->tpidrro_el0 = 0x0;
5756
thread->arch.priv_stack_start = 0;
5857
#else
5958
pInitCtx->elr = (uint64_t)z_thread_entry;
@@ -104,9 +103,6 @@ FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
104103
pInitCtx->spsr = DAIF_FIQ_BIT | SPSR_MODE_EL0T;
105104
pInitCtx->elr = (uint64_t)z_thread_entry;
106105

107-
/* The thread will be in user context */
108-
pInitCtx->tpidrro_el0 = 0x1;
109-
110106
pInitCtx->x0 = (uint64_t)user_entry;
111107
pInitCtx->x1 = (uint64_t)p1;
112108
pInitCtx->x2 = (uint64_t)p2;

arch/arm64/core/userspace.S

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,8 @@ valid_syscall_id:
110110
ldr x9, [x9, x8, lsl #3]
111111

112112
/* Recover the privileged stack */
113-
#ifdef CONFIG_SMP
114-
get_cpu x10, x8
113+
get_cpu x10
115114
ldr x10, [x10, #___cpu_t_current_OFFSET]
116-
#else
117-
ldr x10, =_kernel
118-
ldr x10, [x10, #_kernel_offset_to_current]
119-
#endif
120115
ldr x10, [x10, #_thread_offset_to_priv_stack_start]
121116
add x10, x10, #CONFIG_PRIVILEGED_STACK_SIZE
122117

arch/arm64/core/vector_table.S

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010

1111
#include <toolchain.h>
1212
#include <linker/sections.h>
13+
#include <offsets.h>
1314
#include <arch/cpu.h>
14-
#include <offsets_short.h>
15+
#include <arch/arm64/tpidrro_el0.h>
1516
#include "vector_table.h"
1617

1718
_ASM_FILE_PROLOGUE
@@ -56,12 +57,10 @@ _ASM_FILE_PROLOGUE
5657
stp \xreg0, \xreg1, [sp, ___esf_t_spsr_elr_OFFSET]
5758

5859
#ifdef CONFIG_USERSPACE
59-
/* Save the current kernel/user mode in the context */
60+
/* Clear usermode flag */
6061
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
62+
bic \xreg0, \xreg0, #TPIDRROEL0_IN_EL0
63+
msr tpidrro_el0, \xreg0
6564
#endif
6665

6766
.endm
@@ -219,8 +218,12 @@ SECTION_FUNC(TEXT, z_arm64_exit_exc)
219218

220219
#ifdef CONFIG_USERSPACE
221220
/* Restore the kernel/user mode flag */
222-
ldr x0, [sp, ___esf_t_tpidrro_el0_OFFSET]
221+
tst x0, #SPSR_MODE_MASK /* EL0 == 0 */
222+
bne 1f
223+
mrs x0, tpidrro_el0
224+
orr x0, x0, #TPIDRROEL0_IN_EL0
223225
msr tpidrro_el0, x0
226+
1:
224227
#endif
225228

226229
ldp x0, x1, [sp, ___esf_t_x0_x1_OFFSET]

include/arch/arm64/arch_inlines.h

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,12 @@
1010
#ifndef _ASMLANGUAGE
1111

1212
#include <kernel_structs.h>
13-
#include <arch/cpu.h>
1413
#include <arch/arm64/lib_helpers.h>
14+
#include <arch/arm64/tpidrro_el0.h>
1515

1616
static ALWAYS_INLINE _cpu_t *arch_curr_cpu(void)
1717
{
18-
#ifdef CONFIG_SMP
19-
uint64_t core;
20-
21-
/* Note: Only support one Cluster */
22-
core = MPIDR_TO_CORE(GET_MPIDR());
23-
24-
return &_kernel.cpus[core];
25-
#else
26-
return &_kernel.cpus[0];
27-
#endif /* CONFIG_SMP */
18+
return (_cpu_t *)(read_tpidrro_el0() & TPIDRROEL0_CURR_CPU);
2819
}
2920

3021
#endif /* !_ASMLANGUAGE */

include/arch/arm64/cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#define SPSR_MODE_EL1H (0x5)
3333
#define SPSR_MODE_EL2T (0x8)
3434
#define SPSR_MODE_EL2H (0x9)
35+
#define SPSR_MODE_MASK (0xf)
3536

3637

3738
#define SCTLR_EL3_RES1 (BIT(29) | BIT(28) | BIT(23) | \

include/arch/arm64/exc.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ 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
5350
} __aligned(16);
5451

5552
typedef struct __esf z_arch_esf_t;

0 commit comments

Comments
 (0)