diff mbox series

[06/10] arm64: mm: Handle scope beyond the capacity of kernel pgtable in mmu_head_create_pgd_mapping()

Message ID 20240313125711.20651-7-piliu@redhat.com (mailing list archive)
State New, archived
Headers show
Series arm64: mm: Use __create_pgd_mapping_locked() in | expand

Commit Message

Pingfan Liu March 13, 2024, 12:57 p.m. UTC
This patch serves the same purpose as the
commit fa2a8445b1d3 ("arm64: allow ID map to be extended to 52 bits")

Since it is harmless to ditto init_pg_dir, there is no need to
distinguish between init_idmap_pg_dir and init_pg_dir.

Signed-off-by: Pingfan Liu <piliu@redhat.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
To: linux-arm-kernel@lists.infradead.org
---
 arch/arm64/mm/mmu_head.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
diff mbox series

Patch

diff --git a/arch/arm64/mm/mmu_head.c b/arch/arm64/mm/mmu_head.c
index e00f6f2c7bec..2df91e62ddb0 100644
--- a/arch/arm64/mm/mmu_head.c
+++ b/arch/arm64/mm/mmu_head.c
@@ -66,5 +66,23 @@  void INSTRUMENT_OPTION mmu_head_create_pgd_mapping(pgd_t *pgdir, phys_addr_t phy
 	virt = ALIGN_DOWN(virt, SWAPPER_BLOCK_SIZE);
 	end = ALIGN(end, SWAPPER_BLOCK_SIZE);
 	size = end - phys;
+	/*
+	 * In case that the kernel routines support small VA range while the boot image
+	 * is put beyond the scope, blindless extending the pgtable by one level
+	 */
+	if ((IS_ENABLED(CONFIG_ARM64_16K_PAGES) && IS_ENABLED(CONFIG_ARM64_VA_BITS_36)) ||
+	    (IS_ENABLED(CONFIG_ARM64_64K_PAGES) && IS_ENABLED(CONFIG_ARM64_VA_BITS_42)) ||
+	    (IS_ENABLED(CONFIG_ARM64_4K_PAGES) && IS_ENABLED(CONFIG_ARM64_VA_BITS_39))) {
+		unsigned long pgd_paddr;
+		pgd_t *pgd;
+		pgd_t pgd_val;
+
+		pgd_paddr = headpool_pgtable_alloc(0);
+		pgd_val = __pgd(pgd_paddr | P4D_TYPE_TABLE);
+		/* The shift should be one more level than PGDIR_SHIFT */
+		pgd = pgdir + (virt >> ARM64_HW_PGTABLE_LEVEL_SHIFT(3 - CONFIG_PGTABLE_LEVELS));
+		set_pgd(pgd, pgd_val);
+		pgdir = pgd;
+	}
 	__create_pgd_mapping_locked(pgdir, phys, virt, size, prot, pgtable_alloc, flags);
 }