All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages
@ 2022-11-17 13:24 Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 1/7] arm64: ptdump: Disregard unaddressable VA space Ard Biesheuvel
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2022-11-17 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ard Biesheuvel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Catalin Marinas, Mark Brown, Anshuman Khandual,
	Richard Henderson

Enable support for LPA2 when running with 16k pages. Unlike with 4k
pages, this does not require adding support for 5 level paging, but
beyond that, there is no fundamental difference between LPA2 support on
4k or 16k pages.

There are a few rough edges that make this less straight-forward than it
was to enable LVA on 64k pages: even though also in this case, we can
rely on statically sized root level page tables, we cannot advance the
TTBR1 pointer to the pgdir entry that covers the start of the 48-bit
addressable like we do on LVA, as the resulting address is not 64 byte
aligned, which is a requirement for TTBR registers.

Another slight complication is that the repurposed physical address bits
in the page table descriptors were not RES0 before, and so there is now
a big global switch (called TCR.DS) which controls how all page table
descriptors are interpreted. This requires some extra care in the PTE
conversion helpers, and additional handling in the boot code to ensure
that we set TCR.DS safely if supported (and not overridden)

This series applies onto some of my previous work that is still in
flight, so these patches will not apply in isolation. Complete branch
can be found here:
https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=arm64-16k-lpa2

Tested on QEMU with -cpu max and lpa2 both off and on, as well as using
the arm64.nolva override kernel command line parameter. Note that this
requires a QEMU patch that has not been merged yet:
https://lore.kernel.org/qemu-devel/20221116170316.259695-1-ardb@kernel.org/

Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Richard Henderson <richard.henderson@linaro.org>

Ard Biesheuvel (7):
  arm64: ptdump: Disregard unaddressable VA space
  arm64: mm: Disable all 52-bit virtual addressing support with
    arm64.nolva
  arm64: mm: Wire up TCR.DS bit to PTE shareability fields
  arm64: mm: Support use of 52-bit pgdirs on 48-bit/16k systems
  arm64: mm: Add LPA2 support to phys<->pte conversion routines
  arm64: Enable LPA2 at boot if supported by the system
  arm64: Enable 52-bit virtual addressing for 16k granule configs

 arch/arm64/Kconfig                     |   6 +-
 arch/arm64/include/asm/assembler.h     |  33 ++-----
 arch/arm64/include/asm/cpufeature.h    |   1 +
 arch/arm64/include/asm/mmu.h           |  18 ++++
 arch/arm64/include/asm/pgtable-hwdef.h |  11 ++-
 arch/arm64/include/asm/pgtable-prot.h  |  18 +++-
 arch/arm64/include/asm/pgtable.h       |   5 +-
 arch/arm64/kernel/cpufeature.c         |  27 ++++-
 arch/arm64/kernel/image-vars.h         |   3 +
 arch/arm64/kernel/pi/idreg-override.c  |  26 +++++
 arch/arm64/kernel/pi/map_kernel.c      | 103 +++++++++++++++++++-
 arch/arm64/mm/mmap.c                   |   4 +
 arch/arm64/mm/mmu.c                    |   2 +
 arch/arm64/mm/proc.S                   |  13 +++
 arch/arm64/mm/ptdump.c                 |   4 +-
 15 files changed, 229 insertions(+), 45 deletions(-)

-- 
2.35.1


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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC PATCH 1/7] arm64: ptdump: Disregard unaddressable VA space
  2022-11-17 13:24 [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Ard Biesheuvel
@ 2022-11-17 13:24 ` Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 2/7] arm64: mm: Disable all 52-bit virtual addressing support with arm64.nolva Ard Biesheuvel
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2022-11-17 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ard Biesheuvel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Catalin Marinas, Mark Brown, Anshuman Khandual,
	Richard Henderson

Configurations built with support for 52-bit virtual addressing can also
run on CPUs that only support 48 bits of VA space, in which case only
that part of swapper_pg_dir that represents the 48-bit addressable
region is relevant, and everything else is ignored by the hardware.

In a future patch, we will clone the top 2 pgd_t entries at the bottom,
to support 52-bit VA configurations built for 16k pages and LPA2, where
we cannot simply point TTBR1 to the pgd_t entries where they actually
reside. However, we should avoid misinterpreting those cloned entries as
describing the start of the 52-bit VA space when the hardware does not
support that.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/mm/ptdump.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index 9bc4066c5bf33a72..6c13bf6b7d5df4e4 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -358,7 +358,7 @@ void ptdump_check_wx(void)
 		.ptdump = {
 			.note_page = note_page,
 			.range = (struct ptdump_range[]) {
-				{PAGE_OFFSET, ~0UL},
+				{_PAGE_OFFSET(vabits_actual), ~0UL},
 				{0, 0}
 			}
 		}
@@ -380,6 +380,8 @@ static int __init ptdump_init(void)
 	address_markers[KASAN_START_NR].start_address = KASAN_SHADOW_START;
 #endif
 	ptdump_initialize();
+	if (VA_BITS > VA_BITS_MIN)
+		kernel_ptdump_info.base_addr = _PAGE_OFFSET(vabits_actual);
 	ptdump_debugfs_register(&kernel_ptdump_info, "kernel_page_tables");
 	return 0;
 }
-- 
2.35.1


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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 2/7] arm64: mm: Disable all 52-bit virtual addressing support with arm64.nolva
  2022-11-17 13:24 [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 1/7] arm64: ptdump: Disregard unaddressable VA space Ard Biesheuvel
@ 2022-11-17 13:24 ` Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 3/7] arm64: mm: Wire up TCR.DS bit to PTE shareability fields Ard Biesheuvel
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2022-11-17 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ard Biesheuvel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Catalin Marinas, Mark Brown, Anshuman Khandual,
	Richard Henderson

The LVA feature only applies to 64k pages configurations, and for
smaller page sizes there are other feature registers that describe the
virtual addressing capabilities of the CPU.

Let's adhere to the principle of least surprise, and wire up arm64.nolva
so that it disables 52-bit virtual addressing support regardless of the
page size.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/include/asm/cpufeature.h   |  1 +
 arch/arm64/kernel/cpufeature.c        |  4 ++-
 arch/arm64/kernel/image-vars.h        |  1 +
 arch/arm64/kernel/pi/idreg-override.c | 26 ++++++++++++++++++++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 7aa9cd4fc67f7c61..dbf0186f46ae54ef 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -910,6 +910,7 @@ static inline unsigned int get_vmid_bits(u64 mmfr1)
 
 struct arm64_ftr_reg *get_arm64_ftr_reg(u32 sys_id);
 
+extern struct arm64_ftr_override id_aa64mmfr0_override;
 extern struct arm64_ftr_override id_aa64mmfr1_override;
 extern struct arm64_ftr_override id_aa64mmfr2_override;
 extern struct arm64_ftr_override id_aa64pfr0_override;
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 469d8b31487e88b6..4a631a6e7e42b981 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -636,6 +636,7 @@ static const struct arm64_ftr_bits ftr_raz[] = {
 #define ARM64_FTR_REG(id, table)		\
 	__ARM64_FTR_REG_OVERRIDE(#id, id, table, &no_override)
 
+struct arm64_ftr_override id_aa64mmfr0_override;
 struct arm64_ftr_override id_aa64mmfr1_override;
 struct arm64_ftr_override id_aa64mmfr2_override;
 struct arm64_ftr_override id_aa64pfr0_override;
@@ -701,7 +702,8 @@ static const struct __ftr_reg_entry {
 			       &id_aa64isar2_override),
 
 	/* Op1 = 0, CRn = 0, CRm = 7 */
-	ARM64_FTR_REG(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0),
+	ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0,
+			       &id_aa64mmfr0_override),
 	ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1,
 			       &id_aa64mmfr1_override),
 	ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2,
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index 3bdf0e7865730213..82bafa1f869c3a8b 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -45,6 +45,7 @@ PROVIDE(__pi_memstart_offset_seed	= memstart_offset_seed);
 
 PROVIDE(__pi_id_aa64isar1_override	= id_aa64isar1_override);
 PROVIDE(__pi_id_aa64isar2_override	= id_aa64isar2_override);
+PROVIDE(__pi_id_aa64mmfr0_override	= id_aa64mmfr0_override);
 PROVIDE(__pi_id_aa64mmfr1_override	= id_aa64mmfr1_override);
 PROVIDE(__pi_id_aa64mmfr2_override	= id_aa64mmfr2_override);
 PROVIDE(__pi_id_aa64pfr0_override	= id_aa64pfr0_override);
diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
index 3be2f887e6cae29f..aeab2198720ac67c 100644
--- a/arch/arm64/kernel/pi/idreg-override.c
+++ b/arch/arm64/kernel/pi/idreg-override.c
@@ -139,10 +139,36 @@ DEFINE_OVERRIDE(6, sw_features, "arm64_sw", arm64_sw_feature_override,
 		FIELD("nowxn", ARM64_SW_FEATURE_OVERRIDE_NOWXN),
 		{});
 
+asmlinkage bool __init mmfr2_varange_filter(u64 val)
+{
+	u64 mmfr0, tg4, tg16;
+
+	if (val)
+		return false;
+
+	mmfr0 = read_sysreg(id_aa64mmfr0_el1);
+	tg4 = (mmfr0 & ID_AA64MMFR0_EL1_TGRAN4_MASK) >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT;
+	tg16 = (mmfr0 & ID_AA64MMFR0_EL1_TGRAN16_MASK) >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT;
+
+	if (tg4 == ID_AA64MMFR0_EL1_TGRAN4_52_BIT) {
+		id_aa64mmfr0_override.val |=
+			ID_AA64MMFR0_EL1_TGRAN4_IMP << ID_AA64MMFR0_EL1_TGRAN4_SHIFT;
+		id_aa64mmfr0_override.mask |= ID_AA64MMFR0_EL1_TGRAN4_MASK;
+	}
+
+	if (tg16 == ID_AA64MMFR0_EL1_TGRAN16_52_BIT) {
+		id_aa64mmfr0_override.val |=
+			ID_AA64MMFR0_EL1_TGRAN16_IMP << ID_AA64MMFR0_EL1_TGRAN16_SHIFT;
+		id_aa64mmfr0_override.mask |= ID_AA64MMFR0_EL1_TGRAN16_MASK;
+	}
+	return true;
+}
+
 DEFINE_OVERRIDE(7, mmfr2, "id_aa64mmfr2", id_aa64mmfr2_override,
 		FIELD("varange", ID_AA64MMFR2_EL1_VARange_SHIFT),
 		FIELD("e0pd", ID_AA64MMFR2_EL1_E0PD_SHIFT),
 		{});
+DEFINE_OVERRIDE_FILTER(mmfr2, 0, mmfr2_varange_filter);
 
 /*
  * regs[] is populated by R_AARCH64_PREL32 directives invisible to the compiler
-- 
2.35.1


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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 3/7] arm64: mm: Wire up TCR.DS bit to PTE shareability fields
  2022-11-17 13:24 [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 1/7] arm64: ptdump: Disregard unaddressable VA space Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 2/7] arm64: mm: Disable all 52-bit virtual addressing support with arm64.nolva Ard Biesheuvel
@ 2022-11-17 13:24 ` Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 4/7] arm64: mm: Support use of 52-bit pgdirs on 48-bit/16k systems Ard Biesheuvel
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2022-11-17 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ard Biesheuvel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Catalin Marinas, Mark Brown, Anshuman Khandual,
	Richard Henderson

When LPA2 is enabled, bits 8 and 9 of page and block descriptors become
part of the output address instead of carrying shareability attributes
for the region in question.

So avoid setting these bits if TCR.DS == 1, which means LPA2 is enabled.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/include/asm/pgtable-hwdef.h |  1 +
 arch/arm64/include/asm/pgtable-prot.h  | 18 ++++++++++++++++--
 arch/arm64/mm/mmap.c                   |  4 ++++
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index f658aafc47dfa29a..c4ad7fbb12c5c07a 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -276,6 +276,7 @@
 #define TCR_E0PD1		(UL(1) << 56)
 #define TCR_TCMA0		(UL(1) << 57)
 #define TCR_TCMA1		(UL(1) << 58)
+#define TCR_DS			(UL(1) << 59)
 
 /*
  * TTBR.
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 9b165117a454595a..15888fa87072f609 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -40,6 +40,20 @@ extern bool arm64_use_ng_mappings;
 #define PTE_MAYBE_NG		(arm64_use_ng_mappings ? PTE_NG : 0)
 #define PMD_MAYBE_NG		(arm64_use_ng_mappings ? PMD_SECT_NG : 0)
 
+#if !defined(CONFIG_ARM64_PA_BITS_52) || defined(CONFIG_ARM64_64K_PAGES)
+#define lpa2_is_enabled()	false
+#define PTE_MAYBE_SHARED	PTE_SHARED
+#define PMD_MAYBE_SHARED	PMD_SECT_S
+#else
+static inline bool lpa2_is_enabled(void)
+{
+	return read_sysreg(tcr_el1) & TCR_DS;
+}
+
+#define PTE_MAYBE_SHARED	(lpa2_is_enabled() ? 0 : PTE_SHARED)
+#define PMD_MAYBE_SHARED	(lpa2_is_enabled() ? 0 : PMD_SECT_S)
+#endif
+
 /*
  * If we have userspace only BTI we don't want to mark kernel pages
  * guarded even if the system does support BTI.
@@ -50,8 +64,8 @@ extern bool arm64_use_ng_mappings;
 #define PTE_MAYBE_GP		0
 #endif
 
-#define PROT_DEFAULT		(_PROT_DEFAULT | PTE_MAYBE_NG)
-#define PROT_SECT_DEFAULT	(_PROT_SECT_DEFAULT | PMD_MAYBE_NG)
+#define PROT_DEFAULT		(PTE_TYPE_PAGE | PTE_MAYBE_NG | PTE_MAYBE_SHARED | PTE_AF)
+#define PROT_SECT_DEFAULT	(PMD_TYPE_SECT | PMD_MAYBE_NG | PMD_MAYBE_SHARED | PMD_SECT_AF)
 
 #define PROT_DEVICE_nGnRnE	(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
 #define PROT_DEVICE_nGnRE	(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE))
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index 8f5b7ce857ed4a8f..adcf547f74eb8e60 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -73,6 +73,10 @@ static int __init adjust_protection_map(void)
 		protection_map[VM_EXEC | VM_SHARED] = PAGE_EXECONLY;
 	}
 
+	if (lpa2_is_enabled())
+		for (int i = 0; i < ARRAY_SIZE(protection_map); i++)
+			pgprot_val(protection_map[i]) &= ~PTE_SHARED;
+
 	return 0;
 }
 arch_initcall(adjust_protection_map);
-- 
2.35.1


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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 4/7] arm64: mm: Support use of 52-bit pgdirs on 48-bit/16k systems
  2022-11-17 13:24 [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2022-11-17 13:24 ` [RFC PATCH 3/7] arm64: mm: Wire up TCR.DS bit to PTE shareability fields Ard Biesheuvel
@ 2022-11-17 13:24 ` Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 5/7] arm64: mm: Add LPA2 support to phys<->pte conversion routines Ard Biesheuvel
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2022-11-17 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ard Biesheuvel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Catalin Marinas, Mark Brown, Anshuman Khandual,
	Richard Henderson

On LVA/64k granule configurations, we simply extend the level 1 root
page table to cover 52 bits of VA space, and if the system in question
only supports 48 bits, we point TTBR1 to the pgdir entry that covers the
start of the 48-bit addressable part of the VA space.

Sadly, we cannot use the same trick on LPA2/16k granule configurations.
This is due to the fact that TTBR registers require 64 byte aligned
addresses, while the 48-bit addressable entries in question will not
appear at a 64 byte aligned address if the entire 52-bit VA table is
aligned to its size (which is another requirement for TTBR registers).

Fortunately, we are only dealing with two entries in this case: one that
covers the kernel/vmalloc region and one covering the linear map. This
makes it feasible to simply clone those entries into the start of the
page table after the first mapping into the respective region is
created.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/include/asm/assembler.h | 17 +++++------------
 arch/arm64/include/asm/mmu.h       | 18 ++++++++++++++++++
 arch/arm64/kernel/cpufeature.c     |  1 +
 arch/arm64/kernel/pi/map_kernel.c  |  2 +-
 arch/arm64/mm/mmu.c                |  2 ++
 5 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 4cb84dc6e2205a91..9fa62f102c1c94e9 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -609,11 +609,15 @@ alternative_endif
  * but we have to add an offset so that the TTBR1 address corresponds with the
  * pgdir entry that covers the lowest 48-bit addressable VA.
  *
+ * Note that this trick only works for 64k pages - 4k pages uses an additional
+ * paging level, and on 16k pages, we would end up with a TTBR address that is
+ * not 64 byte aligned.
+ *
  * orr is used as it can cover the immediate value (and is idempotent).
  * 	ttbr: Value of ttbr to set, modified.
  */
 	.macro	offset_ttbr1, ttbr, tmp
-#ifdef CONFIG_ARM64_VA_BITS_52
+#if defined(CONFIG_ARM64_VA_BITS_52) && defined(CONFIG_ARM64_64K_PAGES)
 	mrs	\tmp, tcr_el1
 	and	\tmp, \tmp, #TCR_T1SZ_MASK
 	cmp	\tmp, #TCR_T1SZ(VA_BITS_MIN)
@@ -622,17 +626,6 @@ alternative_endif
 #endif
 	.endm
 
-/*
- * Perform the reverse of offset_ttbr1.
- * bic is used as it can cover the immediate value and, in future, won't need
- * to be nop'ed out when dealing with 52-bit kernel VAs.
- */
-	.macro	restore_ttbr1, ttbr
-#ifdef CONFIG_ARM64_VA_BITS_52
-	bic	\ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET
-#endif
-	.endm
-
 /*
  * Arrange a physical address in a TTBR register, taking care of 52-bit
  * addresses.
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index a93d495d6e8c94a2..aa9fdefdb8c8b9e6 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -16,6 +16,7 @@
 
 #include <linux/refcount.h>
 #include <asm/cpufeature.h>
+#include <asm/pgtable-prot.h>
 
 typedef struct {
 	atomic64_t	id;
@@ -72,6 +73,23 @@ extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot);
 extern void mark_linear_text_alias_ro(void);
 extern bool kaslr_requires_kpti(void);
 
+static inline void sync_kernel_pgdir_root_entries(pgd_t *pgdir)
+{
+	/*
+	 * On 16k pages, we cannot advance the TTBR1 address to the pgdir entry
+	 * that covers the start of the 48-bit addressable kernel VA space like
+	 * we do on 64k pages when the hardware does not support LPA2, since the
+	 * resulting address would not be 64 byte aligned. So instead, copy the
+	 * pgdir entry that covers the mapping we just created to the start of
+	 * the page table.
+	 */
+	if (IS_ENABLED(CONFIG_ARM64_16K_PAGES) &&
+	    VA_BITS > VA_BITS_MIN && !lpa2_is_enabled()) {
+		pgdir[0] = pgdir[PTRS_PER_PGD - 2];
+		pgdir[1] = pgdir[PTRS_PER_PGD - 1];
+	}
+}
+
 #define INIT_MM_CONTEXT(name)	\
 	.pgd = swapper_pg_dir,
 
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 4a631a6e7e42b981..d19f9c1a93d9d000 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1768,6 +1768,7 @@ kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
 		create_kpti_ng_temp_pgd(kpti_ng_temp_pgd, __pa(alloc),
 					KPTI_NG_TEMP_VA, PAGE_SIZE, PAGE_KERNEL,
 					kpti_ng_pgd_alloc, 0);
+		sync_kernel_pgdir_root_entries(kpti_ng_temp_pgd);
 	}
 
 	cpu_install_idmap();
diff --git a/arch/arm64/kernel/pi/map_kernel.c b/arch/arm64/kernel/pi/map_kernel.c
index 6c5d78dcb90e55c5..3b0b3fecf2bd533b 100644
--- a/arch/arm64/kernel/pi/map_kernel.c
+++ b/arch/arm64/kernel/pi/map_kernel.c
@@ -217,8 +217,8 @@ static void __init map_kernel(u64 kaslr_offset, u64 va_offset)
 	map_segment(init_pg_dir, &pgdp, va_offset, __initdata_begin,
 		    __initdata_end, data_prot, false);
 	map_segment(init_pg_dir, &pgdp, va_offset, _data, _end, data_prot, true);
+	sync_kernel_pgdir_root_entries(init_pg_dir);
 	dsb(ishst);
-
 	idmap_cpu_replace_ttbr1(init_pg_dir);
 
 	if (twopass) {
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 63fb62e16a1f8873..90733567f0b89a31 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -665,6 +665,7 @@ static int __init map_entry_trampoline(void)
 	__create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS,
 			     entry_tramp_text_size(), prot,
 			     __pgd_pgtable_alloc, NO_BLOCK_MAPPINGS);
+	sync_kernel_pgdir_root_entries(tramp_pg_dir);
 
 	/* Map both the text and data into the kernel page table */
 	for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++)
@@ -729,6 +730,7 @@ void __init paging_init(void)
 	idmap_t0sz = 63UL - __fls(__pa_symbol(_end) | GENMASK(VA_BITS_MIN - 1, 0));
 
 	map_mem(swapper_pg_dir);
+	sync_kernel_pgdir_root_entries(swapper_pg_dir);
 
 	memblock_allow_resize();
 
-- 
2.35.1


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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 5/7] arm64: mm: Add LPA2 support to phys<->pte conversion routines
  2022-11-17 13:24 [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2022-11-17 13:24 ` [RFC PATCH 4/7] arm64: mm: Support use of 52-bit pgdirs on 48-bit/16k systems Ard Biesheuvel
@ 2022-11-17 13:24 ` Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 6/7] arm64: Enable LPA2 at boot if supported by the system Ard Biesheuvel
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2022-11-17 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ard Biesheuvel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Catalin Marinas, Mark Brown, Anshuman Khandual,
	Richard Henderson

In preparation for enabling LPA2 support, introduce the mask values for
converting between physical addresses and their representations in a
page table descriptor.

While at it, move pte_to_phys into its only user, which gets invoked
when system-wide alternatives are applied, which means we can rely on a
boot-time alternative here.

For LPA2, the PTE_ADDR_MASK contains two non-adjacent sequences of zero
bits, which means it no longer fits into the immediate field of an
ordinary ALU instruction. So let's redefine it to include the bits in
between as well, and only use it when converting from physical address
to PTE representation, where the distinction does not matter. Also
update the name accordingly to emphasize this.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/include/asm/assembler.h     | 16 ++--------------
 arch/arm64/include/asm/pgtable-hwdef.h | 10 +++++++---
 arch/arm64/include/asm/pgtable.h       |  5 +++--
 arch/arm64/mm/proc.S                   | 10 ++++++++++
 4 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 9fa62f102c1c94e9..44a801e1dc4bf027 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -644,25 +644,13 @@ alternative_endif
 
 	.macro	phys_to_pte, pte, phys
 #ifdef CONFIG_ARM64_PA_BITS_52
-	/*
-	 * We assume \phys is 64K aligned and this is guaranteed by only
-	 * supporting this configuration with 64K pages.
-	 */
-	orr	\pte, \phys, \phys, lsr #36
-	and	\pte, \pte, #PTE_ADDR_MASK
+	orr	\pte, \phys, \phys, lsr #PTE_ADDR_HIGH_SHIFT
+	and	\pte, \pte, #PHYS_TO_PTE_ADDR_MASK
 #else
 	mov	\pte, \phys
 #endif
 	.endm
 
-	.macro	pte_to_phys, phys, pte
-	and	\phys, \pte, #PTE_ADDR_MASK
-#ifdef CONFIG_ARM64_PA_BITS_52
-	orr	\phys, \phys, \phys, lsl #PTE_ADDR_HIGH_SHIFT
-	and	\phys, \phys, GENMASK_ULL(PHYS_MASK_SHIFT - 1, PAGE_SHIFT)
-#endif
-	.endm
-
 /*
  * tcr_clear_errata_bits - Clear TCR bits that trigger an errata on this CPU.
  */
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index c4ad7fbb12c5c07a..b91fe4781b066d54 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -155,13 +155,17 @@
 #define PTE_PXN			(_AT(pteval_t, 1) << 53)	/* Privileged XN */
 #define PTE_UXN			(_AT(pteval_t, 1) << 54)	/* User XN */
 
-#define PTE_ADDR_LOW		(((_AT(pteval_t, 1) << (48 - PAGE_SHIFT)) - 1) << PAGE_SHIFT)
+#define PTE_ADDR_LOW		(((_AT(pteval_t, 1) << (50 - PAGE_SHIFT)) - 1) << PAGE_SHIFT)
 #ifdef CONFIG_ARM64_PA_BITS_52
+#ifdef CONFIG_ARM64_64K_PAGES
 #define PTE_ADDR_HIGH		(_AT(pteval_t, 0xf) << 12)
-#define PTE_ADDR_MASK		(PTE_ADDR_LOW | PTE_ADDR_HIGH)
 #define PTE_ADDR_HIGH_SHIFT	36
+#define PHYS_TO_PTE_ADDR_MASK	(PTE_ADDR_LOW | PTE_ADDR_HIGH)
 #else
-#define PTE_ADDR_MASK		PTE_ADDR_LOW
+#define PTE_ADDR_HIGH		(_AT(pteval_t, 0x3) << 8)
+#define PTE_ADDR_HIGH_SHIFT	42
+#define PHYS_TO_PTE_ADDR_MASK	GENMASK_ULL(49, 8)
+#endif
 #endif
 
 /*
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index daedd6172227f0ca..666db7173d0f9b66 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -76,15 +76,16 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 #ifdef CONFIG_ARM64_PA_BITS_52
 static inline phys_addr_t __pte_to_phys(pte_t pte)
 {
+	pte_val(pte) &= ~PTE_MAYBE_SHARED;
 	return (pte_val(pte) & PTE_ADDR_LOW) |
 		((pte_val(pte) & PTE_ADDR_HIGH) << PTE_ADDR_HIGH_SHIFT);
 }
 static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
 {
-	return (phys | (phys >> PTE_ADDR_HIGH_SHIFT)) & PTE_ADDR_MASK;
+	return (phys | (phys >> PTE_ADDR_HIGH_SHIFT)) & PHYS_TO_PTE_ADDR_MASK;
 }
 #else
-#define __pte_to_phys(pte)	(pte_val(pte) & PTE_ADDR_MASK)
+#define __pte_to_phys(pte)	(pte_val(pte) & PTE_ADDR_LOW)
 #define __phys_to_pte_val(phys)	(phys)
 #endif
 
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 02818fa6aded3218..c747a2ef478cabec 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -208,6 +208,16 @@ SYM_FUNC_ALIAS(__pi_idmap_cpu_replace_ttbr1, idmap_cpu_replace_ttbr1)
 
 	.pushsection ".idmap.text", "awx"
 
+	.macro	pte_to_phys, phys, pte
+	and	\phys, \pte, #PTE_ADDR_LOW
+#ifdef CONFIG_ARM64_PA_BITS_52
+alternative_if ARM64_HAS_LVA
+	orr	\phys, \phys, \pte, lsl #PTE_ADDR_HIGH_SHIFT
+	and	\phys, \phys, GENMASK_ULL(PHYS_MASK_SHIFT - 1, PAGE_SHIFT)
+alternative_else_nop_endif
+#endif
+	.endm
+
 	.macro	kpti_mk_tbl_ng, type, num_entries
 	add	end_\type\()p, cur_\type\()p, #\num_entries * 8
 .Ldo_\type:
-- 
2.35.1


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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 6/7] arm64: Enable LPA2 at boot if supported by the system
  2022-11-17 13:24 [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Ard Biesheuvel
                   ` (4 preceding siblings ...)
  2022-11-17 13:24 ` [RFC PATCH 5/7] arm64: mm: Add LPA2 support to phys<->pte conversion routines Ard Biesheuvel
@ 2022-11-17 13:24 ` Ard Biesheuvel
  2022-11-17 13:24 ` [RFC PATCH 7/7] arm64: Enable 52-bit virtual addressing for 16k granule configs Ard Biesheuvel
  2022-11-18 10:38 ` [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Catalin Marinas
  7 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2022-11-17 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ard Biesheuvel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Catalin Marinas, Mark Brown, Anshuman Khandual,
	Richard Henderson

Update the early kernel mapping code to take 52-bit virtual addressing
into account based on the LPA2 feature. This is a bit more involved than
LVA, given that some page table descriptor bits change meaning in this
case.

To keep the handling in asm to a minimum, the initial ID map is still
created with 48-bit virtual addressing, which implies that the kernel
image must be loaded into 48-bit addressable physical memory. This is
currently required by the boot protocol, even though we happen to
support placement outside of that for LVA/64k based configurations.

Enabling LPA2 involves more than setting TCR.T1SZ to a lower value,
there is also a DS bit in TCR that changes the meaning of bits [9:8] in
all page table descriptors. Since we cannot enable DS and every live
page table descriptor at the same time, we have to pivot through another
temporary mapping. This avoids reintroducing manipulations of the page
tables with the MMU and caches disabled, which is something we generally
try to avoid.

To permit the LPA2 feature to be overridden on the kernel command line,
which may be necessary to work around silicon errata, or to deal with
mismatched features on heterogeneous SoC designs, test for CPU feature
overrides first, and only then enable LPA2.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/kernel/image-vars.h    |   2 +
 arch/arm64/kernel/pi/map_kernel.c | 101 +++++++++++++++++++-
 arch/arm64/mm/proc.S              |   3 +
 3 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index 82bafa1f869c3a8b..f48b6f09d278d3bf 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -56,6 +56,8 @@ PROVIDE(__pi_arm64_sw_feature_override	= arm64_sw_feature_override);
 PROVIDE(__pi_arm64_use_ng_mappings	= arm64_use_ng_mappings);
 PROVIDE(__pi__ctype			= _ctype);
 
+PROVIDE(__pi_init_idmap_pg_dir		= init_idmap_pg_dir);
+PROVIDE(__pi_init_idmap_pg_end		= init_idmap_pg_end);
 PROVIDE(__pi_init_pg_dir		= init_pg_dir);
 PROVIDE(__pi_init_pg_end		= init_pg_end);
 PROVIDE(__pi_swapper_pg_dir		= swapper_pg_dir);
diff --git a/arch/arm64/kernel/pi/map_kernel.c b/arch/arm64/kernel/pi/map_kernel.c
index 3b0b3fecf2bd533b..71cc32cd2545b85a 100644
--- a/arch/arm64/kernel/pi/map_kernel.c
+++ b/arch/arm64/kernel/pi/map_kernel.c
@@ -137,6 +137,22 @@ static bool __init arm64_early_this_cpu_has_lva(void)
 						    ID_AA64MMFR2_EL1_VARange_SHIFT);
 }
 
+static bool __init arm64_early_this_cpu_has_lpa2(void)
+{
+	bool gran4k = IS_ENABLED(CONFIG_ARM64_4K_PAGES);
+	u64 mmfr0;
+	int feat;
+
+	mmfr0 = read_sysreg(id_aa64mmfr0_el1);
+	mmfr0 &= ~id_aa64mmfr0_override.mask;
+	mmfr0 |= id_aa64mmfr0_override.val;
+	feat = cpuid_feature_extract_field(mmfr0, ID_AA64MMFR0_EL1_TGRAN_SHIFT,
+					   gran4k /* signed */);
+
+	return gran4k ? feat >= ID_AA64MMFR0_EL1_TGRAN4_52_BIT
+		      : feat >= ID_AA64MMFR0_EL1_TGRAN16_52_BIT;
+}
+
 static bool __init arm64_early_this_cpu_has_pac(void)
 {
 	u64 isar1, isar2;
@@ -279,6 +295,74 @@ static void noinline __section(".idmap.text") disable_wxn(void)
 	    ::	"r"(sctlr & ~SCTLR_ELx_M), "r"(sctlr));
 }
 
+static void noinline __section(".idmap.text") set_ttbr0_for_lpa2(u64 ttbr)
+{
+	u64 sctlr = read_sysreg(sctlr_el1);
+	u64 tcr = read_sysreg(tcr_el1) | TCR_DS;
+
+	asm("	msr	sctlr_el1, %0		;"
+	    "	isb				;"
+	    "   msr     ttbr0_el1, %1		;"
+	    "   msr     tcr_el1, %2		;"
+	    "	isb				;"
+	    "	tlbi    vmalle1			;"
+	    "	dsb     nsh			;"
+	    "	isb				;"
+	    "	msr     sctlr_el1, %3		;"
+	    "	isb				;"
+	    ::	"r"(sctlr & ~SCTLR_ELx_M), "r"(ttbr), "r"(tcr), "r"(sctlr));
+}
+
+static void remap_idmap_for_lpa2(void)
+{
+	extern pgd_t init_idmap_pg_dir[], init_idmap_pg_end[];
+	pgd_t *pgdp = (void *)init_pg_dir + PAGE_SIZE;
+	pgprot_t text_prot = PAGE_KERNEL_ROX;
+	pgprot_t data_prot = PAGE_KERNEL;
+
+	/* clear the bits that change meaning once LPA2 is turned on */
+	pgprot_val(text_prot) &= ~PTE_SHARED;
+	pgprot_val(data_prot) &= ~PTE_SHARED;
+
+	/*
+	 * We have to clear bits [9:8] in all block or page descriptors in the
+	 * initial ID map, as otherwise they will be (mis)interpreted as
+	 * physical address bits once we flick the LPA2 switch (TCR.DS). Since
+	 * we cannot manipulate live descriptors in that way without creating
+	 * potential TLB conflicts, let's create another temporary ID map in a
+	 * LPA2 compatible fashion, and update the initial ID map while running
+	 * from that.
+	 */
+	map_segment(init_pg_dir, &pgdp, 0, _stext, __inittext_end, text_prot, false);
+	map_segment(init_pg_dir, &pgdp, 0, __initdata_begin, _end, data_prot, false);
+	dsb(ishst);
+	set_ttbr0_for_lpa2((u64)init_pg_dir);
+
+	/*
+	 * Recreate the initial ID map with the same granularity as before.
+	 * Don't bother with the FDT, we no longer need it after this.
+	 */
+	memset(init_idmap_pg_dir, 0,
+	       (u64)init_idmap_pg_dir - (u64)init_idmap_pg_end);
+
+	pgdp = (void *)init_idmap_pg_dir + PAGE_SIZE;
+	map_segment(init_idmap_pg_dir, &pgdp, 0,
+		    PTR_ALIGN_DOWN(&_stext[0], INIT_IDMAP_BLOCK_SIZE),
+		    PTR_ALIGN_DOWN(&__bss_start[0], INIT_IDMAP_BLOCK_SIZE),
+		    text_prot, false);
+	map_segment(init_idmap_pg_dir, &pgdp, 0,
+		    PTR_ALIGN_DOWN(&__bss_start[0], INIT_IDMAP_BLOCK_SIZE),
+		    PTR_ALIGN(&_end[0], INIT_IDMAP_BLOCK_SIZE),
+		    data_prot, false);
+	dsb(ishst);
+
+	/* switch back to the updated initial ID map */
+	set_ttbr0_for_lpa2((u64)init_idmap_pg_dir);
+
+	/* wipe the temporary ID map from memory */
+	memset(init_pg_dir, 0, (u64)init_pg_end - (u64)init_pg_dir);
+}
+
 asmlinkage void __init early_map_kernel(u64 boot_status, void *fdt)
 {
 	static char const chosen_str[] __initconst = "/chosen";
@@ -292,9 +376,6 @@ asmlinkage void __init early_map_kernel(u64 boot_status, void *fdt)
 	/* Parse the command line for CPU feature overrides */
 	init_feature_override(boot_status, fdt, chosen);
 
-	if (VA_BITS > VA_BITS_MIN && arm64_early_this_cpu_has_lva())
-		sysreg_clear_set(tcr_el1, TCR_T1SZ_MASK, TCR_T1SZ(VA_BITS));
-
 	if (IS_ENABLED(CONFIG_ARM64_WXN) &&
 	    cpuid_feature_extract_unsigned_field(arm64_sw_feature_override.val,
 						 ARM64_SW_FEATURE_OVERRIDE_NOWXN))
@@ -322,6 +403,20 @@ asmlinkage void __init early_map_kernel(u64 boot_status, void *fdt)
 			arm64_use_ng_mappings = true;
 	}
 
+	if (VA_BITS > VA_BITS_MIN) {
+		bool va52 = false;
+
+		if (IS_ENABLED(CONFIG_ARM64_64K_PAGES)) {
+			va52 = arm64_early_this_cpu_has_lva();
+		} else if (arm64_early_this_cpu_has_lpa2()) {
+			remap_idmap_for_lpa2();
+			va52 = true;
+		}
+		if (va52)
+			sysreg_clear_set(tcr_el1, TCR_T1SZ_MASK,
+					 TCR_T1SZ(VA_BITS));
+	}
+
 	va_base = KIMAGE_VADDR + kaslr_offset;
 	map_kernel(kaslr_offset, va_base - pa_base);
 }
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index c747a2ef478cabec..8197663a54f63c9d 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -443,6 +443,9 @@ SYM_FUNC_START(__cpu_setup)
 #if VA_BITS > VA_BITS_MIN
 alternative_if ARM64_HAS_LVA
 	eor		tcr, tcr, #TCR_T1SZ(VA_BITS) ^ TCR_T1SZ(VA_BITS_MIN)
+#ifndef CONFIG_ARM64_64K_PAGES
+	orr		tcr, tcr, #TCR_DS
+#endif
 alternative_else_nop_endif
 #elif VA_BITS < 48
 	idmap_get_t0sz	x9
-- 
2.35.1


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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 7/7] arm64: Enable 52-bit virtual addressing for 16k granule configs
  2022-11-17 13:24 [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Ard Biesheuvel
                   ` (5 preceding siblings ...)
  2022-11-17 13:24 ` [RFC PATCH 6/7] arm64: Enable LPA2 at boot if supported by the system Ard Biesheuvel
@ 2022-11-17 13:24 ` Ard Biesheuvel
  2022-11-18 10:38 ` [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Catalin Marinas
  7 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2022-11-17 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ard Biesheuvel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Catalin Marinas, Mark Brown, Anshuman Khandual,
	Richard Henderson

Update Kconfig to permit 16k granule configurations to be built with
52-bit virtual addressing, now that all the prerequisites are in place.

While at it, update the feature description so it matches on the
appropriate feature bits depending on the page size. For simplicity,
let's just keep ARM64_HAS_LVA as the feature name.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/Kconfig             |  6 ++++--
 arch/arm64/kernel/cpufeature.c | 22 ++++++++++++++++----
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 79ec4bc05694acec..aece91a774a84276 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -344,6 +344,7 @@ config PGTABLE_LEVELS
 	default 3 if ARM64_64K_PAGES && (ARM64_VA_BITS_48 || ARM64_VA_BITS_52)
 	default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39
 	default 3 if ARM64_16K_PAGES && ARM64_VA_BITS_47
+	default 4 if ARM64_16K_PAGES && (ARM64_VA_BITS_48 || ARM64_VA_BITS_52)
 	default 4 if !ARM64_64K_PAGES && ARM64_VA_BITS_48
 
 config ARCH_SUPPORTS_UPROBES
@@ -1197,7 +1198,8 @@ config ARM64_VA_BITS_48
 
 config ARM64_VA_BITS_52
 	bool "52-bit"
-	depends on ARM64_64K_PAGES && (ARM64_PAN || !ARM64_SW_TTBR0_PAN)
+	depends on ARM64_64K_PAGES || ARM64_16K_PAGES
+	depends on ARM64_PAN || !ARM64_SW_TTBR0_PAN
 	help
 	  Enable 52-bit virtual addressing for userspace when explicitly
 	  requested via a hint to mmap(). The kernel will also use 52-bit
@@ -1247,7 +1249,7 @@ config ARM64_PA_BITS_48
 
 config ARM64_PA_BITS_52
 	bool "52-bit (ARMv8.2)"
-	depends on ARM64_64K_PAGES
+	depends on ARM64_64K_PAGES || ARM64_16K_PAGES
 	depends on ARM64_PAN || !ARM64_SW_TTBR0_PAN
 	help
 	  Enable support for a 52-bit physical address space, introduced as
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d19f9c1a93d9d000..05c46e9c1b5a4c9c 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2663,15 +2663,29 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 	},
 #ifdef CONFIG_ARM64_VA_BITS_52
 	{
-		.desc = "52-bit Virtual Addressing (LVA)",
 		.capability = ARM64_HAS_LVA,
 		.type = ARM64_CPUCAP_BOOT_CPU_FEATURE,
-		.sys_reg = SYS_ID_AA64MMFR2_EL1,
-		.sign = FTR_UNSIGNED,
+		.matches = has_cpuid_feature,
 		.field_width = 4,
+#ifdef CONFIG_ARM64_64K_PAGES
+		.desc = "52-bit Virtual Addressing (LVA)",
+		.sign = FTR_SIGNED,
+		.sys_reg = SYS_ID_AA64MMFR2_EL1,
 		.field_pos = ID_AA64MMFR2_EL1_VARange_SHIFT,
-		.matches = has_cpuid_feature,
 		.min_field_value = ID_AA64MMFR2_EL1_VARange_52,
+#else
+		.desc = "52-bit Virtual Addressing (LPA2)",
+		.sys_reg = SYS_ID_AA64MMFR0_EL1,
+#ifdef CONFIG_ARM64_4K_PAGES
+		.sign = FTR_SIGNED,
+		.field_pos = ID_AA64MMFR0_EL1_TGRAN4_SHIFT,
+		.min_field_value = ID_AA64MMFR0_EL1_TGRAN4_52_BIT,
+#else
+		.sign = FTR_UNSIGNED,
+		.field_pos = ID_AA64MMFR0_EL1_TGRAN16_SHIFT,
+		.min_field_value = ID_AA64MMFR0_EL1_TGRAN16_52_BIT,
+#endif
+#endif
 	},
 #endif
 	{},
-- 
2.35.1


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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages
  2022-11-17 13:24 [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Ard Biesheuvel
                   ` (6 preceding siblings ...)
  2022-11-17 13:24 ` [RFC PATCH 7/7] arm64: Enable 52-bit virtual addressing for 16k granule configs Ard Biesheuvel
@ 2022-11-18 10:38 ` Catalin Marinas
  2022-11-18 10:50   ` Ard Biesheuvel
  2022-11-18 11:18   ` Anshuman Khandual
  7 siblings, 2 replies; 13+ messages in thread
From: Catalin Marinas @ 2022-11-18 10:38 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Mark Brown, Anshuman Khandual, Richard Henderson

Hi Ard,

On Thu, Nov 17, 2022 at 02:24:16PM +0100, Ard Biesheuvel wrote:
> Enable support for LPA2 when running with 16k pages. Unlike with 4k
> pages, this does not require adding support for 5 level paging, but
> beyond that, there is no fundamental difference between LPA2 support on
> 4k or 16k pages.

We have some patches already from Anshuman, targeting both 4K and 16K
pages:

https://lore.kernel.org/r/1632998116-11552-1-git-send-email-anshuman.khandual@arm.com

I don't think they've been rebased on top of 6.1-rcX though. Could you
please liaise with Anshuman and agree on a way forward? I'd rather only
review a single series if they do the same thing. I have a preference
for a more complete solution (4K and 16K) rather than just 16K pages. I
think we can even ignore some corner cases like 39-bit VA (if anyone is
asking, we could do it later but it doesn't seem realistic).

And a question for Anshuman: do you plan to refresh your series?

Thanks.

-- 
Catalin

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages
  2022-11-18 10:38 ` [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Catalin Marinas
@ 2022-11-18 10:50   ` Ard Biesheuvel
  2022-11-18 11:04     ` Ryan Roberts
  2022-11-18 11:53     ` Anshuman Khandual
  2022-11-18 11:18   ` Anshuman Khandual
  1 sibling, 2 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2022-11-18 10:50 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: linux-arm-kernel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Mark Brown, Anshuman Khandual, Richard Henderson

On Fri, 18 Nov 2022 at 11:38, Catalin Marinas <catalin.marinas@arm.com> wrote:
>
> Hi Ard,
>
> On Thu, Nov 17, 2022 at 02:24:16PM +0100, Ard Biesheuvel wrote:
> > Enable support for LPA2 when running with 16k pages. Unlike with 4k
> > pages, this does not require adding support for 5 level paging, but
> > beyond that, there is no fundamental difference between LPA2 support on
> > 4k or 16k pages.
>
> We have some patches already from Anshuman, targeting both 4K and 16K
> pages:
>
> https://lore.kernel.org/r/1632998116-11552-1-git-send-email-anshuman.khandual@arm.com
>

Ah right - I was aware that Anshuman had been looking into this as
well, but I did not realise working code had been sent to the list.

That series doesn't cover 5 level paging yet, right?

> I don't think they've been rebased on top of 6.1-rcX though. Could you
> please liaise with Anshuman and agree on a way forward? I'd rather only
> review a single series if they do the same thing. I have a preference
> for a more complete solution (4K and 16K) rather than just 16K pages. I
> think we can even ignore some corner cases like 39-bit VA (if anyone is
> asking, we could do it later but it doesn't seem realistic).
>

If  we can agree that we don't need more than 48 bits for the ID map
(at least for the time being), this all fits quite nicely on top of
the boot code refactor that i sent out last week, where the code in
head.S is only responsible for creating the [initial] ID map, and
everything else is done from C code.

I'll have a look today at how much additional work is needed on top of
this series to accommodate 4k 52-bit VA and PA support, but beyond
adding p4d handling in some places, I think it should be fairly
limited.

> And a question for Anshuman: do you plan to refresh your series?
>

Yeah let's align on a way forward here. Apologies for stepping on
this, I wasn't aware how much actual code you had already written.

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages
  2022-11-18 10:50   ` Ard Biesheuvel
@ 2022-11-18 11:04     ` Ryan Roberts
  2022-11-18 11:53     ` Anshuman Khandual
  1 sibling, 0 replies; 13+ messages in thread
From: Ryan Roberts @ 2022-11-18 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 18/11/2022 10:50, Ard Biesheuvel wrote:
> On Fri, 18 Nov 2022 at 11:38, Catalin Marinas <catalin.marinas@arm.com> wrote:
>>
>> Hi Ard,
>>
>> On Thu, Nov 17, 2022 at 02:24:16PM +0100, Ard Biesheuvel wrote:
>>> Enable support for LPA2 when running with 16k pages. Unlike with 4k
>>> pages, this does not require adding support for 5 level paging, but
>>> beyond that, there is no fundamental difference between LPA2 support on
>>> 4k or 16k pages.
>>
>> We have some patches already from Anshuman, targeting both 4K and 16K
>> pages:
>>
>> https://lore.kernel.org/r/1632998116-11552-1-git-send-email-anshuman.khandual@arm.com

FYI, I also have a set of patches that implements LPA2 (4K and 16K pages
including 5 levels for 4K case) for kvm stage2 and hyp stage1. This works
independently of the kernel stage1 work, but I've been waiting for Anshuman's
rebase for 6.1 to do my final testing before submitting to the list (without
those patches I can't test the stage2 OA >48 bits case).

Hope I'm not stepping on anyone's toes - shout if so.

Thanks,
Ryan


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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages
  2022-11-18 10:38 ` [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Catalin Marinas
  2022-11-18 10:50   ` Ard Biesheuvel
@ 2022-11-18 11:18   ` Anshuman Khandual
  1 sibling, 0 replies; 13+ messages in thread
From: Anshuman Khandual @ 2022-11-18 11:18 UTC (permalink / raw)
  To: Catalin Marinas, Ard Biesheuvel
  Cc: linux-arm-kernel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Mark Brown, Richard Henderson



On 11/18/22 16:08, Catalin Marinas wrote:
> Hi Ard,
> 
> On Thu, Nov 17, 2022 at 02:24:16PM +0100, Ard Biesheuvel wrote:
>> Enable support for LPA2 when running with 16k pages. Unlike with 4k
>> pages, this does not require adding support for 5 level paging, but
>> beyond that, there is no fundamental difference between LPA2 support on
>> 4k or 16k pages.
> We have some patches already from Anshuman, targeting both 4K and 16K
> pages:
> 
> https://lore.kernel.org/r/1632998116-11552-1-git-send-email-anshuman.khandual@arm.com
> 
> I don't think they've been rebased on top of 6.1-rcX though. Could you
> please liaise with Anshuman and agree on a way forward? I'd rather only
> review a single series if they do the same thing. I have a preference
> for a more complete solution (4K and 16K) rather than just 16K pages. I
> think we can even ignore some corner cases like 39-bit VA (if anyone is
> asking, we could do it later but it doesn't seem realistic).
> 
> And a question for Anshuman: do you plan to refresh your series?
This contains above series rebased on v6.1-rc1, but without an working idmap
though, which prevents booting the kernel loaded beyond 48 bits PA.

https://gitlab.arm.com/linux-arm/linux-anshuman/-/commits/lpa2/rfc/v2/

But in the local tree, fixed 'init_idmap_pg_dir' to boot the kernel beyond 48
bit physical address for [4K|48VA|52PA], but still working towards getting the
runtime 'idmap_pg_dir' right, although the kernel still boots if 'init_pg_dir'
is used instead in all such places.

Regardless, I will post the series early next week for all of us to sync up.

- Anshuman

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages
  2022-11-18 10:50   ` Ard Biesheuvel
  2022-11-18 11:04     ` Ryan Roberts
@ 2022-11-18 11:53     ` Anshuman Khandual
  1 sibling, 0 replies; 13+ messages in thread
From: Anshuman Khandual @ 2022-11-18 11:53 UTC (permalink / raw)
  To: Ard Biesheuvel, Catalin Marinas
  Cc: linux-arm-kernel, Marc Zyngier, Will Deacon, Mark Rutland,
	Kees Cook, Mark Brown, Richard Henderson



On 11/18/22 16:20, Ard Biesheuvel wrote:
> On Fri, 18 Nov 2022 at 11:38, Catalin Marinas <catalin.marinas@arm.com> wrote:
>>
>> Hi Ard,
>>
>> On Thu, Nov 17, 2022 at 02:24:16PM +0100, Ard Biesheuvel wrote:
>>> Enable support for LPA2 when running with 16k pages. Unlike with 4k
>>> pages, this does not require adding support for 5 level paging, but
>>> beyond that, there is no fundamental difference between LPA2 support on
>>> 4k or 16k pages.
>>
>> We have some patches already from Anshuman, targeting both 4K and 16K
>> pages:
>>
>> https://lore.kernel.org/r/1632998116-11552-1-git-send-email-anshuman.khandual@arm.com
>>
> 
> Ah right - I was aware that Anshuman had been looking into this as
> well, but I did not realise working code had been sent to the list.
> 
> That series doesn't cover 5 level paging yet, right?

The posted series last year was to enable 52 bit PA for all VA configs on
4K and 16K page sizes. There was a fix (and other changes) to idmap which
enabled two additional idmap levels, to support much spaced VA-PA configs
for FEAT_LPA2, but now those idmap changes need to be reworked after your
recent boot code changes.

But it never enabled 52 bit VA (although I had some local changes) which
would have required proper 5 level paging.

> 
>> I don't think they've been rebased on top of 6.1-rcX though. Could you
>> please liaise with Anshuman and agree on a way forward? I'd rather only
>> review a single series if they do the same thing. I have a preference
>> for a more complete solution (4K and 16K) rather than just 16K pages. I
>> think we can even ignore some corner cases like 39-bit VA (if anyone is
>> asking, we could do it later but it doesn't seem realistic).
>>
> 
> If  we can agree that we don't need more than 48 bits for the ID map
> (at least for the time being), this all fits quite nicely on top of
> the boot code refactor that i sent out last week, where the code in
> head.S is only responsible for creating the [initial] ID map, and
> everything else is done from C code.

I have some changes to 'init_idmap_pg_dir' creation in the assembly code
i.e create_idmap which gets [4K|52PA|48VA] to boot with kernel loaded
beyond 48 bits PA. The problem is, it gets stuck at "smp: Bringing up
secondary CPUs .." as the runtime 'idmap_pg_dir' created with C code
create_idmap() does not handle (does not create required additional
pgtable levels) when VA=48.

Something else I discovered is that current 'idmap_pg_dir' does not work
with an existing config [64K|52PA|48PA] when vmlinux is loaded beyond 48
bits PA. After fixing this existing problem, my plan was to enable it for
FEAT_LPA2 configs on 4K/16K.

> 
> I'll have a look today at how much additional work is needed on top of
> this series to accommodate 4k 52-bit VA and PA support, but beyond
> adding p4d handling in some places, I think it should be fairly
> limited.
> 
>> And a question for Anshuman: do you plan to refresh your series?
>>
> 
> Yeah let's align on a way forward here. Apologies for stepping on
> this, I wasn't aware how much actual code you had already written.

No worries. Let sync up on Monday, or any other time suitable for you.
I can walk you through all that I have, all that planed etc, then we
could figure out how to proceed further.

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2022-11-18 11:54 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-17 13:24 [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Ard Biesheuvel
2022-11-17 13:24 ` [RFC PATCH 1/7] arm64: ptdump: Disregard unaddressable VA space Ard Biesheuvel
2022-11-17 13:24 ` [RFC PATCH 2/7] arm64: mm: Disable all 52-bit virtual addressing support with arm64.nolva Ard Biesheuvel
2022-11-17 13:24 ` [RFC PATCH 3/7] arm64: mm: Wire up TCR.DS bit to PTE shareability fields Ard Biesheuvel
2022-11-17 13:24 ` [RFC PATCH 4/7] arm64: mm: Support use of 52-bit pgdirs on 48-bit/16k systems Ard Biesheuvel
2022-11-17 13:24 ` [RFC PATCH 5/7] arm64: mm: Add LPA2 support to phys<->pte conversion routines Ard Biesheuvel
2022-11-17 13:24 ` [RFC PATCH 6/7] arm64: Enable LPA2 at boot if supported by the system Ard Biesheuvel
2022-11-17 13:24 ` [RFC PATCH 7/7] arm64: Enable 52-bit virtual addressing for 16k granule configs Ard Biesheuvel
2022-11-18 10:38 ` [RFC PATCH 0/7] arm64: Enable LPA2 support for 16k pages Catalin Marinas
2022-11-18 10:50   ` Ard Biesheuvel
2022-11-18 11:04     ` Ryan Roberts
2022-11-18 11:53     ` Anshuman Khandual
2022-11-18 11:18   ` Anshuman Khandual

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.