From ba610864c76939a1da8562cce94d2fbbff9d0d5b Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sat, 12 Feb 2022 01:31:28 -0800 Subject: [PATCH] [kernel] Add TLB invalidation when unmapping pages This has always been on the todo list, but it finally bit me. srv.init re-uses load addresses when loading multiple programs, and collision between reused addresses was causing corruption without the TLB flush. Now srv.init also doesn't increment its load address for sections when loading a single program either, since unmapping pages actually works. --- src/kernel/vm_space.cpp | 11 +++++++++-- src/user/srv.init/loader.cpp | 6 +----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/kernel/vm_space.cpp b/src/kernel/vm_space.cpp index bb7843a..63e8946 100644 --- a/src/kernel/vm_space.cpp +++ b/src/kernel/vm_space.cpp @@ -228,6 +228,12 @@ vm_space::clear(const obj::vm_area &vma, uintptr_t offset, size_t count, bool fr uintptr_t phys = e & ~0xfffull; if (e & page_table::flag::present) { + uint64_t orig = e; + e = 0; + if (orig & page_table::flag::accessed) { + auto *addr = reinterpret_cast(it.vaddress()); + asm ( "invlpg %0" :: "m"(*addr) : "memory" ); + } if (free_count && phys == free_start + (free_count * frame_size)) { ++free_count; } else { @@ -238,7 +244,6 @@ vm_space::clear(const obj::vm_area &vma, uintptr_t offset, size_t count, bool fr } } - e = 0; ++it; } @@ -286,12 +291,14 @@ vm_space::handle_fault(uintptr_t addr, fault_type fault) if (fault && fault_type::present) return false; + uintptr_t page = (addr & ~0xfffull); + uintptr_t base = 0; obj::vm_area *area = get(addr, &base); if (!area) return false; - uintptr_t offset = (addr & ~0xfffull) - base; + uintptr_t offset = page - base; uintptr_t phys_page = 0; if (!area->get_page(offset, phys_page)) return false; diff --git a/src/user/srv.init/loader.cpp b/src/user/srv.init/loader.cpp index 8272934..472b5b7 100644 --- a/src/user/srv.init/loader.cpp +++ b/src/user/srv.init/loader.cpp @@ -15,7 +15,7 @@ using bootproto::module_program; extern j6_handle_t __handle_self; extern j6_handle_t __handle_sys; -constexpr uintptr_t load_addr_base = 0xf8000000; +constexpr uintptr_t load_addr = 0xf8000000; constexpr size_t stack_size = 0x10000; constexpr uintptr_t stack_top = 0x80000000000; @@ -61,8 +61,6 @@ load_program(const module_program &prog, j6_handle_t sys, char *err_msg) return false; } - uintptr_t load_addr = load_addr_base; - for (auto &seg : progelf.programs()) { if (seg.type != elf::segment_type::load) continue; @@ -95,8 +93,6 @@ load_program(const module_program &prog, j6_handle_t sys, char *err_msg) sprintf(err_msg, " ** error loading program '%s': unmapping sub vma: %lx", prog.filename, res); return false; } - - load_addr += 0x1000 * ((seg.mem_size + 0xfff) >> 12); } j6_handle_t stack_vma = j6_handle_invalid;