From 764376196a1169edd9ef5b84d970fd5e393c784f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=AD=A5=E9=AA=A5?= <xubuji20@mails.ucas.ac.cn> Date: Tue, 1 Aug 2023 18:05:23 +0800 Subject: [PATCH] fix: do swap before memory is used out --- kernel/include/mem.h | 3 +++ kernel/irq/irq.cpp | 9 ++++++--- kernel/mem/mem.cpp | 20 ++++++++++++++++++-- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/kernel/include/mem.h b/kernel/include/mem.h index 7e2cb02..312744d 100644 --- a/kernel/include/mem.h +++ b/kernel/include/mem.h @@ -62,6 +62,7 @@ private: SpinLock m_lock; size_t m_max_order; Slice<Node *> m_lists; + size_t free_mem_size; void remove_node(Node *node, size_t order); void insert_node(Node *node, size_t order); @@ -74,6 +75,8 @@ protected: void __free(void *ptr, size_t len) override; public: + int in_swap_process = 0; + BuddyAllocator() = default; void init(Slice<byte> buffer); diff --git a/kernel/irq/irq.cpp b/kernel/irq/irq.cpp index ff10198..37eca1a 100644 --- a/kernel/irq/irq.cpp +++ b/kernel/irq/irq.cpp @@ -56,14 +56,18 @@ void handle_exc_page_fault(Context *c) // try kill process exit(1); } + uintptr_t page_aligned_stval = c->stval & ~0xfff; if (c->scause == EXC_INST_PAGE_FAULT) { - // TODO: swap - // assert(0); + if (is_swapped_page(hart[hartid].proc, page_aligned_stval)) { + do_swap_in(hart[hartid].proc, page_aligned_stval); + return; + } fmt::warn("Inst Page Fault: kill {}({})\n", hart[hartid].proc->pid, hart[hartid].proc->name); dump_context(c); exit(1); return; } + ensure_user_addr((uintptr_t)c->sepc & ~0xfff, 1); uint16_t inst_lo = *((uint16_t *)c->sepc); uint16_t inst_hi = *((uint16_t *)c->sepc + 2); uint32_t inst = ((uint32_t)inst_hi << 16) | inst_lo; // FIXME: compressed inst on page boundary @@ -125,7 +129,6 @@ void handle_exc_page_fault(Context *c) } uint32_t opcode = inst & 0x7f; uint32_t amo_func = (inst & 0xf8000000) >> 27; - uintptr_t page_aligned_stval = c->stval & ~0xfff; if (opcode == 0x3 || (opcode == 0x2f && amo_func == 0x10)) /* load */ { if (is_swapped_page(hart[hartid].proc, page_aligned_stval)) { diff --git a/kernel/mem/mem.cpp b/kernel/mem/mem.cpp index c2947b3..f93c41f 100644 --- a/kernel/mem/mem.cpp +++ b/kernel/mem/mem.cpp @@ -60,6 +60,7 @@ Optional<void *> BuddyAllocator::__try_alloc(size_t size, size_t alignment) { power <<= 1; order++; } + free_mem_size -= PAGE_SIZE << order; size_t order2 = order; size_t power2 = power; @@ -83,11 +84,16 @@ Optional<void *> BuddyAllocator::__try_alloc(size_t size, size_t alignment) { } Optional<void *> BuddyAllocator::__alloc(size_t size, size_t alignment) { + pcb_t *proc = get_current_proc(); + if (in_swap_process == 0 && free_mem_size <= 8 * LARGE_PAGE_SIZE) { + for (size_t npage = 1; npage <= 512; npage++) { + if (do_swap_out_proc(proc, 1) == 0) break; + } + } auto result = __try_alloc(size, alignment); if (result.has_value()) return result.value(); - pcb_t *proc = get_current_proc(); for (size_t npage = 1; npage <= 512; npage++) { - do_swap_out_proc(proc, 1); + if (do_swap_out_proc(proc, 1) == 0) break; result = __try_alloc(size, alignment); if (result.has_value()) return result.value(); } @@ -96,6 +102,7 @@ Optional<void *> BuddyAllocator::__alloc(size_t size, size_t alignment) { void BuddyAllocator::__free(void *ptr, size_t len) { LockGuard locked(&m_lock); + free_mem_size += len; size_t order = 0; size_t power = UNIT; while (power < len) { @@ -158,6 +165,7 @@ void BuddyAllocator::init(Slice<byte> buffer) { free_mem = free_mem.slice(UNIT - align_offset, free_mem.size()); } free_mem = free_mem.slice(0, free_mem.size() - free_mem.size() % UNIT); + free_mem_size = free_mem.size(); set(m_lists, static_cast<Node *>(nullptr)); size_t count = 0; @@ -377,6 +385,8 @@ void do_swap_read(int blk_num, uintptr_t kvaddr) { } void do_swap_out(pcb_t *owner, uintptr_t vaddr) { + buddy_allocator->in_swap_process++; + assert(owner->user_page_list->m_value.find(vaddr) != owner->user_page_list->m_value.end()); mcb_t *mcb = owner->user_page_list->m_value[vaddr]; uintptr_t kvaddr = walk(owner->pgdir->m_value, vaddr).value(); @@ -393,9 +403,13 @@ void do_swap_out(pcb_t *owner, uintptr_t vaddr) { remap3(holder.second->pgdir->m_value, holder.first, 0, new_flags); } buddy_allocator->free(Slice<byte>((byte *)kvaddr, PAGE_SIZE)); + + buddy_allocator->in_swap_process--; } void do_swap_in(pcb_t *owner, uintptr_t vaddr) { + buddy_allocator->in_swap_process++; + assert(owner->user_page_list->m_value.find(vaddr) != owner->user_page_list->m_value.end()); mcb_t *mcb = owner->user_page_list->m_value[vaddr]; assert(mcb->swapped_block > 0); @@ -410,6 +424,8 @@ void do_swap_in(pcb_t *owner, uintptr_t vaddr) { #endif mcb->swapped_block = 0; mcb->swapped_flags = 0; + + buddy_allocator->in_swap_process--; } // mode > 0, collect $mode pages -- GitLab