[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.
This commit is contained in:
Justin C. Miller
2022-02-12 01:31:28 -08:00
parent d7bf156b30
commit ba610864c7
2 changed files with 10 additions and 7 deletions

View File

@@ -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; uintptr_t phys = e & ~0xfffull;
if (e & page_table::flag::present) { if (e & page_table::flag::present) {
uint64_t orig = e;
e = 0;
if (orig & page_table::flag::accessed) {
auto *addr = reinterpret_cast<const uint8_t *>(it.vaddress());
asm ( "invlpg %0" :: "m"(*addr) : "memory" );
}
if (free_count && phys == free_start + (free_count * frame_size)) { if (free_count && phys == free_start + (free_count * frame_size)) {
++free_count; ++free_count;
} else { } else {
@@ -238,7 +244,6 @@ vm_space::clear(const obj::vm_area &vma, uintptr_t offset, size_t count, bool fr
} }
} }
e = 0;
++it; ++it;
} }
@@ -286,12 +291,14 @@ vm_space::handle_fault(uintptr_t addr, fault_type fault)
if (fault && fault_type::present) if (fault && fault_type::present)
return false; return false;
uintptr_t page = (addr & ~0xfffull);
uintptr_t base = 0; uintptr_t base = 0;
obj::vm_area *area = get(addr, &base); obj::vm_area *area = get(addr, &base);
if (!area) if (!area)
return false; return false;
uintptr_t offset = (addr & ~0xfffull) - base; uintptr_t offset = page - base;
uintptr_t phys_page = 0; uintptr_t phys_page = 0;
if (!area->get_page(offset, phys_page)) if (!area->get_page(offset, phys_page))
return false; return false;

View File

@@ -15,7 +15,7 @@ using bootproto::module_program;
extern j6_handle_t __handle_self; extern j6_handle_t __handle_self;
extern j6_handle_t __handle_sys; 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 size_t stack_size = 0x10000;
constexpr uintptr_t stack_top = 0x80000000000; 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; return false;
} }
uintptr_t load_addr = load_addr_base;
for (auto &seg : progelf.programs()) { for (auto &seg : progelf.programs()) {
if (seg.type != elf::segment_type::load) if (seg.type != elf::segment_type::load)
continue; 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); sprintf(err_msg, " ** error loading program '%s': unmapping sub vma: %lx", prog.filename, res);
return false; return false;
} }
load_addr += 0x1000 * ((seg.mem_size + 0xfff) >> 12);
} }
j6_handle_t stack_vma = j6_handle_invalid; j6_handle_t stack_vma = j6_handle_invalid;