arm64: Create an empty page table for use as a placeholder page table.

Change-Id: Iff78f06a7abd6b2403e521b252c011d37f657c60
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8103
Haiku-Format: Haiku-format Bot <[email protected]>
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: Fredrik Holmqvist <[email protected]>
This commit is contained in:
Owen Anderson
2024-08-29 08:10:03 +00:00
committed by Adrien Destugues
parent fa359dc091
commit c37d2d8eaa
2 changed files with 30 additions and 0 deletions
@@ -5,5 +5,6 @@
#ifndef _KERNEL_ARCH_ARM64_ARCH_VM_TRANSLATION_MAP_H_
#define _KERNEL_ARCH_ARM64_ARCH_VM_TRANSLATION_MAP_H_
void arch_vm_install_empty_table_ttbr0(void);
#endif /* _KERNEL_ARCH_ARM64_ARCH_VM_TRANSLATION_MAP_H_ */
@@ -8,6 +8,7 @@
#include <boot/kernel_args.h>
#include <vm/VMAddressSpace.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include "PMAPPhysicalPageMapper.h"
#include "VMSAv8TranslationMap.h"
@@ -18,12 +19,37 @@ static char sPhysicalPageMapperData[sizeof(PMAPPhysicalPageMapper)];
// low bit is implicitly zero.
static constexpr uint64_t kTtbrBasePhysAddrMask = (((1UL << 47) - 1) << 1);
// Physical pointer to an empty page table, which is used for break-before-make
// when updating TTBR0_EL1.
static phys_addr_t sEmptyTable;
static void
arch_vm_alloc_empty_table(void)
{
vm_page_reservation reservation;
vm_page_reserve_pages(&reservation, 1, VM_PRIORITY_SYSTEM);
vm_page* page = vm_page_allocate_page(&reservation, PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR);
DEBUG_PAGE_ACCESS_END(page);
sEmptyTable = page->physical_page_number << PAGE_SHIFT;
}
void
arch_vm_install_empty_table_ttbr0(void)
{
WRITE_SPECIALREG(TTBR0_EL1, sEmptyTable);
asm("isb");
}
status_t
arch_vm_translation_map_create_map(bool kernel, VMTranslationMap** _map)
{
phys_addr_t pt = 0;
if (kernel) {
pt = READ_SPECIALREG(TTBR1_EL1) & kTtbrBasePhysAddrMask;
arch_vm_install_empty_table_ttbr0();
}
*_map = new (std::nothrow) VMSAv8TranslationMap(kernel, pt, 12, 48, 1);
@@ -40,6 +66,9 @@ arch_vm_translation_map_init(kernel_args* args, VMPhysicalPageMapper** _physical
{
dprintf("arch_vm_translation_map_init\n");
// Create an empty page table for use when we don't want a userspace page table.
arch_vm_alloc_empty_table();
// nuke TTBR0 mapping, we use identity mapping in kernel space at KERNEL_PMAP_BASE
memset((void*) READ_SPECIALREG(TTBR0_EL1), 0, B_PAGE_SIZE);