From patchwork Mon Nov 15 15:28:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 12619815 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4CF7C433EF for ; Mon, 15 Nov 2021 15:31:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9A0E963212 for ; Mon, 15 Nov 2021 15:31:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236702AbhKOPd4 (ORCPT ); Mon, 15 Nov 2021 10:33:56 -0500 Received: from mail.kernel.org ([198.145.29.99]:52458 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236500AbhKOPci (ORCPT ); Mon, 15 Nov 2021 10:32:38 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id E37FF63213; Mon, 15 Nov 2021 15:29:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1636990182; bh=eT4sFfkvqP5IKHbiucXxT/uXo0IzztyGi1fbDq3eAVc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cbC7mRIQWvuBiCwmOZD887bpP80m8Cb2gXWS+jAfuQAV7Gngcqhdnc/1rS3lG1eLE p8ZjVJOF5xDuPw/sXjDR+fYfMYhFq3uX5mo8lKw+VjG5NHgAYtP80hpkSFiUhymmUt pdDEx6RDplmJ2JvczfTWoJf6Dw3gJfbZPKF+EcGv11fjoDrIbC5hRwFj1PtKcgnOin nKAk4Yad/tCpws0Xy+6lM1kzYcNQ20PcUnn5wdkxrixCYT5CST+aLUWzpgITDyolKj 0UqczKDzKu3zZC/FIPU0d5I/+bD+E3tkU5JCJzbEpC9vXONgGR/U2tgeplySaGT9FL 7OoCPzSEbNRug== From: Mark Brown To: Catalin Marinas , Will Deacon , Shuah Khan , Shuah Khan Cc: Alan Hayward , Luis Machado , Salil Akerkar , Basant Kumar Dwivedi , Szabolcs Nagy , linux-arm-kernel@lists.infradead.org, linux-kselftest@vger.kernel.org, Mark Brown Subject: [PATCH v6 17/37] arm64/sme: Implement support for TPIDR2 Date: Mon, 15 Nov 2021 15:28:15 +0000 Message-Id: <20211115152835.3212149-18-broonie@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211115152835.3212149-1-broonie@kernel.org> References: <20211115152835.3212149-1-broonie@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4258; h=from:subject; bh=eT4sFfkvqP5IKHbiucXxT/uXo0IzztyGi1fbDq3eAVc=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBhknyS1Lzp80PTRFnHXKwfnEM/0J9uI+LsOEY7yRro aUhtbVaJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCYZJ8kgAKCRAk1otyXVSH0EoTB/ 9JEBbDLh9bb1a/GuB6cL3cnLSWlhcBreA3SQ4GKum6NFjBllgCliva5y9bUpU+1t4UutgksMcnvZVE uspnhUkXOUUHyHgWZ7OW4imAtbKn0MQGYkTeFwx7BUIpZV9cpVUiffeKJWYbwpgYO031DWTkjsU1tZ V/eACtSnKOZrvBm3yWpjUzbvqGnXJEGJ11z/WqohHZiBcyn7W69RlDzzkOrp2G7B4ABlqG3sMja7H9 TgiHVSNKZn2xti2laCdb22Ys3FDoHx1QYuk/Ug1xO/gJIqkOw0bnxyZaEOq4IIEQ2/KWY5lCgzYSQw ngQ7m6ZWAvuskP40KmXczXQy+ZQhi5 X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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 --- arch/arm64/include/asm/cpufeature.h | 5 +++++ arch/arm64/include/asm/processor.h | 1 + arch/arm64/kernel/fpsimd.c | 4 ++++ arch/arm64/kernel/process.c | 14 ++++++++++++-- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index c5fee98307cb..d67246141b7c 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -746,6 +746,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) && diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index f2c2ebd440e2..008a1767ebff 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -168,6 +168,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, diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 20c889487193..0af82c518979 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -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(); } /* diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index aacf2f5559a8..3adca0123943 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -249,6 +249,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; @@ -342,6 +344,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))) @@ -352,10 +356,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 @@ -386,6 +392,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) @@ -398,6 +406,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); } /*