linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb+git@google.com>
To: linux-arm-kernel@lists.infradead.org
Cc: Ard Biesheuvel <ardb@kernel.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	 Will Deacon <will@kernel.org>, Marc Zyngier <maz@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	 Ryan Roberts <ryan.roberts@arm.com>,
	Anshuman Khandual <anshuman.khandual@arm.com>,
	 Kees Cook <keescook@chromium.org>
Subject: [PATCH v8 25/43] arm64: mm: Handle LVA support as a CPU feature
Date: Wed, 14 Feb 2024 13:29:11 +0100	[thread overview]
Message-ID: <20240214122845.2033971-70-ardb+git@google.com> (raw)
In-Reply-To: <20240214122845.2033971-45-ardb+git@google.com>

From: Ard Biesheuvel <ardb@kernel.org>

Currently, we detect CPU support for 52-bit virtual addressing (LVA)
extremely early, before creating the kernel page tables or enabling the
MMU. We cannot override the feature this early, and so large virtual
addressing is always enabled on CPUs that implement support for it if
the software support for it was enabled at build time. It also means we
rely on non-trivial code in asm to deal with this feature.

Given that both the ID map and the TTBR1 mapping of the kernel image are
guaranteed to be 48-bit addressable, it is not actually necessary to
enable support this early, and instead, we can model it as a CPU
feature. That way, we can rely on code patching to get the correct
TCR.T1SZ values programmed on secondary boot and resume from suspend.

On the primary boot path, we simply enable the MMU with 48-bit virtual
addressing initially, and update TCR.T1SZ if LVA is supported from C
code, right before creating the kernel mapping. Given that TTBR1 still
points to reserved_pg_dir at this point, updating TCR.T1SZ should be
safe without the need for explicit TLB maintenance.

Since this gets rid of all accesses to the vabits_actual variable from
asm code that occurred before TCR.T1SZ had been programmed, we no longer
have a need for this variable, and we can replace it with a C expression
that produces the correct value directly, based on the value of TCR.T1SZ.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/include/asm/cpufeature.h |  9 ++++++
 arch/arm64/include/asm/memory.h     | 13 ++++++++-
 arch/arm64/kernel/cpufeature.c      | 13 +++++++++
 arch/arm64/kernel/head.S            | 29 +++++---------------
 arch/arm64/kernel/image-vars.h      |  1 -
 arch/arm64/kernel/pi/map_kernel.c   |  3 ++
 arch/arm64/kernel/sleep.S           |  3 --
 arch/arm64/mm/mmu.c                 |  5 ----
 arch/arm64/mm/proc.S                |  9 +++---
 arch/arm64/tools/cpucaps            |  1 +
 10 files changed, 49 insertions(+), 37 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index e3edae1825f3..4f4dc5496ee3 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -995,6 +995,15 @@ static inline bool cpu_has_pac(void)
 					    &id_aa64isar2_override);
 }
 
+static inline bool cpu_has_lva(void)
+{
+	u64 mmfr2;
+
+	mmfr2 = read_sysreg_s(SYS_ID_AA64MMFR2_EL1);
+	return cpuid_feature_extract_unsigned_field(mmfr2,
+						    ID_AA64MMFR2_EL1_VARange_SHIFT);
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 60904a6c4b42..9680d7444b3b 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -209,9 +209,20 @@
 #include <asm/boot.h>
 #include <asm/bug.h>
 #include <asm/sections.h>
+#include <asm/sysreg.h>
+
+static inline u64 __pure read_tcr(void)
+{
+	u64  tcr;
+
+	// read_sysreg() uses asm volatile, so avoid it here
+	asm("mrs %0, tcr_el1" : "=r"(tcr));
+	return tcr;
+}
 
 #if VA_BITS > 48
-extern u64			vabits_actual;
+// For reasons of #include hell, we can't use TCR_T1SZ_OFFSET/TCR_T1SZ_MASK here
+#define vabits_actual		(64 - ((read_tcr() >> 16) & 63))
 #else
 #define vabits_actual		((u64)VA_BITS)
 #endif
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 7064cf13f226..8eb8c7f7b317 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2692,6 +2692,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_lpa2,
 	},
+#ifdef CONFIG_ARM64_VA_BITS_52
+	{
+		.desc = "52-bit Virtual Addressing (LVA)",
+		.capability = ARM64_HAS_VA52,
+		.type = ARM64_CPUCAP_BOOT_CPU_FEATURE,
+		.sys_reg = SYS_ID_AA64MMFR2_EL1,
+		.sign = FTR_UNSIGNED,
+		.field_width = 4,
+		.field_pos = ID_AA64MMFR2_EL1_VARange_SHIFT,
+		.matches = has_cpuid_feature,
+		.min_field_value = ID_AA64MMFR2_EL1_VARange_52,
+	},
+#endif
 	{},
 };
 
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 545b5d8976f4..e25351addfd0 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -80,7 +80,6 @@
 	 *  x19        primary_entry() .. start_kernel()        whether we entered with the MMU on
 	 *  x20        primary_entry() .. __primary_switch()    CPU boot mode
 	 *  x21        primary_entry() .. start_kernel()        FDT pointer passed at boot in x0
-	 *  x25        primary_entry() .. start_kernel()        supported VA size
 	 */
 SYM_CODE_START(primary_entry)
 	bl	record_mmu_state
@@ -125,14 +124,6 @@ SYM_CODE_START(primary_entry)
 	 * On return, the CPU will be ready for the MMU to be turned on and
 	 * the TCR will have been set.
 	 */
-#if VA_BITS > 48
-	mrs_s	x0, SYS_ID_AA64MMFR2_EL1
-	tst	x0, ID_AA64MMFR2_EL1_VARange_MASK
-	mov	x0, #VA_BITS
-	mov	x25, #VA_BITS_MIN
-	csel	x25, x25, x0, eq
-	mov	x0, x25
-#endif
 	bl	__cpu_setup			// initialise processor
 	b	__primary_switch
 SYM_CODE_END(primary_entry)
@@ -242,11 +233,6 @@ SYM_FUNC_START_LOCAL(__primary_switched)
 	mov	x0, x20
 	bl	set_cpu_boot_mode_flag
 
-#if VA_BITS > 48
-	adr_l	x8, vabits_actual		// Set this early so KASAN early init
-	str	x25, [x8]			// ... observes the correct value
-	dc	civac, x8			// Make visible to booting secondaries
-#endif
 #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
 	bl	kasan_early_init
 #endif
@@ -376,10 +362,13 @@ SYM_FUNC_START_LOCAL(secondary_startup)
 	 * Common entry point for secondary CPUs.
 	 */
 	mov	x20, x0				// preserve boot mode
+
+#ifdef CONFIG_ARM64_VA_BITS_52
+alternative_if ARM64_HAS_VA52
 	bl	__cpu_secondary_check52bitva
-#if VA_BITS > 48
-	ldr_l	x0, vabits_actual
+alternative_else_nop_endif
 #endif
+
 	bl	__cpu_setup			// initialise processor
 	adrp	x1, swapper_pg_dir
 	adrp	x2, idmap_pg_dir
@@ -482,12 +471,8 @@ SYM_FUNC_START(__enable_mmu)
 	ret
 SYM_FUNC_END(__enable_mmu)
 
+#ifdef CONFIG_ARM64_VA_BITS_52
 SYM_FUNC_START(__cpu_secondary_check52bitva)
-#if VA_BITS > 48
-	ldr_l	x0, vabits_actual
-	cmp	x0, #52
-	b.ne	2f
-
 	mrs_s	x0, SYS_ID_AA64MMFR2_EL1
 	and	x0, x0, ID_AA64MMFR2_EL1_VARange_MASK
 	cbnz	x0, 2f
@@ -498,9 +483,9 @@ SYM_FUNC_START(__cpu_secondary_check52bitva)
 	wfi
 	b	1b
 
-#endif
 2:	ret
 SYM_FUNC_END(__cpu_secondary_check52bitva)
+#endif
 
 SYM_FUNC_START_LOCAL(__no_granule_support)
 	/* Indicate that this CPU can't boot and is stuck in the kernel */
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index e140c5bda90b..2b9d702abe0f 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -36,7 +36,6 @@ PROVIDE(__pi___memcpy			= __pi_memcpy);
 PROVIDE(__pi___memmove			= __pi_memmove);
 PROVIDE(__pi___memset			= __pi_memset);
 
-PROVIDE(__pi_vabits_actual		= vabits_actual);
 PROVIDE(__pi_id_aa64isar1_override	= id_aa64isar1_override);
 PROVIDE(__pi_id_aa64isar2_override	= id_aa64isar2_override);
 PROVIDE(__pi_id_aa64mmfr1_override	= id_aa64mmfr1_override);
diff --git a/arch/arm64/kernel/pi/map_kernel.c b/arch/arm64/kernel/pi/map_kernel.c
index 4b76a007a50d..1853825aa29d 100644
--- a/arch/arm64/kernel/pi/map_kernel.c
+++ b/arch/arm64/kernel/pi/map_kernel.c
@@ -165,6 +165,9 @@ asmlinkage void __init early_map_kernel(u64 boot_status, void *fdt)
 	chosen = fdt_path_offset(fdt, chosen_str);
 	init_feature_override(boot_status, fdt, chosen);
 
+	if (VA_BITS > VA_BITS_MIN && cpu_has_lva())
+		sysreg_clear_set(tcr_el1, TCR_T1SZ_MASK, TCR_T1SZ(VA_BITS));
+
 	/*
 	 * The virtual KASLR displacement modulo 2MiB is decided by the
 	 * physical placement of the image, as otherwise, we might not be able
diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index 2aa5129d8253..f093cdf71be1 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -102,9 +102,6 @@ SYM_CODE_START(cpu_resume)
 	mov	x0, xzr
 	bl	init_kernel_el
 	mov	x19, x0			// preserve boot mode
-#if VA_BITS > 48
-	ldr_l	x0, vabits_actual
-#endif
 	bl	__cpu_setup
 	/* enable the MMU early - so we can access sleep_save_stash by va */
 	adrp	x1, swapper_pg_dir
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index a3d23da92d87..ba00d0205447 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -45,11 +45,6 @@
 #define NO_CONT_MAPPINGS	BIT(1)
 #define NO_EXEC_MAPPINGS	BIT(2)	/* assumes FEAT_HPDS is not used */
 
-#if VA_BITS > 48
-u64 vabits_actual __ro_after_init = VA_BITS_MIN;
-EXPORT_SYMBOL(vabits_actual);
-#endif
-
 u64 kimage_voffset __ro_after_init;
 EXPORT_SYMBOL(kimage_voffset);
 
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 55c366dbda8f..d104ddab26a4 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -397,8 +397,6 @@ SYM_FUNC_END(idmap_kpti_install_ng_mappings)
  *
  *	Initialise the processor for turning the MMU on.
  *
- * Input:
- *	x0 - actual number of VA bits (ignored unless VA_BITS > 48)
  * Output:
  *	Return in x0 the value of the SCTLR_EL1 register.
  */
@@ -422,16 +420,17 @@ SYM_FUNC_START(__cpu_setup)
 	mair	.req	x17
 	tcr	.req	x16
 	mov_q	mair, MAIR_EL1_SET
-	mov_q	tcr, TCR_T0SZ(IDMAP_VA_BITS) | TCR_T1SZ(VA_BITS) | TCR_CACHE_FLAGS | \
+	mov_q	tcr, TCR_T0SZ(IDMAP_VA_BITS) | TCR_T1SZ(VA_BITS_MIN) | TCR_CACHE_FLAGS | \
 		     TCR_SMP_FLAGS | TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \
 		     TCR_TBI0 | TCR_A1 | TCR_KASAN_SW_FLAGS | TCR_MTE_FLAGS
 
 	tcr_clear_errata_bits tcr, x9, x5
 
 #ifdef CONFIG_ARM64_VA_BITS_52
-	sub		x9, xzr, x0
-	add		x9, x9, #64
+	mov		x9, #64 - VA_BITS
+alternative_if ARM64_HAS_VA52
 	tcr_set_t1sz	tcr, x9
+alternative_else_nop_endif
 #endif
 
 	/*
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index b912b1409fc0..b370d808b3ec 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -50,6 +50,7 @@ HAS_STAGE2_FWB
 HAS_TCR2
 HAS_TIDCP1
 HAS_TLB_RANGE
+HAS_VA52
 HAS_VIRT_HOST_EXTN
 HAS_WFXT
 HW_DBM
-- 
2.43.0.687.g38aa6559b0-goog


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

  parent reply	other threads:[~2024-02-14 12:32 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-14 12:28 [PATCH v8 00/43] arm64: Add support for LPA2 and WXN at stage 1 Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 01/43] arm64: kernel: Manage absolute relocations in code built under pi/ Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 02/43] arm64: kernel: Don't rely on objcopy to make code under pi/ __init Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 03/43] arm64: head: move relocation handling to C code Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 04/43] arm64: idreg-override: Move to early mini C runtime Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 05/43] arm64: kernel: Remove early fdt remap code Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 06/43] arm64: head: Clear BSS and the kernel page tables in one go Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 07/43] arm64: Move feature overrides into the BSS section Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 08/43] arm64: head: Run feature override detection before mapping the kernel Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 09/43] arm64: head: move dynamic shadow call stack patching into early C runtime Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 10/43] arm64: cpufeature: Add helper to test for CPU feature overrides Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 11/43] arm64: kaslr: Use feature override instead of parsing the cmdline again Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 12/43] arm64: idreg-override: Create a pseudo feature for rodata=off Ard Biesheuvel
2024-02-14 12:28 ` [PATCH v8 13/43] arm64: Add helpers to probe local CPU for PAC and BTI support Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 14/43] arm64: head: allocate more pages for the kernel mapping Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 15/43] arm64: head: move memstart_offset_seed handling to C code Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 16/43] arm64: mm: Make kaslr_requires_kpti() a static inline Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 17/43] arm64: mmu: Make __cpu_replace_ttbr1() out of line Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 18/43] arm64: head: Move early kernel mapping routines into C code Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 19/43] arm64: mm: Use 48-bit virtual addressing for the permanent ID map Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 20/43] arm64: pgtable: Decouple PGDIR size macros from PGD/PUD/PMD levels Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 21/43] arm64: kernel: Create initial ID map from C code Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 22/43] arm64: mm: avoid fixmap for early swapper_pg_dir updates Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 23/43] arm64: mm: omit redundant remap of kernel image Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 24/43] arm64: Revert "mm: provide idmap pointer to cpu_replace_ttbr1()" Ard Biesheuvel
2024-02-14 12:29 ` Ard Biesheuvel [this message]
2024-02-14 12:29 ` [PATCH v8 26/43] arm64: mm: Add feature override support for LVA Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 27/43] arm64: Avoid #define'ing PTE_MAYBE_NG to 0x0 for asm use Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 28/43] arm64: Add ESR decoding for exceptions involving translation level -1 Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 29/43] arm64: mm: Wire up TCR.DS bit to PTE shareability fields Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 30/43] arm64: mm: Add LPA2 support to phys<->pte conversion routines Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 31/43] arm64: mm: Add definitions to support 5 levels of paging Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 32/43] arm64: mm: add LPA2 and 5 level paging support to G-to-nG conversion Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 33/43] arm64: Enable LPA2 at boot if supported by the system Ard Biesheuvel
2024-08-06 16:16   ` Ryan Roberts
2024-08-07  8:46     ` Ryan Roberts
2024-08-07 21:41       ` Ryan Roberts
2024-08-27  9:03         ` Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 34/43] arm64: mm: Add 5 level paging support to fixmap and swapper handling Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 35/43] arm64: kasan: Reduce minimum shadow alignment and enable 5 level paging Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 36/43] arm64: mm: Add support for folding PUDs at runtime Ard Biesheuvel
2024-02-29 14:17   ` Ryan Roberts
2024-02-29 23:01     ` Nathan Chancellor
2024-03-01  8:54       ` Ryan Roberts
2024-03-01  9:10         ` Ard Biesheuvel
2024-03-01  9:37           ` Ard Biesheuvel
2024-03-01  9:47             ` Ryan Roberts
2024-03-01 10:22               ` Ryan Roberts
2024-09-30 14:36   ` Ryan Roberts
2024-09-30 14:53     ` Ard Biesheuvel
2024-09-30 15:12       ` Ryan Roberts
2024-10-01  6:23         ` Ard Biesheuvel
2024-10-02  9:08           ` Ryan Roberts
2024-10-12  9:47             ` Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 37/43] arm64: ptdump: Disregard unaddressable VA space Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 38/43] arm64: ptdump: Deal with translation levels folded at runtime Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 39/43] arm64: kvm: avoid CONFIG_PGTABLE_LEVELS for runtime levels Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 40/43] arm64: Enable 52-bit virtual addressing for 4k and 16k granule configs Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 41/43] arm64: defconfig: Enable LPA2 support Ard Biesheuvel
2024-02-14 12:29 ` [PATCH v8 42/43] mm: add arch hook to validate mmap() prot flags Ard Biesheuvel
2024-03-12 19:53   ` Catalin Marinas
2024-03-12 23:23     ` Ard Biesheuvel
2024-03-13 10:47       ` Catalin Marinas
2024-03-13 11:45         ` Ard Biesheuvel
2024-03-13 15:31           ` Catalin Marinas
2024-02-14 12:29 ` [PATCH v8 43/43] arm64: mm: add support for WXN memory translation attribute Ard Biesheuvel
2024-02-16 17:35 ` [PATCH v8 00/43] arm64: Add support for LPA2 and WXN at stage 1 Catalin Marinas
2024-02-16 18:23   ` Ard Biesheuvel
2024-02-16 22:34     ` 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=20240214122845.2033971-70-ardb+git@google.com \
    --to=ardb+git@google.com \
    --cc=anshuman.khandual@arm.com \
    --cc=ardb@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=keescook@chromium.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=ryan.roberts@arm.com \
    --cc=will@kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).