From c1c3f9812bcc301fdfbd5b626673a974965b6d4c Mon Sep 17 00:00:00 2001 From: urnenfeld Date: Wed, 16 Mar 2022 16:34:38 +0100 Subject: [PATCH] boot/efi/arm64: Rework exception level handling * Deal additionally with EL1 context * Reuse possible present TTBRx allocations * Dump MMU & System Control Registers Change-Id: If27531f3c9d3fa096da11e8a7d46dd7d82a90e33 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5108 Tested-by: Commit checker robot Reviewed-by: David Karoly Reviewed-by: Fredrik Holmqvist --- .../boot/platform/efi/arch/arm64/arch_mmu.cpp | 18 +++++-- .../platform/efi/arch/arm64/arch_start.cpp | 51 ++++++++++++------- 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/system/boot/platform/efi/arch/arm64/arch_mmu.cpp b/src/system/boot/platform/efi/arch/arm64/arch_mmu.cpp index 4901634e8e..88655cb5e3 100644 --- a/src/system/boot/platform/efi/arch/arm64/arch_mmu.cpp +++ b/src/system/boot/platform/efi/arch/arm64/arch_mmu.cpp @@ -411,14 +411,22 @@ arch_mmu_post_efi_setup(size_t memory_map_size, void arch_mmu_allocate_kernel_page_tables(void) { - uint64* page = CurrentRegime.AllocatePage(); + uint64* page = reinterpret_cast(READ_SPECIALREG(TTBR1_EL1)); - if (page != NULL) { - WRITE_SPECIALREG(TTBR1_EL1, page); - sPageDirectory = page; + // NOTE: On devices supporting multiple translation base registers, TTBR0 must + // be used solely. + if (page == NULL) { + page = CurrentRegime.AllocatePage(); + if (page != NULL) { + WRITE_SPECIALREG(TTBR1_EL1, page); + } else { + panic("Not enough memory for kernel initial page\n"); + } } else { - panic("Not enough memory for kernel initial page\n"); + TRACE(("TTBR1_EL1 present ...")); } + + sPageDirectory = page; } diff --git a/src/system/boot/platform/efi/arch/arm64/arch_start.cpp b/src/system/boot/platform/efi/arch/arm64/arch_start.cpp index 307bdbd020..2cc2f2abb2 100644 --- a/src/system/boot/platform/efi/arch/arm64/arch_start.cpp +++ b/src/system/boot/platform/efi/arch/arm64/arch_start.cpp @@ -150,30 +150,40 @@ arch_start_kernel(addr_t kernelEntry) * On AArch64 UEFI shall execute as 64-bit code at either EL1 or EL2, * depending on whether or not virtualization is available at OS load time." */ - if (arch_exception_level() != 1) { - dprintf("Current Exception Level EL%1ld\n", arch_exception_level()); - if (arch_exception_level() == 2) { - /* Transitioning from EL we lose present MMU configuration - * which we would like to preserve e.g. peripherals mappings */ - if (arch_mmu_enabled()) { - dprintf("MMU Enabled, Translation Table @ %lx Granularity %s, bits %d\n", - arch_mmu_base_register(), - granule_type_str(arch_mmu_user_granule()), - arch_mmu_user_address_bits()); + dprintf("Current Exception Level EL%1lx\n", arch_exception_level()); + dprintf("TTBR0: %" B_PRIx64 " TTBRx: %" B_PRIx64 " SCTLR: %" B_PRIx64 " TCR: %" B_PRIx64 "\n", + arch_mmu_base_register(), + arch_mmu_base_register(true), + _arch_mmu_get_sctlr(), + _arch_mmu_get_tcr()); - dprintf("Kernel entry accessibility W: %x R: %x\n", - arch_mmu_write_access(kernelEntry), - arch_mmu_read_access(kernelEntry)); + if (arch_mmu_enabled()) { + dprintf("MMU Enabled, Granularity %s, bits %d\n", + granule_type_str(arch_mmu_user_granule()), + arch_mmu_user_address_bits()); - arch_mmu_dump_present_tables(); + dprintf("Kernel entry accessibility W: %x R: %x\n", + arch_mmu_write_access(kernelEntry), + arch_mmu_read_access(kernelEntry)); - el2toel1 = true; // we want to print before exit services - } + arch_mmu_dump_present_tables(); + } - } else { - // Not ready, undexpected any transition different than EL2 >> EL1 + switch (arch_exception_level()) { + case 1: + /* arch_cache_disable(); */ + /* arch_mmu_generate_post_efi_page_tables */ + + break; + + case 2: + + el2toel1 = true; // we want to print before exit services + break; + + default: panic("Unexpected Exception Level\n"); - } + break; } @@ -215,6 +225,9 @@ arch_start_kernel(addr_t kernelEntry) _arch_transition_EL2_EL1(); + arch_cache_enable(); + } else { + arch_cache_enable(); }