All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb@kernel.org>
To: linux@armlinux.org.uk, linux-arm-kernel@lists.infradead.org
Cc: linux-hardening@vger.kernel.org, Ard Biesheuvel <ardb@kernel.org>,
	Nicolas Pitre <nico@fluxnic.net>, Arnd Bergmann <arnd@arndb.de>,
	Kees Cook <keescook@chromium.org>,
	Keith Packard <keithpac@amazon.com>,
	Linus Walleij <linus.walleij@linaro.org>,
	Nick Desaulniers <ndesaulniers@google.com>,
	Tony Lindgren <tony@atomide.com>, Marc Zyngier <maz@kernel.org>,
	Vladimir Murzin <vladimir.murzin@arm.com>,
	Jesse Taube <mr.bossman075@gmail.com>
Subject: [PATCH v5 15/32] ARM: smp: defer TPIDRURO update for SMP v6 configurations too
Date: Mon, 24 Jan 2022 18:47:27 +0100	[thread overview]
Message-ID: <20220124174744.1054712-16-ardb@kernel.org> (raw)
In-Reply-To: <20220124174744.1054712-1-ardb@kernel.org>

Defer TPIDURO updates for user space until exit also for CPU_V6+SMP
configurations so that we can decide at runtime whether to use it to
carry the current pointer, provided that we are running on a CPU that
actually implements this register. This is needed for
THREAD_INFO_IN_TASK support for UP systems, which requires that all SMP
capable systems use the TPIDRURO based access to 'current' as the only
remaining alternative will be a global variable which only works on UP.

Given that SMP implies support for HWCAP_TLS, we can patch away the
hwcap test entirely from the context switch path rather than just the
TPIDRURO assignment when running on SMP hardware.

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Nicolas Pitre <nico@fluxnic.net>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Tested-by: Marc Zyngier <maz@kernel.org>
Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> # ARMv7M
---
 arch/arm/include/asm/tls.h     | 30 +++++++++++++-------
 arch/arm/kernel/entry-header.S |  8 +++++-
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h
index c3296499176c..de254347acf6 100644
--- a/arch/arm/include/asm/tls.h
+++ b/arch/arm/include/asm/tls.h
@@ -18,21 +18,31 @@
 	.endm
 
 	.macro switch_tls_v6, base, tp, tpuser, tmp1, tmp2
-	ldr	\tmp1, =elf_hwcap
-	ldr	\tmp1, [\tmp1, #0]
+#ifdef CONFIG_SMP
+ALT_SMP(nop)
+ALT_UP_B(.L0_\@)
+	.subsection 1
+#endif
+.L0_\@: ldr_va	\tmp1, elf_hwcap
 	mov	\tmp2, #0xffff0fff
 	tst	\tmp1, #HWCAP_TLS		@ hardware TLS available?
 	streq	\tp, [\tmp2, #-15]		@ set TLS value at 0xffff0ff0
-	mrcne	p15, 0, \tmp2, c13, c0, 2	@ get the user r/w register
-	mcrne	p15, 0, \tp, c13, c0, 3		@ yes, set TLS register
-	mcrne	p15, 0, \tpuser, c13, c0, 2	@ set user r/w register
-	strne	\tmp2, [\base, #TI_TP_VALUE + 4] @ save it
+	beq	.L2_\@
+	mcr	p15, 0, \tp, c13, c0, 3		@ yes, set TLS register
+#ifdef CONFIG_SMP
+	b	.L1_\@
+	.previous
+#endif
+.L1_\@: switch_tls_v6k \base, \tp, \tpuser, \tmp1, \tmp2
+.L2_\@:
 	.endm
 
 	.macro switch_tls_software, base, tp, tpuser, tmp1, tmp2
 	mov	\tmp1, #0xffff0fff
 	str	\tp, [\tmp1, #-15]		@ set TLS value at 0xffff0ff0
 	.endm
+#else
+#include <asm/smp_plat.h>
 #endif
 
 #ifdef CONFIG_TLS_REG_EMUL
@@ -43,7 +53,7 @@
 #elif defined(CONFIG_CPU_V6)
 #define tls_emu		0
 #define has_tls_reg		(elf_hwcap & HWCAP_TLS)
-#define defer_tls_reg_update	0
+#define defer_tls_reg_update	is_smp()
 #define switch_tls	switch_tls_v6
 #elif defined(CONFIG_CPU_32v6K)
 #define tls_emu		0
@@ -81,11 +91,11 @@ static inline void set_tls(unsigned long val)
 	 */
 	barrier();
 
-	if (!tls_emu && !defer_tls_reg_update) {
-		if (has_tls_reg) {
+	if (!tls_emu) {
+		if (has_tls_reg && !defer_tls_reg_update) {
 			asm("mcr p15, 0, %0, c13, c0, 3"
 			    : : "r" (val));
-		} else {
+		} else if (!has_tls_reg) {
 #ifdef CONFIG_KUSER_HELPERS
 			/*
 			 * User space must never try to access this
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index ae24dd54e9ef..da206bd4f194 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -292,12 +292,18 @@
 
 
 	.macro	restore_user_regs, fast = 0, offset = 0
-#if defined(CONFIG_CPU_32v6K) && !defined(CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_32v6K) && \
+    (!defined(CONFIG_CPU_V6) || defined(CONFIG_SMP))
+#ifdef CONFIG_CPU_V6
+ALT_SMP(nop)
+ALT_UP_B(.L1_\@)
+#endif
 	@ The TLS register update is deferred until return to user space so we
 	@ can use it for other things while running in the kernel
 	get_thread_info r1
 	ldr	r1, [r1, #TI_TP_VALUE]
 	mcr	p15, 0, r1, c13, c0, 3		@ set TLS register
+.L1_\@:
 #endif
 
 	uaccess_enable r1, isb=0
-- 
2.30.2


WARNING: multiple messages have this Message-ID (diff)
From: Ard Biesheuvel <ardb@kernel.org>
To: linux@armlinux.org.uk, linux-arm-kernel@lists.infradead.org
Cc: linux-hardening@vger.kernel.org, Ard Biesheuvel <ardb@kernel.org>,
	Nicolas Pitre <nico@fluxnic.net>, Arnd Bergmann <arnd@arndb.de>,
	Kees Cook <keescook@chromium.org>,
	Keith Packard <keithpac@amazon.com>,
	Linus Walleij <linus.walleij@linaro.org>,
	Nick Desaulniers <ndesaulniers@google.com>,
	Tony Lindgren <tony@atomide.com>, Marc Zyngier <maz@kernel.org>,
	Vladimir Murzin <vladimir.murzin@arm.com>,
	Jesse Taube <mr.bossman075@gmail.com>
Subject: [PATCH v5 15/32] ARM: smp: defer TPIDRURO update for SMP v6 configurations too
Date: Mon, 24 Jan 2022 18:47:27 +0100	[thread overview]
Message-ID: <20220124174744.1054712-16-ardb@kernel.org> (raw)
In-Reply-To: <20220124174744.1054712-1-ardb@kernel.org>

Defer TPIDURO updates for user space until exit also for CPU_V6+SMP
configurations so that we can decide at runtime whether to use it to
carry the current pointer, provided that we are running on a CPU that
actually implements this register. This is needed for
THREAD_INFO_IN_TASK support for UP systems, which requires that all SMP
capable systems use the TPIDRURO based access to 'current' as the only
remaining alternative will be a global variable which only works on UP.

Given that SMP implies support for HWCAP_TLS, we can patch away the
hwcap test entirely from the context switch path rather than just the
TPIDRURO assignment when running on SMP hardware.

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Nicolas Pitre <nico@fluxnic.net>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Tested-by: Marc Zyngier <maz@kernel.org>
Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> # ARMv7M
---
 arch/arm/include/asm/tls.h     | 30 +++++++++++++-------
 arch/arm/kernel/entry-header.S |  8 +++++-
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h
index c3296499176c..de254347acf6 100644
--- a/arch/arm/include/asm/tls.h
+++ b/arch/arm/include/asm/tls.h
@@ -18,21 +18,31 @@
 	.endm
 
 	.macro switch_tls_v6, base, tp, tpuser, tmp1, tmp2
-	ldr	\tmp1, =elf_hwcap
-	ldr	\tmp1, [\tmp1, #0]
+#ifdef CONFIG_SMP
+ALT_SMP(nop)
+ALT_UP_B(.L0_\@)
+	.subsection 1
+#endif
+.L0_\@: ldr_va	\tmp1, elf_hwcap
 	mov	\tmp2, #0xffff0fff
 	tst	\tmp1, #HWCAP_TLS		@ hardware TLS available?
 	streq	\tp, [\tmp2, #-15]		@ set TLS value at 0xffff0ff0
-	mrcne	p15, 0, \tmp2, c13, c0, 2	@ get the user r/w register
-	mcrne	p15, 0, \tp, c13, c0, 3		@ yes, set TLS register
-	mcrne	p15, 0, \tpuser, c13, c0, 2	@ set user r/w register
-	strne	\tmp2, [\base, #TI_TP_VALUE + 4] @ save it
+	beq	.L2_\@
+	mcr	p15, 0, \tp, c13, c0, 3		@ yes, set TLS register
+#ifdef CONFIG_SMP
+	b	.L1_\@
+	.previous
+#endif
+.L1_\@: switch_tls_v6k \base, \tp, \tpuser, \tmp1, \tmp2
+.L2_\@:
 	.endm
 
 	.macro switch_tls_software, base, tp, tpuser, tmp1, tmp2
 	mov	\tmp1, #0xffff0fff
 	str	\tp, [\tmp1, #-15]		@ set TLS value at 0xffff0ff0
 	.endm
+#else
+#include <asm/smp_plat.h>
 #endif
 
 #ifdef CONFIG_TLS_REG_EMUL
@@ -43,7 +53,7 @@
 #elif defined(CONFIG_CPU_V6)
 #define tls_emu		0
 #define has_tls_reg		(elf_hwcap & HWCAP_TLS)
-#define defer_tls_reg_update	0
+#define defer_tls_reg_update	is_smp()
 #define switch_tls	switch_tls_v6
 #elif defined(CONFIG_CPU_32v6K)
 #define tls_emu		0
@@ -81,11 +91,11 @@ static inline void set_tls(unsigned long val)
 	 */
 	barrier();
 
-	if (!tls_emu && !defer_tls_reg_update) {
-		if (has_tls_reg) {
+	if (!tls_emu) {
+		if (has_tls_reg && !defer_tls_reg_update) {
 			asm("mcr p15, 0, %0, c13, c0, 3"
 			    : : "r" (val));
-		} else {
+		} else if (!has_tls_reg) {
 #ifdef CONFIG_KUSER_HELPERS
 			/*
 			 * User space must never try to access this
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index ae24dd54e9ef..da206bd4f194 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -292,12 +292,18 @@
 
 
 	.macro	restore_user_regs, fast = 0, offset = 0
-#if defined(CONFIG_CPU_32v6K) && !defined(CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_32v6K) && \
+    (!defined(CONFIG_CPU_V6) || defined(CONFIG_SMP))
+#ifdef CONFIG_CPU_V6
+ALT_SMP(nop)
+ALT_UP_B(.L1_\@)
+#endif
 	@ The TLS register update is deferred until return to user space so we
 	@ can use it for other things while running in the kernel
 	get_thread_info r1
 	ldr	r1, [r1, #TI_TP_VALUE]
 	mcr	p15, 0, r1, c13, c0, 3		@ set TLS register
+.L1_\@:
 #endif
 
 	uaccess_enable r1, isb=0
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2022-01-24 17:48 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-24 17:47 [PATCH v5 00/32] ARM vmap'ed and IRQ stacks roundup Ard Biesheuvel
2022-01-24 17:47 ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 01/32] ARM: riscpc: drop support for IOMD_IRQREQC/IOMD_IRQREQD IRQ groups Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 02/32] ARM: riscpc: use GENERIC_IRQ_MULTI_HANDLER Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 03/32] ARM: footbridge: " Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 04/32] ARM: iop32x: offset IRQ numbers by 1 Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 05/32] ARM: iop32x: use GENERIC_IRQ_MULTI_HANDLER Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 06/32] ARM: remove old-style irq entry Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 07/32] irqchip: nvic: Use GENERIC_IRQ_MULTI_HANDLER Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 08/32] ARM: decompressor: disable stack protector Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 09/32] ARM: stackprotector: prefer compiler for TLS based per-task protector Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 10/32] ARM: entry: preserve thread_info pointer in switch_to Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 11/32] ARM: module: implement support for PC-relative group relocations Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 12/32] ARM: assembler: add optimized ldr/str macros to load variables from memory Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 13/32] ARM: percpu: add SMP_ON_UP support Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 14/32] ARM: use TLS register for 'current' on !SMP as well Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` Ard Biesheuvel [this message]
2022-01-24 17:47   ` [PATCH v5 15/32] ARM: smp: defer TPIDRURO update for SMP v6 configurations too Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 16/32] ARM: implement THREAD_INFO_IN_TASK for uniprocessor systems Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 17/32] ARM: assembler: introduce bl_r macro Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 18/32] ARM: unwind: support unwinding across multiple stacks Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 19/32] ARM: export dump_mem() to other objects Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 20/32] ARM: unwind: dump exception stack from calling frame Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 21/32] ARM: backtrace-clang: avoid crash on bogus frame pointer Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 22/32] ARM: implement IRQ stacks Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 23/32] ARM: call_with_stack: add unwind support Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 24/32] ARM: run softirqs on the per-CPU IRQ stack Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-03-22  9:04   ` Sebastian Andrzej Siewior
2022-03-22  9:04     ` Sebastian Andrzej Siewior
2022-03-22  9:35     ` Ard Biesheuvel
2022-03-22  9:35       ` Ard Biesheuvel
2022-03-22 11:29       ` Sebastian Andrzej Siewior
2022-03-22 11:29         ` Sebastian Andrzej Siewior
2022-01-24 17:47 ` [PATCH v5 25/32] ARM: memcpy: use frame pointer as unwind anchor Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 26/32] ARM: memmove: " Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 27/32] ARM: memset: clean up unwind annotations Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 28/32] ARM: unwind: disregard unwind info before stack frame is set up Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 29/32] ARM: entry: rework stack realignment code in svc_entry Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 30/32] ARM: switch_to: clean up Thumb2 code path Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 31/32] ARM: mm: prepare vmalloc_seq handling for use under SMP Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:47 ` [PATCH v5 32/32] ARM: implement support for vmap'ed stacks Ard Biesheuvel
2022-01-24 17:47   ` Ard Biesheuvel
2022-01-24 17:56 ` [PATCH v5 00/32] ARM vmap'ed and IRQ stacks roundup Russell King (Oracle)
2022-01-24 17:56   ` Russell King (Oracle)
2022-01-24 17:57   ` Ard Biesheuvel
2022-01-24 17:57     ` Ard Biesheuvel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220124174744.1054712-16-ardb@kernel.org \
    --to=ardb@kernel.org \
    --cc=arnd@arndb.de \
    --cc=keescook@chromium.org \
    --cc=keithpac@amazon.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=maz@kernel.org \
    --cc=mr.bossman075@gmail.com \
    --cc=ndesaulniers@google.com \
    --cc=nico@fluxnic.net \
    --cc=tony@atomide.com \
    --cc=vladimir.murzin@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.