As arm64 implementations may support a subset of the architecturally defined granules, we need to check and warn the user if the configured translation granule is not supported. Signed-off-by: Nikos Nikoleris <nikos.nikoleris@xxxxxxx> --- lib/arm64/asm/processor.h | 36 ++++++++++++++++++++++++++++++++++++ lib/arm/mmu.c | 3 +++ 2 files changed, 39 insertions(+) diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index 02665b8..9248689 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -117,5 +117,41 @@ static inline u64 get_ctr(void) extern u32 dcache_line_size; +static inline unsigned long get_id_aa64mmfr0_el1(void) +{ + return read_sysreg(id_aa64mmfr0_el1); +} + +#define ID_AA64MMFR0_TGRAN4_SHIFT 28 +#define ID_AA64MMFR0_TGRAN64_SHIFT 24 +#define ID_AA64MMFR0_TGRAN16_SHIFT 20 + +#define ID_AA64MMFR0_TGRAN4_SUPPORTED 0x0 +#define ID_AA64MMFR0_TGRAN64_SUPPORTED 0x0 +#define ID_AA64MMFR0_TGRAN16_SUPPORTED 0x1 + +static inline bool system_supports_granule(size_t granule) +{ + u32 shift; + u32 val; + u64 mmfr0; + + if (granule == SZ_4K) { + shift = ID_AA64MMFR0_TGRAN4_SHIFT; + val = ID_AA64MMFR0_TGRAN4_SUPPORTED; + } else if (granule == SZ_16K) { + shift = ID_AA64MMFR0_TGRAN16_SHIFT; + val = ID_AA64MMFR0_TGRAN16_SUPPORTED; + } else { + assert(granule == SZ_64K); + shift = ID_AA64MMFR0_TGRAN64_SHIFT; + val = ID_AA64MMFR0_TGRAN64_SUPPORTED; + } + + mmfr0 = get_id_aa64mmfr0_el1(); + + return ((mmfr0 >> shift) & 0xf) == val; +} + #endif /* !__ASSEMBLY__ */ #endif /* _ASMARM64_PROCESSOR_H_ */ diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c index 540a1e8..a3758a0 100644 --- a/lib/arm/mmu.c +++ b/lib/arm/mmu.c @@ -160,6 +160,9 @@ void *setup_mmu(phys_addr_t phys_end) #ifdef __aarch64__ init_alloc_vpage((void*)(4ul << 30)); + + assert_msg(system_supports_granule(PAGE_SIZE), + "Unsupported translation granule %ld\n", PAGE_SIZE); #endif mmu_idmap = alloc_page(); -- 2.17.1