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
This commit is contained in:
Andrew Turner 2025-03-27 13:47:28 +00:00
parent 2e16618fe7
commit e9ab9910fa
3 changed files with 23 additions and 5 deletions

View file

@ -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

View file

@ -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

View file

@ -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