diff --git a/src/kernel/vm_space.cpp b/src/kernel/vm_space.cpp index 98fd6c9..f1052d0 100644 --- a/src/kernel/vm_space.cpp +++ b/src/kernel/vm_space.cpp @@ -256,31 +256,40 @@ vm_space::initialize_tcb(TCB &tcb) ~memory::page_offset; } +size_t +vm_space::allocate(uintptr_t virt, size_t count, uintptr_t *phys) +{ + uintptr_t base = 0; + vm_area *area = get(virt, &base); + + uintptr_t offset = (virt & ~0xfffull) - base; + if (!area || !area->allowed(offset)) + return 0; + + uintptr_t addr = 0; + size_t n = frame_allocator::get().allocate(count, &addr); + + void *mem = memory::to_virtual(addr); + if (area->flags() && vm_flags::zero) + kutil::memset(mem, 0, count * memory::frame_size); + + area->commit(addr, offset, 1); + if (phys) + *phys = addr; + + return n; +} + bool vm_space::handle_fault(uintptr_t addr, fault_type fault) { - uintptr_t page = addr & ~0xfffull; - // TODO: Handle more fult types if (fault && fault_type::present) return false; - uintptr_t base = 0; - vm_area *area = get(addr, &base); - - if (!area || !area->allowed(page-base)) - return false; - - uintptr_t phys = 0; - size_t n = frame_allocator::get().allocate(1, &phys); + size_t n = allocate(addr, 1, nullptr); kassert(n, "Failed to allocate a new page during page fault"); - - if (area->flags() && vm_flags::zero) - kutil::memset(memory::to_virtual(phys), 0, memory::frame_size); - - uintptr_t offset = page - base; - area->commit(phys, offset, 1); - return true; + return n; } size_t diff --git a/src/kernel/vm_space.h b/src/kernel/vm_space.h index 0d229a0..dd2bfa6 100644 --- a/src/kernel/vm_space.h +++ b/src/kernel/vm_space.h @@ -79,6 +79,13 @@ public: fetch = 0x10 }; + /// Allocate pages into virtual memory. May allocate less than requested. + /// \arg virt The virtual address at which to allocate + /// \arg count The number of pages to allocate + /// \arg phys [out] The physical address of the pages allocated + /// \returns The number of pages actually allocated + size_t allocate(uintptr_t virt, size_t count, uintptr_t *phys); + /// Handle a page fault. /// \arg addr Address which caused the fault /// \arg ft Flags from the interrupt about the kind of fault