Skip to content

Commit

Permalink
arm64/sme: Implement support for TPIDR2
Browse files Browse the repository at this point in the history
The Scalable Matrix Extension introduces support for a new thread specific
data register TPIDR2 intended for use by libc. The kernel must save the
value of TPIDR2 on context switch and should ensure that all new threads
start off with a default value of 0. Add a field to the thread_struct to
store TPIDR2 and context switch it with the other thread specific data.

In case there are future extensions which also use TPIDR2 we introduce
system_supports_tpidr2() and use that rather than system_supports_sme()
for TPIDR2 handling.

Signed-off-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/20220419112247.711548-13-broonie@kernel.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
  • Loading branch information
Mark Brown authored and Catalin Marinas committed Apr 22, 2022
1 parent 9e4ab6c commit a9d6915
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 2 deletions.
5 changes: 5 additions & 0 deletions arch/arm64/include/asm/cpufeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,11 @@ static __always_inline bool system_supports_fa64(void)
cpus_have_const_cap(ARM64_SME_FA64);
}

static __always_inline bool system_supports_tpidr2(void)
{
return system_supports_sme();
}

static __always_inline bool system_supports_cnp(void)
{
return IS_ENABLED(CONFIG_ARM64_CNP) &&
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ struct thread_struct {
u64 mte_ctrl;
#endif
u64 sctlr_user;
u64 tpidr2_el0;
};

static inline unsigned int thread_get_vl(struct thread_struct *thread,
Expand Down
4 changes: 4 additions & 0 deletions arch/arm64/kernel/fpsimd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,10 @@ void sme_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
/* Allow SME in kernel */
write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_SMEN_EL1EN, CPACR_EL1);
isb();

/* Allow EL0 to access TPIDR2 */
write_sysreg(read_sysreg(SCTLR_EL1) | SCTLR_ELx_ENTP2, SCTLR_EL1);
isb();
}

/*
Expand Down
14 changes: 12 additions & 2 deletions arch/arm64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ void show_regs(struct pt_regs *regs)
static void tls_thread_flush(void)
{
write_sysreg(0, tpidr_el0);
if (system_supports_tpidr2())
write_sysreg_s(0, SYS_TPIDR2_EL0);

if (is_compat_task()) {
current->thread.uw.tp_value = 0;
Expand Down Expand Up @@ -343,6 +345,8 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
* out-of-sync with the saved value.
*/
*task_user_tls(p) = read_sysreg(tpidr_el0);
if (system_supports_tpidr2())
p->thread.tpidr2_el0 = read_sysreg_s(SYS_TPIDR2_EL0);

if (stack_start) {
if (is_compat_thread(task_thread_info(p)))
Expand All @@ -353,10 +357,12 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,

/*
* If a TLS pointer was passed to clone, use it for the new
* thread.
* thread. We also reset TPIDR2 if it's in use.
*/
if (clone_flags & CLONE_SETTLS)
if (clone_flags & CLONE_SETTLS) {
p->thread.uw.tp_value = tls;
p->thread.tpidr2_el0 = 0;
}
} else {
/*
* A kthread has no context to ERET to, so ensure any buggy
Expand Down Expand Up @@ -387,6 +393,8 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
void tls_preserve_current_state(void)
{
*task_user_tls(current) = read_sysreg(tpidr_el0);
if (system_supports_tpidr2() && !is_compat_task())
current->thread.tpidr2_el0 = read_sysreg_s(SYS_TPIDR2_EL0);
}

static void tls_thread_switch(struct task_struct *next)
Expand All @@ -399,6 +407,8 @@ static void tls_thread_switch(struct task_struct *next)
write_sysreg(0, tpidrro_el0);

write_sysreg(*task_user_tls(next), tpidr_el0);
if (system_supports_tpidr2())
write_sysreg_s(next->thread.tpidr2_el0, SYS_TPIDR2_EL0);
}

/*
Expand Down

0 comments on commit a9d6915

Please sign in to comment.