git: e9ab9910fa12 - main - arm64: Clean up enabling in-kernel BTI

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Thu, 27 Mar 2025 13:47:47 UTC
The branch main has been updated by andrew:

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

commit e9ab9910fa12ce7b042a83a25dfaf5efdb631a32
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2025-03-27 13:47:28 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2025-03-27 13:47:28 +0000

    arm64: Clean up enabling in-kernel BTI
    
    Some hypervisors incorrectly use the Guarded Page (GP) bit from the
    last level page table as part of the output address. This causes them
    to raise an address size exception as the calculated physical address
    is too large.
    
    Only set the GP bit in the page table when BTI is present.
    
    Reviewed by:    alc, kib, markj
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D49154
---
 sys/arm64/arm64/locore.S | 22 +++++++++++++++++++---
 sys/arm64/arm64/pmap.c   |  3 ++-
 sys/arm64/include/pte.h  |  3 ++-
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S
index 88193b6c93f7..9cf23fcf13a1 100644
--- a/sys/arm64/arm64/locore.S
+++ b/sys/arm64/arm64/locore.S
@@ -87,6 +87,7 @@ ENTRY(_start)
 	 * x26 = Kernel L1 table
 	 * x24 = TTBR1 table
 	 * x22 = PTE shareability attributes
+	 * x21 = BTI guarded page attribute if supported
 	 */
 
 	/* Enable the mmu */
@@ -136,9 +137,13 @@ virtdone:
 	str	x27, [x0, #BP_KERN_TTBR0]
 	str	x23, [x0, #BP_BOOT_EL]
 
-	/* Set this before it's used in kasan_init_early */
+	/* Set these before they are used in kasan_init_early */
 	adrp	x1, pmap_sh_attr
 	str	x22, [x1, :lo12:pmap_sh_attr]
+#ifdef __ARM_FEATURE_BTI_DEFAULT
+	adrp	x1, pmap_gp_attr
+	str	x21, [x1, :lo12:pmap_gp_attr]
+#endif
 
 #ifdef KASAN
 	/* Save bootparams */
@@ -487,6 +492,17 @@ LENTRY(create_pagetables)
 	cmp	x6, x27
 	b.lo	1b
 
+#ifdef __ARM_FEATURE_BTI_DEFAULT
+	/*
+	 * Check if the CPU supports BTI
+	 */
+	mrs	x6, id_aa64pfr1_el1		/* Read the ID register */
+	and	x6, x6, ID_AA64PFR1_BT_MASK	/* Mask the field we need */
+	cmp	x6, xzr				/* Check it's non-zero */
+	cset	x6, ne				/* x6 is set if non-zero */
+	lsl	x21, x6, ATTR_S1_GP_SHIFT	/* Shift to the correct bit */
+#endif
+
 	/*
 	 * Find the shareability attribute we should use. If FEAT_LPA2 is
 	 * enabled then the shareability field is moved from the page table
@@ -785,7 +801,7 @@ LENTRY(build_l2_block_pagetable)
 	orr	x12, x12, #(ATTR_AF)
 	orr	x12, x12, #(ATTR_S1_UXN)
 #ifdef __ARM_FEATURE_BTI_DEFAULT
-	orr	x12, x12, #(ATTR_S1_GP)
+	orr	x12, x12, x21
 #endif
 	/* Set the shareability attribute */
 	orr	x12, x12, x22
@@ -863,7 +879,7 @@ LENTRY(build_l3_page_pagetable)
 	orr	x12, x12, #(ATTR_AF)
 	orr	x12, x12, #(ATTR_S1_UXN)
 #ifdef __ARM_FEATURE_BTI_DEFAULT
-	orr	x12, x12, #(ATTR_S1_GP)
+	orr	x12, x12, x21
 #endif
 	/* Set the shareability attribute */
 	orr	x12, x12, x22
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index 5a3dbbf00203..14ef7dd0169c 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -182,7 +182,8 @@
 #define	pmap_l2_pindex(v)	((v) >> L2_SHIFT)
 
 #ifdef __ARM_FEATURE_BTI_DEFAULT
-#define	ATTR_KERN_GP		ATTR_S1_GP
+pt_entry_t __read_mostly pmap_gp_attr;
+#define	ATTR_KERN_GP		pmap_gp_attr
 #else
 #define	ATTR_KERN_GP		0
 #endif
diff --git a/sys/arm64/include/pte.h b/sys/arm64/include/pte.h
index ae6a8694f6c4..464d8c941c56 100644
--- a/sys/arm64/include/pte.h
+++ b/sys/arm64/include/pte.h
@@ -73,7 +73,8 @@ typedef	uint64_t	pt_entry_t;		/* page table entry */
 
 #define	ATTR_CONTIGUOUS		(1UL << 52)
 #define	ATTR_DBM		(1UL << 51)
-#define	ATTR_S1_GP		(1UL << 50)
+#define	ATTR_S1_GP_SHIFT	50
+#define	ATTR_S1_GP		(1UL << ATTR_S1_GP_SHIFT)
 
 /*
  * Largest possible output address field for a level 3 page. Block