Finish micorkernel functions.

This commit is contained in:
TXuian
2024-05-01 12:12:13 +08:00
parent 7a296b2744
commit 50ecc1e520
15 changed files with 132 additions and 95 deletions
@@ -84,9 +84,14 @@ void* slab_alloc(struct slab_allocator* const allocator)
allocator->full->prev = full_head;
}
allocator->full = full_head;
return allocator->full->data + slot * allocator->element_size;
void* return_addr = allocator->full->data + slot * allocator->element_size;
memset(return_addr, 0, allocator->element_size);
return return_addr;
} else {
return allocator->partial->data + slot * allocator->element_size;
void* return_addr = allocator->partial->data + slot * allocator->element_size;
memset(return_addr, 0, allocator->element_size);
return return_addr;
}
}
@@ -109,6 +114,8 @@ void* slab_alloc(struct slab_allocator* const allocator)
allocator->partial->refcount = 1;
}
allocator->partial->bitmap = allocator->bitmap_empty ^ BITMAP_FIRST_BIT;
assert(allocator->partial->data != NULL);
memset(allocator->partial->data, 0, allocator->element_size);
return allocator->partial->data;
}
@@ -62,7 +62,8 @@ static bool _map_pages(uintptr_t* pgdir, uintptr_t vaddr, uintptr_t paddr, uintp
uintptr_t* pte;
while (true) {
if ((pte = _page_walk(pgdir, vaddr, true)) == 0) {
if ((pte = _page_walk(pgdir, vaddr, true)) == NULL) {
ERROR("pte not found for vaddr %x.\n", vaddr);
return false;
}
@@ -81,6 +82,7 @@ static bool _map_pages(uintptr_t* pgdir, uintptr_t vaddr, uintptr_t paddr, uintp
paddr += PAGE_SIZE;
}
assert(vaddr == vaddr_last);
return true;
}
@@ -94,7 +96,8 @@ static bool _unmap_pages(uintptr_t* pgdir, uintptr_t vaddr, uintptr_t len)
uintptr_t* pte;
while (true) {
if ((pte = _page_walk(pgdir, vaddr, true)) == 0) {
if ((pte = _page_walk(pgdir, vaddr, false)) == NULL) {
ERROR("pte not found for vaddr %x.\n", vaddr);
return false;
}
@@ -112,6 +115,7 @@ static bool _unmap_pages(uintptr_t* pgdir, uintptr_t vaddr, uintptr_t len)
vaddr += PAGE_SIZE;
}
assert(vaddr == vaddr_last);
return true;
}
@@ -140,33 +144,6 @@ static bool _map_user_pages(uintptr_t* pgdir, uintptr_t vaddr, uintptr_t paddr,
return _map_pages(pgdir, vaddr, paddr, len, mem_attr);
}
static void _free_user_pgdir(struct TopLevelPageDirectory* pgdir)
{
uintptr_t low_bound = kern_virtmem_buddy.mem_start, high_bound = kern_virtmem_buddy.mem_end;
uintptr_t user_low_bound = user_phy_freemem_buddy.mem_start, user_high_bound = user_phy_freemem_buddy.mem_end;
uintptr_t end_idx = USER_MEM_TOP >> LEVEL3_PDE_SHIFT;
for (uintptr_t i = 0; i < end_idx; i++) {
// free each page table
uintptr_t* pgtbl_paddr = (uintptr_t*)LEVEL4_PTE_ADDR(pgdir->pd_addr[i]);
if (pgtbl_paddr != 0) {
// free each page
for (uintptr_t j = 0; j < NUM_LEVEL4_PTE; j++) {
uintptr_t* page_paddr = (uintptr_t*)ALIGNDOWN(((uintptr_t*)P2V(pgtbl_paddr))[j], PAGE_SIZE);
if (page_paddr != NULL) {
if (LIKELY((uintptr_t)page_paddr >= low_bound && (uintptr_t)page_paddr < high_bound)) {
kfree(P2V(page_paddr));
} else if (LIKELY((uintptr_t)page_paddr >= user_low_bound && (uintptr_t)page_paddr < user_high_bound)) {
raw_free((char*)page_paddr);
}
}
}
kfree(P2V(pgtbl_paddr));
}
}
kfree((char*)pgdir->pd_addr);
}
/// assume that a user pagedir is allocated from [0, size)
/// if new_size > old_size, allocate more space,
/// if old_size > new_size, free extra space, to avoid unnecessary alloc/free.
@@ -191,7 +168,9 @@ static uintptr_t _resize_user_pgdir(struct TopLevelPageDirectory* pgdir, uintptr
}
memset(new_page, 0, PAGE_SIZE);
xizi_pager.map_pages(pgdir->pd_addr, cur_size, V2P(new_page), PAGE_SIZE, false);
if (!xizi_pager.map_pages(pgdir->pd_addr, cur_size, V2P(new_page), PAGE_SIZE, false)) {
return cur_size;
}
cur_size += PAGE_SIZE;
}
@@ -29,6 +29,11 @@ Modification:
*************************************************/
#include <stdint.h>
#include "core.h"
#include "memlayout.h"
#include "assert.h"
#include "buddy.h"
#include "kalloc.h"
#include "pagetable.h"
@@ -36,6 +41,7 @@ uintptr_t* _page_walk(uintptr_t* pgdir, uintptr_t vaddr, bool alloc)
{
// get page table addr
assert(pgdir != NULL);
uintptr_t pde_attr = 0;
_p_pgtbl_mmu_access->MmuPdeAttr(&pde_attr);
@@ -55,4 +61,37 @@ uintptr_t* _page_walk(uintptr_t* pgdir, uintptr_t vaddr, bool alloc)
}
return &pgtbl_vaddr[LEVEL4_PTE_IDX(vaddr)];
}
void _free_user_pgdir(struct TopLevelPageDirectory* pgdir)
{
uintptr_t low_bound = kern_virtmem_buddy.mem_start, high_bound = kern_virtmem_buddy.mem_end;
uintptr_t user_low_bound = user_phy_freemem_buddy.mem_start, user_high_bound = user_phy_freemem_buddy.mem_end;
uintptr_t end_idx = USER_MEM_TOP >> LEVEL3_PDE_SHIFT;
for (uintptr_t level4_entry_idx = 0; level4_entry_idx < end_idx; level4_entry_idx++) {
// free each level4 page table
uintptr_t* pgtbl_paddr = (uintptr_t*)LEVEL4_PTE_ADDR(pgdir->pd_addr[level4_entry_idx]);
if (pgtbl_paddr != NULL) {
// free each page
for (uintptr_t page_entry_idx = 0; page_entry_idx < NUM_LEVEL4_PTE; page_entry_idx++) {
uintptr_t vaddr = (level4_entry_idx << LEVEL3_PDE_SHIFT) | (page_entry_idx << LEVEL4_PTE_SHIFT);
// get page paddr
uintptr_t* page_paddr = (uintptr_t*)ALIGNDOWN(((uintptr_t*)P2V(pgtbl_paddr))[page_entry_idx], PAGE_SIZE);
if (page_paddr != NULL) {
// IPC vaddr should not be addressed here.
assert(vaddr < USER_IPC_SPACE_BASE || vaddr >= USER_IPC_SPACE_TOP);
if (LIKELY((uintptr_t)page_paddr >= low_bound && (uintptr_t)page_paddr < high_bound)) {
kfree(P2V(page_paddr));
} else if (LIKELY((uintptr_t)page_paddr >= user_low_bound && (uintptr_t)page_paddr < user_high_bound)) {
raw_free((char*)page_paddr);
}
}
}
kfree(P2V(pgtbl_paddr));
}
}
kfree((char*)pgdir->pd_addr);
}
@@ -95,6 +95,7 @@ static uintptr_t map_task_share_page(struct TaskMicroDescriptor* task, const uin
uintptr_t vaddr = (uintptr_t)NULL;
if (task->massive_ipc_allocator != NULL) {
vaddr = (uintptr_t)KBuddyAlloc(task->massive_ipc_allocator, PAGE_SIZE * nr_pages * 2);
assert(xizi_pager.address_translate(&task->pgdir, vaddr) == (uintptr_t)NULL);
} else {
vaddr = alloc_share_page_addr(task, nr_pages * 2);
if (vaddr >= USER_IPC_USE_ALLOCATOR_WATERMARK) {
@@ -122,9 +123,7 @@ static uintptr_t map_task_share_page(struct TaskMicroDescriptor* task, const uin
p_mmu_driver->TlbFlush(vaddr, 2 * nr_pages * PAGE_SIZE);
/// @todo clean range rather than all
// p_dcache_done->flushall();
p_dcache_done->invalidateall();
// p_dcache_done->flush(vaddr, vaddr + 2 * nr_pages * PAGE_SIZE);
}
return vaddr;
}
@@ -148,9 +147,7 @@ uintptr_t task_map_pages(struct TaskMicroDescriptor* task, const uintptr_t vaddr
p_mmu_driver->TlbFlush(vaddr, nr_pages * PAGE_SIZE);
/// @todo clean range rather than all
// p_dcache_done->flushall();
p_dcache_done->invalidateall();
// p_dcache_done->flush(vaddr, vaddr + nr_pages * PAGE_SIZE);
}
return vaddr;
@@ -171,9 +168,7 @@ void unmap_task_share_pages(struct TaskMicroDescriptor* task, const uintptr_t ta
p_mmu_driver->TlbFlush(task_vaddr, 2 * nr_pages * PAGE_SIZE);
/// @todo clean range rather than all
// p_dcache_done->flushall();
p_dcache_done->invalidateall();
// p_dcache_done->flush(task_vaddr, task_vaddr + 2 * nr_pages * PAGE_SIZE);
}
}
@@ -246,21 +241,31 @@ int delete_share_pages(struct session_backend* session_backend)
return -1;
}
assert(session_backend->server_side.closed || session_backend->client_side.closed);
/* unmap share pages */
if (session_backend->client) {
doubleListDel(&session_backend->client_side.node);
}
if (session_backend->server) {
// close ssesion in server's perspective
if (session_backend->server_side.closed && session_backend->server != NULL) {
xizi_share_page_manager.unmap_task_share_pages(session_backend->server, session_backend->server_side.buf_addr, session_backend->nr_pages);
doubleListDel(&session_backend->server_side.node);
session_backend->server->mem_size -= session_backend->nr_pages * PAGE_SIZE;
session_backend->server = NULL;
}
session_backend->server->mem_size -= session_backend->nr_pages * PAGE_SIZE;
session_backend->client->mem_size -= session_backend->nr_pages * PAGE_SIZE;
// close ssesion in client's perspective
if (session_backend->client_side.closed && session_backend->client != NULL) {
xizi_share_page_manager.unmap_task_share_pages(session_backend->client, session_backend->client_side.buf_addr, session_backend->nr_pages);
doubleListDel(&session_backend->client_side.node);
session_backend->client->mem_size -= session_backend->nr_pages * PAGE_SIZE;
session_backend->client = NULL;
}
/* free seesion backend */
kfree((void*)session_backend->buf_kernel_addr);
slab_free(SessionAllocator(), (void*)session_backend);
if (session_backend->server_side.closed && session_backend->client_side.closed) {
assert(session_backend->client == NULL && session_backend->server == NULL);
kfree((void*)session_backend->buf_kernel_addr);
slab_free(SessionAllocator(), (void*)session_backend);
}
return 0;
}