From 16ea8ef0c827aeceb630677b7ed93c3fb0e4c398 Mon Sep 17 00:00:00 2001 From: Matthias Rosenfelder Date: Wed, 31 Jan 2024 15:17:45 +1100 Subject: [PATCH] elfloader: Set Exec-Never for Device Memory Type PTE. The ARM spec (ARM DDI 0487J.a) says on page B2-216 ("Aarch64 Application Level Memory Model"): "Hardware does not prevent speculative instruction fetches from a memory location with any of the Device memory attributes unless the memory location is also marked as execute-never for all Exception levels." and "Failure to mark a memory location with any Device memory attribute as execute-never for all Exception levels is a programming error." Similar statements can be found in the chapter about the Aarch32 Application Level Memory Model for aarch32 mode. Signed-off-by: Andy Bui --- elfloader-tool/include/arch-arm/64/mode/aarch64.h | 2 ++ elfloader-tool/include/elfloader_common.h | 2 +- elfloader-tool/src/arch-arm/64/mmu.c | 13 +++++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/elfloader-tool/include/arch-arm/64/mode/aarch64.h b/elfloader-tool/include/arch-arm/64/mode/aarch64.h index e46611c4..89fdcfd6 100644 --- a/elfloader-tool/include/arch-arm/64/mode/aarch64.h +++ b/elfloader-tool/include/arch-arm/64/mode/aarch64.h @@ -63,3 +63,5 @@ #define MT_NORMAL 4 #define MT_NORMAL_WT 5 #define MAIR(_attr, _mt) ((_attr) << ((_mt) * 8)) + +#define IS_DEV_MEM_INDEX(_idx) ((_idx) <= MT_DEVICE_GRE) diff --git a/elfloader-tool/include/elfloader_common.h b/elfloader-tool/include/elfloader_common.h index 7a54c316..c80f143c 100644 --- a/elfloader-tool/include/elfloader_common.h +++ b/elfloader-tool/include/elfloader_common.h @@ -14,7 +14,7 @@ typedef uintptr_t vaddr_t; #define PAGE_BITS 12 -#define BIT(x) (1 << (x)) +#define BIT(x) (1ul << (x)) #define MASK(n) (BIT(n) - 1) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define IS_ALIGNED(n, b) (!((n) & MASK(b))) diff --git a/elfloader-tool/src/arch-arm/64/mmu.c b/elfloader-tool/src/arch-arm/64/mmu.c index c70b5466..35df2a3f 100644 --- a/elfloader-tool/src/arch-arm/64/mmu.c +++ b/elfloader-tool/src/arch-arm/64/mmu.c @@ -142,14 +142,19 @@ static inline uint64_t make_pde_from_ptr(pte_t *pagetable_target) return make_pde(va_to_pa((uintptr_t)pagetable_target)); } -/* ARM DDI 0487I.a, section D8.5.2 */ +/* ARM DDI 0487J.a, section D8.5.2 */ #define INNER_SHAREABLE 3 static inline uint64_t make_pte(paddr_t pa, uint8_t mem_attr_index) { - /* Note: As per R_PYFVQ from the ARM spec, we can always safely set the - * shareability to inner, even for device-type memory. + /* As per R_PYFVQ from the ARM spec, we can always safely set the shareability + * to inner, even for Device memory type. + * For exec-never bit(s), see Table D8-46 for EL2 translation regime (TR) + * and Table D8-45 for all others. + * PXN (bit 53) is RES0 for EL2 TR (Figure D8-16), so we simply always set it. */ - return mask_pa(pa) + uint64_t xn = (IS_DEV_MEM_INDEX(mem_attr_index)) ? (BIT(54) | BIT(53)) : 0; + return xn + | mask_pa(pa) | BIT(10) /* access flag */ #if CONFIG_MAX_NUM_NODES > 1 | (INNER_SHAREABLE << 8)