From f61fb770f082a11de41f6fb0d799fefed6bfd2a7 Mon Sep 17 00:00:00 2001 From: David Karoly Date: Tue, 30 May 2023 19:21:31 +0200 Subject: [PATCH] kernel/arm: don't set Accessed Flag when initially mapping a page Pages should not be marked as accessed when initially mapping them. However, there's a short interval during kernel startup when new pages are mapped but the fault handler is not installed yet. Therefore, we set Accessed Flag to 1 in early_map. Once the kernel initialization has progressed enough, we start mapping new pages with Accessed Flag set to 0. The chicken and egg problem of initially mapping the vector page is tackled by preallocating the vector page in the boot loader. Change-Id: Ie3be4f81812d7a090af57e8c79420598d16182b9 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6450 Reviewed-by: Fredrik Holmqvist Tested-by: Commit checker robot --- .../private/system/arch/arm/arch_cpu_defs.h | 2 + .../boot/platform/efi/arch/arm/arch_mmu.cpp | 14 ++++++ src/system/kernel/arch/arm/arch_int.cpp | 50 +++++++------------ .../arm/paging/32bit/ARMPagingMethod32Bit.cpp | 3 +- .../arm/paging/32bit/ARMPagingMethod32Bit.h | 3 ++ 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/headers/private/system/arch/arm/arch_cpu_defs.h b/headers/private/system/arch/arm/arch_cpu_defs.h index c7c6f17ece..53c580a089 100644 --- a/headers/private/system/arch/arm/arch_cpu_defs.h +++ b/headers/private/system/arch/arm/arch_cpu_defs.h @@ -24,6 +24,8 @@ #define CPSR_F 0x40 #define CPSR_I 0x80 +#define SCTLR_HIGH_VECTORS 0x00002000 + #define FSR_WNR 0x800 #define FSR_LPAE 0x200 diff --git a/src/system/boot/platform/efi/arch/arm/arch_mmu.cpp b/src/system/boot/platform/efi/arch/arm/arch_mmu.cpp index 57cf3abb48..38fd96cf4f 100644 --- a/src/system/boot/platform/efi/arch/arm/arch_mmu.cpp +++ b/src/system/boot/platform/efi/arch/arm/arch_mmu.cpp @@ -35,6 +35,8 @@ static constexpr bool kTracePageDirectory = false; #define PHYSICAL_MEMORY_LOW 0x00000000 #define PHYSICAL_MEMORY_HIGH 0x8000000000ull +#define USER_VECTOR_ADDR_HIGH 0xffff0000 + #define ALIGN_PAGEDIR (1024 * 16) #define MAX_PAGE_TABLES 192 #define PAGE_TABLE_AREA_SIZE (MAX_PAGE_TABLES * ARM_MMU_L2_COARSE_TABLE_SIZE) @@ -42,6 +44,7 @@ static constexpr bool kTracePageDirectory = false; static uint32_t *sPageDirectory = NULL; static uint32_t *sNextPageTable = NULL; static uint32_t *sLastPageTable = NULL; +static uint32_t *sVectorTable = (uint32_t*)USER_VECTOR_ADDR_HIGH; static void @@ -232,12 +235,23 @@ arch_mmu_allocate_page_tables(void) } +static void +arch_mmu_allocate_vector_table(void) +{ + if (platform_allocate_region((void **)&sVectorTable, B_PAGE_SIZE, 0, false) != B_OK) + panic("Failed to allocate vector table."); + + memset(sVectorTable, 0, B_PAGE_SIZE); +} + + uint32_t arch_mmu_generate_post_efi_page_tables(size_t memoryMapSize, efi_memory_descriptor *memoryMap, size_t descriptorSize, uint32_t descriptorVersion) { arch_mmu_allocate_page_tables(); + arch_mmu_allocate_vector_table(); build_physical_memory_list(memoryMapSize, memoryMap, descriptorSize, descriptorVersion, diff --git a/src/system/kernel/arch/arm/arch_int.cpp b/src/system/kernel/arch/arm/arch_int.cpp index 872f63cbfb..31be5687f6 100644 --- a/src/system/kernel/arch/arm/arch_int.cpp +++ b/src/system/kernel/arch/arm/arch_int.cpp @@ -60,8 +60,6 @@ extern int _vectors_start; extern int _vectors_end; -static area_id sVectorPageArea; -static void *sVectorPageAddress; static area_id sUserVectorPageArea; static void *sUserVectorPageAddress; //static fdt_module_info *sFdtModule; @@ -120,52 +118,40 @@ print_iframe(const char *event, struct iframe *frame) } +extern "C" void arm_vector_init(void); + + status_t arch_int_init(kernel_args *args) { + TRACE("arch_int_init\n"); + + // copy vector code to vector page + memcpy((void*)USER_VECTOR_ADDR_HIGH, &_vectors_start, VECTORPAGE_SIZE); + + // initialize stack for vectors + arm_vector_init(); + + // enable high vectors + arm_set_sctlr(arm_get_sctlr() | SCTLR_HIGH_VECTORS); + return B_OK; } -extern "C" void arm_vector_init(void); - - status_t arch_int_init_post_vm(kernel_args *args) { - // create a read/write kernel area - sVectorPageArea = create_area("vectorpage", (void **)&sVectorPageAddress, - B_ANY_ADDRESS, VECTORPAGE_SIZE, B_FULL_LOCK, - B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA); - if (sVectorPageArea < 0) - panic("vector page could not be created!"); + TRACE("arch_int_init_post_vm\n"); - // clone it at a fixed address with user read/only permissions sUserVectorPageAddress = (addr_t*)USER_VECTOR_ADDR_HIGH; - sUserVectorPageArea = clone_area("user_vectorpage", + sUserVectorPageArea = create_area("user_vectorpage", (void **)&sUserVectorPageAddress, B_EXACT_ADDRESS, - B_READ_AREA | B_EXECUTE_AREA, sVectorPageArea); + B_PAGE_SIZE, B_ALREADY_WIRED, B_READ_AREA | B_EXECUTE_AREA); if (sUserVectorPageArea < 0) panic("user vector page @ %p could not be created (%x)!", - sVectorPageAddress, sUserVectorPageArea); - - // copy vectors into the newly created area - memcpy(sVectorPageAddress, &_vectors_start, VECTORPAGE_SIZE); - - arm_vector_init(); - - // see if high vectors are enabled - if ((arm_get_sctlr() & (1 << 13)) != 0) - dprintf("High vectors already enabled\n"); - else { - arm_set_sctlr(arm_get_sctlr() | (1 << 13)); - - if ((arm_get_sctlr() & (1 << 13)) == 0) - dprintf("Unable to enable high vectors!\n"); - else - dprintf("Enabled high vectors\n"); - } + sUserVectorPageAddress, sUserVectorPageArea); if (strncmp(args->arch_args.interrupt_controller.kind, INTC_KIND_GICV2, sizeof(args->arch_args.interrupt_controller.kind)) == 0) { diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp index 05fdc35c87..2b852e9947 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp @@ -408,7 +408,7 @@ ARMPagingMethod32Bit::MapEarly(kernel_args* args, addr_t virtualAddress, // now, fill in the pentry PutPageTableEntryInTable(ptEntry, - physicalAddress, attributes, 0, IS_KERNEL_ADDRESS(virtualAddress)); + physicalAddress, attributes | PAGE_ACCESSED, 0, IS_KERNEL_ADDRESS(virtualAddress)); return B_OK; } @@ -502,7 +502,6 @@ ARMPagingMethod32Bit::PutPageTableEntryInTable(page_table_entry* entry, | ARM_MMU_L2_TYPE_SMALLNEW | MemoryTypeToPageTableEntryFlags(memoryType) | AttributesToPageTableEntryFlags(attributes) - | ARM_MMU_L2_FLAG_AP0 | (globalPage ? 0 : ARM_MMU_L2_FLAG_NG); // put it in the page table diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h index f0016d859e..bb9a5d2f60 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h +++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h @@ -169,6 +169,9 @@ ARMPagingMethod32Bit::AttributesToPageTableEntryFlags(uint32 attributes) apFlags |= ARM_MMU_L2_FLAG_XN; } + if ((attributes & PAGE_ACCESSED) != 0) + apFlags |= ARM_MMU_L2_FLAG_AP0; + return apFlags; }