From 2035fffa1c522a2792cab6103303b75818d827cb Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sat, 9 Mar 2019 13:10:10 -0800 Subject: [PATCH] Fix loading large process images. 2MiB large pages were being used for any large page mapping, but the page manager doesn't correctly handle them everywhere yet. Now only allow them for offset pointers (eg MMIO space) that will never be unmapped. --- src/drivers/nulldrv/main.s | 13 ++++++++++--- src/kernel/log.cpp | 1 + src/kernel/log.h | 1 + src/kernel/main.cpp | 5 +++-- src/kernel/page_manager.cpp | 20 +++++++++++++------- src/kernel/page_manager.h | 6 ++++-- 6 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/drivers/nulldrv/main.s b/src/drivers/nulldrv/main.s index 0aadb8c..8c6c979 100644 --- a/src/drivers/nulldrv/main.s +++ b/src/drivers/nulldrv/main.s @@ -1,15 +1,22 @@ +section .bss +mypid: resq 1 +mychild: resq 1 + +section .text global _start _start: xor rbp, rbp ; Sentinel rbp mov rax, 5 ; GETPID syscall int 0xee - mov r12, rax ; save pid to r12 + mov [mypid], rax mov rax, 8 ; FORK syscall int 0xee + mov [mychild], rax - mov r10, rax + mov r12, [mypid] + mov r13, [mychild] mov rax, 1 ; DEBUG syscall int 0xee @@ -22,7 +29,7 @@ _start: mov rbx, 20 ; sleep timeout .loop: - mov rax, 2 ; MESSAGE syscall + mov rax, 1 ; MESSAGE syscall ;mov rax, 0 ; NOOP syscall ;syscall int 0xee diff --git a/src/kernel/log.cpp b/src/kernel/log.cpp index 5c024c6..5e24038 100644 --- a/src/kernel/log.cpp +++ b/src/kernel/log.cpp @@ -17,6 +17,7 @@ static const char *areas[] = { "driver", "file ", "task ", + "paging", nullptr }; diff --git a/src/kernel/log.h b/src/kernel/log.h index c2b2e8a..551dc6f 100644 --- a/src/kernel/log.h +++ b/src/kernel/log.h @@ -14,6 +14,7 @@ enum class logs driver, fs, task, + paging, max }; diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index 541977e..cfb28f5 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -38,13 +38,14 @@ init_console() cons->puts(GIT_VERSION " booting...\n"); log::init(cons); - //log::enable(logs::apic, log::level::debug); - //log::enable(logs::device, log::level::info); + log::enable(logs::apic, log::level::info); + log::enable(logs::device, log::level::info); log::enable(logs::driver, log::level::debug); log::enable(logs::memory, log::level::debug); log::enable(logs::fs, log::level::debug); log::enable(logs::task, log::level::debug); log::enable(logs::boot, log::level::debug); + log::enable(logs::paging, log::level::warn); } void diff --git a/src/kernel/page_manager.cpp b/src/kernel/page_manager.cpp index d15b4ff..3a6dbb4 100644 --- a/src/kernel/page_manager.cpp +++ b/src/kernel/page_manager.cpp @@ -92,7 +92,7 @@ page_table * page_manager::copy_table(page_table *from, page_table::level lvl) { page_table *to = get_table_page(); - log::debug(logs::memory, "Page manager copying level %d table at %016lx to %016lx.", lvl, from, to); + log::debug(logs::paging, "Page manager copying level %d table at %016lx to %016lx.", lvl, from, to); if (lvl == page_table::level::pml4) { to->entries[510] = m_kernel_pml4->entries[510]; @@ -129,7 +129,7 @@ page_manager::copy_table(page_table *from, page_table::level lvl) } if (pages_copied) - log::debug(logs::memory, " copied %3u pages", pages_copied); + log::debug(logs::paging, " copied %3u pages", pages_copied); return to; } @@ -147,8 +147,10 @@ page_manager::map_offset_pointer(void **pointer, size_t length) uintptr_t v = *p + page_offset; uintptr_t c = ((length - 1) / frame_size) + 1; + log::info(logs::paging, "Mapping offset pointer region at %016lx size 0x%lx", *pointer, length); + page_table *pml4 = get_pml4(); - page_in(pml4, *p, v, c); + page_in(pml4, *p, v, c, false, true); *p = v; } @@ -179,7 +181,7 @@ page_manager::get_table_page() } reinterpret_cast(virt)->next = nullptr; - log::debug(logs::memory, "Mappd %d new page table pages at %lx", n, phys); + log::info(logs::paging, "Mappd %d new page table pages at %lx", n, phys); } free_page_header *page = m_page_cache; @@ -210,7 +212,7 @@ page_manager::map_pages(uintptr_t address, size_t count, bool user, page_table * uintptr_t phys = 0; size_t n = m_frames.allocate(count, &phys); - log::debug(logs::memory, "Paging in %d pages at p:%016lx to v:%016lx into %016lx table", + log::info(logs::paging, "Paging in %d pages at p:%016lx to v:%016lx into %016lx table", n, phys, address, pml4); page_in(pml4, phys, address, n, user); @@ -283,8 +285,11 @@ page_manager::check_needs_page(page_table *table, unsigned index, bool user) } void -page_manager::page_in(page_table *pml4, uintptr_t phys_addr, uintptr_t virt_addr, size_t count, bool user) +page_manager::page_in(page_table *pml4, uintptr_t phys_addr, uintptr_t virt_addr, size_t count, bool user, bool large) { + log::debug(logs::paging, "page_in for table %016lx p:%016lx v:%016lx c:%4d u:%d l:%d", + pml4, phys_addr, virt_addr, count, user, large); + page_table_indices idx{virt_addr}; page_table *tables[4] = {pml4, nullptr, nullptr, nullptr}; @@ -301,7 +306,8 @@ page_manager::page_in(page_table *pml4, uintptr_t phys_addr, uintptr_t virt_addr tables[2] = tables[1]->get(idx[1]); for (; idx[2] < 512; idx[2] += 1, idx[3] = 0) { - if (idx[3] == 0 && + if (large && + idx[3] == 0 && count >= 512 && tables[2]->get(idx[2]) == nullptr) { // Do a 2MiB page instead diff --git a/src/kernel/page_manager.h b/src/kernel/page_manager.h index 38c3ad4..548bcf2 100644 --- a/src/kernel/page_manager.h +++ b/src/kernel/page_manager.h @@ -136,13 +136,15 @@ private: /// \arg phys_addr The starting physical address of the pages to be mapped /// \arg virt_addr The starting virtual address ot the memory to be mapped /// \arg count The number of pages to map - /// \art user True if this is a userspace mapping + /// \arg user True if this is a userspace mapping + /// \arg large Whether to allow large pages void page_in( page_table *pml4, uintptr_t phys_addr, uintptr_t virt_addr, size_t count, - bool user = false); + bool user = false, + bool large = false); /// Low-level routine for unmapping a number of pages from the given page table. /// \arg pml4 The root page table for this mapping