arm64: Fix cache enable/disable during bootload

* Fix crash in arch_mmu_generate_post_efi_page_tables due to MMU being
  disabled too early. Fixed by only disabling the cache/MMU while TTBRx
  is being written.
* Disable I-cache while TTBRx is being written. This mirrors the
  behavior in u-boot.
* With these fixes, UEFI boot now reaches ExitBootServices before
  crashing.

Change-Id: Iea04765cdf914791b93b3da378b0df56e46a1d9d
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8079
Haiku-Format: Haiku-format Bot <[email protected]>
Reviewed-by: David Karoly <[email protected]>
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Owen Anderson
2024-08-20 15:19:12 +00:00
committed by waddlesplash
parent 9023c0bff8
commit b983396cfc
3 changed files with 4 additions and 8 deletions
@@ -13,10 +13,9 @@ arch_cache_disable()
{ {
if (arch_mmu_cache_enabled()) { if (arch_mmu_cache_enabled()) {
uint64 sctlr = _arch_mmu_get_sctlr(); uint64 sctlr = _arch_mmu_get_sctlr();
sctlr &= ~(SCTLR_M | SCTLR_C); sctlr &= ~(SCTLR_M | SCTLR_C | SCTLR_I);
_arch_mmu_set_sctlr(sctlr); _arch_mmu_set_sctlr(sctlr);
// _arch_cache_flush_invalidate_all();
_arch_cache_clean_poc(); _arch_cache_clean_poc();
_arch_mmu_invalidate_tlb_all(arch_exception_level()); _arch_mmu_invalidate_tlb_all(arch_exception_level());
} }
@@ -28,7 +27,7 @@ arch_cache_enable()
{ {
if (!arch_mmu_cache_enabled()) { if (!arch_mmu_cache_enabled()) {
uint64 sctlr = _arch_mmu_get_sctlr(); uint64 sctlr = _arch_mmu_get_sctlr();
sctlr |= (SCTLR_M | SCTLR_C); sctlr |= (SCTLR_M | SCTLR_C | SCTLR_I);
_arch_mmu_set_sctlr(sctlr); _arch_mmu_set_sctlr(sctlr);
} }
} }
@@ -348,7 +348,9 @@ arch_mmu_allocate_kernel_page_tables(void)
if (page == NULL) { if (page == NULL) {
page = CurrentRegime.AllocatePage(); page = CurrentRegime.AllocatePage();
if (page != NULL) { if (page != NULL) {
arch_cache_disable();
WRITE_SPECIALREG(TTBR1_EL1, page); WRITE_SPECIALREG(TTBR1_EL1, page);
arch_cache_enable();
} else { } else {
panic("Not enough memory for kernel initial page\n"); panic("Not enough memory for kernel initial page\n");
} }
@@ -115,11 +115,6 @@ arch_start_kernel(addr_t kernelEntry)
dprintf("Kernel entry accessibility W: %x R: %x\n", arch_mmu_write_access(kernelEntry), dprintf("Kernel entry accessibility W: %x R: %x\n", arch_mmu_write_access(kernelEntry),
arch_mmu_read_access(kernelEntry)); arch_mmu_read_access(kernelEntry));
if (el == 1) {
// Disable CACHE & MMU before dealing with TTBRx
arch_cache_disable();
}
} }
// Generate page tables for use after ExitBootServices. // Generate page tables for use after ExitBootServices.