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 <[email protected]>
Reviewed-by: David Karoly <[email protected]>
Reviewed-by: Fredrik Holmqvist <[email protected]>
This commit is contained in:
urnenfeld
2022-03-21 20:06:59 +00:00
committed by Fredrik Holmqvist
parent 09ea42fa68
commit c1c3f9812b
2 changed files with 45 additions and 24 deletions
@@ -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<uint64*>(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;
}
@@ -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();
}