From 8878e0c8157c733f446f5a4f6653bf71253805b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Holz?= Date: Sun, 28 Jan 2024 13:59:52 +0100 Subject: [PATCH] Kernel/riscv64: Implement everything in PageDirectory.cpp This code is heavily based on aarch64's PageDirectory.cpp. --- Kernel/Arch/riscv64/PageDirectory.cpp | 72 ++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/Kernel/Arch/riscv64/PageDirectory.cpp b/Kernel/Arch/riscv64/PageDirectory.cpp index 4e7ab2b0c75..faa14a31ae7 100644 --- a/Kernel/Arch/riscv64/PageDirectory.cpp +++ b/Kernel/Arch/riscv64/PageDirectory.cpp @@ -8,39 +8,84 @@ #include #include +#include #include #include +#include +#include namespace Kernel::Memory { -void PageDirectory::register_page_directory(PageDirectory*) +struct SATPMap { + SpinlockProtected, LockRank::None> map {}; +}; + +static Singleton s_satp_map; + +void PageDirectory::register_page_directory(PageDirectory* page_directory) { - TODO_RISCV64(); + s_satp_map->map.with([&](auto& map) { + map.insert(bit_cast(page_directory->satp()), *page_directory); + }); } -void PageDirectory::deregister_page_directory(PageDirectory*) +void PageDirectory::deregister_page_directory(PageDirectory* page_directory) { - TODO_RISCV64(); + s_satp_map->map.with([&](auto& map) { + map.remove(bit_cast(page_directory->satp())); + }); } -ErrorOr> PageDirectory::try_create_for_userspace(Process&) +ErrorOr> PageDirectory::try_create_for_userspace(Process& process) { - TODO_RISCV64(); + auto directory = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) PageDirectory)); + + directory->m_process = &process; + + directory->m_directory_table = TRY(MM.allocate_physical_page()); + auto kernel_pd_index = (kernel_mapping_base >> VPN_2_OFFSET) & PAGE_TABLE_INDEX_MASK; + for (size_t i = 0; i < kernel_pd_index; i++) { + directory->m_directory_pages[i] = TRY(MM.allocate_physical_page()); + } + + // Share the top 1 GiB of kernel-only mappings (>=kernel_mapping_base) + directory->m_directory_pages[kernel_pd_index] = MM.kernel_page_directory().m_directory_pages[kernel_pd_index]; + + { + InterruptDisabler disabler; + auto& table = *reinterpret_cast(MM.quickmap_page(*directory->m_directory_table)); + for (size_t i = 0; i < array_size(directory->m_directory_pages); i++) { + if (directory->m_directory_pages[i] != nullptr) { + table.raw[i] = ((directory->m_directory_pages[i]->paddr().get()) >> PADDR_PPN_OFFSET) << PTE_PPN_OFFSET; + table.raw[i] |= to_underlying(PageTableEntryBits::Valid); + } + } + MM.unquickmap_page(); + } + + register_page_directory(directory); + return directory; } LockRefPtr PageDirectory::find_current() { - TODO_RISCV64(); + return s_satp_map->map.with([&](auto& map) { + return map.find(bit_cast(RISCV64::CSR::SATP::read())); + }); } -void activate_kernel_page_directory(PageDirectory const&) +void activate_kernel_page_directory(PageDirectory const& page_directory) { - TODO_RISCV64(); + RISCV64::CSR::SATP::write(page_directory.satp()); + Processor::flush_entire_tlb_local(); } -void activate_page_directory(PageDirectory const&, Thread*) +void activate_page_directory(PageDirectory const& page_directory, Thread* thread) { - TODO_RISCV64(); + auto const satp = page_directory.satp(); + thread->regs().satp = satp; + RISCV64::CSR::SATP::write(satp); + Processor::flush_entire_tlb_local(); } UNMAP_AFTER_INIT NonnullLockRefPtr PageDirectory::must_create_kernel_page_directory() @@ -52,7 +97,10 @@ PageDirectory::PageDirectory() = default; UNMAP_AFTER_INIT void PageDirectory::allocate_kernel_directory() { - TODO_RISCV64(); + dmesgln("MM: boot_pdpt @ {}", boot_pdpt); + dmesgln("MM: boot_pd_kernel @ {}", boot_pd_kernel); + m_directory_table = PhysicalPage::create(boot_pdpt, MayReturnToFreeList::No); + m_directory_pages[(kernel_mapping_base >> VPN_2_OFFSET) & PAGE_TABLE_INDEX_MASK] = PhysicalPage::create(boot_pd_kernel, MayReturnToFreeList::No); } PageDirectory::~PageDirectory()