git: 94b09d388b81 - main - arm64: map kernel using large pages when page size is 16K

From: Alan Cox <alc_at_FreeBSD.org>
Date: Sun, 12 May 2024 23:48:50 UTC
The branch main has been updated by alc:

URL: https://cgit.FreeBSD.org/src/commit/?id=94b09d388b81eb724769e506cdf0f51bba9b73fb

commit 94b09d388b81eb724769e506cdf0f51bba9b73fb
Author:     Alan Cox <alc@FreeBSD.org>
AuthorDate: 2024-05-11 06:09:39 +0000
Commit:     Alan Cox <alc@FreeBSD.org>
CommitDate: 2024-05-12 23:22:38 +0000

    arm64: map kernel using large pages when page size is 16K
    
    When the page size is 16K, use ATTR_CONTIGUOUS to map the kernel code
    and data sections using 2M pages.  Previously, they were mapped using
    16K pages.
    
    Reviewed by:    markj
    Tested by:      markj
    Differential Revision:  https://reviews.freebsd.org/D45162
---
 sys/arm64/arm64/locore.S | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S
index f53cd365de55..fffebe8f2b02 100644
--- a/sys/arm64/arm64/locore.S
+++ b/sys/arm64/arm64/locore.S
@@ -516,11 +516,10 @@ booti_no_fdt:
 common:
 #if PAGE_SIZE != PAGE_SIZE_4K
 	/*
-	 * Create L3 pages. The kernel will be loaded at a 2M aligned
-	 * address, however L2 blocks are too large when the page size is
-	 * not 4k to map the kernel with such an aligned address. However,
-	 * when the page size is larger than 4k, L2 blocks are too large to
-	 * map the kernel with such an alignment.
+	 * Create L3 and L3C pages. The kernel will be loaded at a 2M aligned
+	 * address, enabling the creation of L3C pages. However, when the page
+	 * size is larger than 4k, L2 blocks are too large to map the kernel
+	 * with 2M alignment.
 	 */
 #define	PTE_SHIFT	L3_SHIFT
 #define	BUILD_PTE_FUNC	build_l3_page_pagetable
@@ -784,13 +783,17 @@ LENTRY(link_l2_pagetable)
 LEND(link_l2_pagetable)
 
 /*
- * Builds count level 3 page table entries
+ * Builds count level 3 page table entries. Uses ATTR_CONTIGUOUS to create
+ * large page (L3C) mappings when the current VA and remaining count allow
+ * it.
  *  x6  = L3 table
  *  x7  = Block attributes
  *  x8  = VA start
  *  x9  = PA start (trashed)
  *  x10 = Entry count (trashed)
  *  x11, x12 and x13 are trashed
+ *
+ * VA start (x8) modulo L3C_SIZE must equal PA start (x9) modulo L3C_SIZE.
  */
 LENTRY(build_l3_page_pagetable)
 	/*
@@ -811,8 +814,17 @@ LENTRY(build_l3_page_pagetable)
 	/* Only use the output address bits */
 	lsr	x9, x9, #L3_SHIFT
 
+	/* Check if an ATTR_CONTIGUOUS mapping is possible */
+1:	tst	x11, #(L3C_ENTRIES - 1)
+	b.ne	2f
+	cmp	x10, #L3C_ENTRIES
+	b.lo	3f
+	orr	x12, x12, #(ATTR_CONTIGUOUS)
+	b	2f
+3:	and	x12, x12, #(~ATTR_CONTIGUOUS)
+
 	/* Set the physical address for this virtual address */
-1:	orr	x13, x12, x9, lsl #L3_SHIFT
+2:	orr	x13, x12, x9, lsl #L3_SHIFT
 
 	/* Store the entry */
 	str	x13, [x6, x11, lsl #3]