diff options
author | Galen Sagarin <gps5307@rit.edu> | 2025-04-29 14:18:40 -0400 |
---|---|---|
committer | Galen Sagarin <gps5307@rit.edu> | 2025-04-29 14:18:40 -0400 |
commit | ae2cdd83ba4a0cae161db0b29031d5591005fa34 (patch) | |
tree | 82fbdfcbb1fe4e3b5e232db195c8c331d69489fd /kernel/memory/virtalloc.c | |
parent | Started writing fat.c (diff) | |
parent | fs header changes (diff) | |
download | comus-ae2cdd83ba4a0cae161db0b29031d5591005fa34.tar.gz comus-ae2cdd83ba4a0cae161db0b29031d5591005fa34.tar.bz2 comus-ae2cdd83ba4a0cae161db0b29031d5591005fa34.zip |
Merge branch 'main' of https://github.com/kenshineto/kern into fat32
Merging main into here
Diffstat (limited to 'kernel/memory/virtalloc.c')
-rw-r--r-- | kernel/memory/virtalloc.c | 122 |
1 files changed, 99 insertions, 23 deletions
diff --git a/kernel/memory/virtalloc.c b/kernel/memory/virtalloc.c index 0f4de93..0cbba33 100644 --- a/kernel/memory/virtalloc.c +++ b/kernel/memory/virtalloc.c @@ -1,5 +1,7 @@ +#include "lib/kio.h" #include <lib.h> #include <comus/memory.h> +#include <stdint.h> #include "virtalloc.h" @@ -79,7 +81,7 @@ static void free_node(struct virt_ctx *ctx, struct virt_addr_node *node) void virtaddr_init(struct virt_ctx *ctx) { struct virt_addr_node init = { - .start = 0x40005000, // map after paging pt + .start = 0x50000000, .end = 0x1000000000000, // 48bit memory address max .next = NULL, .prev = NULL, @@ -96,6 +98,44 @@ void virtaddr_init(struct virt_ctx *ctx) ctx->is_allocating = false; } +int virtaddr_clone(struct virt_ctx *old, struct virt_ctx *new) +{ + // copy over data + memcpy(new, old, sizeof(struct virt_ctx)); + + // allocate new space + new->alloc_nodes = + kalloc(sizeof(struct virt_addr_node) * new->alloc_node_count); + if (new->alloc_nodes == NULL) + return 1; + + // update prev/next in new allocation space + update_node_ptrs(old->alloc_nodes, new->alloc_nodes, old->alloc_node_count, + new->alloc_node_count); + + // update bootstrap nodes + for (size_t i = 0; i < new->used_node_count; i++) { + struct virt_addr_node *prev, *next; + + if (i >= BOOTSTRAP_VIRT_ALLOC_NODES) + break; + + // get prev + prev = i > 0 ? &new->bootstrap_nodes[i - 1] : NULL; + next = i < BOOTSTRAP_VIRT_ALLOC_NODES - 1 ? + &new->bootstrap_nodes[i + 1] : + NULL; + + new->bootstrap_nodes[i].prev = prev; + new->bootstrap_nodes[i].next = next; + } + + // get starting node + new->start_node = &new->bootstrap_nodes[0]; // for now + + return 0; +} + static void merge_back(struct virt_ctx *ctx, struct virt_addr_node *node) { while (node->prev) { @@ -139,33 +179,69 @@ void *virtaddr_alloc(struct virt_ctx *ctx, int n_pages) if (node->is_alloc) continue; - if (length >= n_length) { - struct virt_addr_node *new = get_node(ctx); - if (node->prev != NULL) { - node->prev->next = new; - } else { - ctx->start_node = new; - } - new->next = node; - new->prev = node->prev; - node->prev = new; - new->start = node->start; - new->end = new->start + n_length; - node->start = new->end; - new->is_alloc = true; - new->is_used = true; - new->next = node; - void *mem = (void *)new->start; - merge_back(ctx, new); - merge_forward(ctx, new); - return mem; - } + if (length < n_length) + continue; + + return (void *)node->start; } return NULL; } -long virtaddr_free(struct virt_ctx *ctx, void *virtaddr) +int virtaddr_take(struct virt_ctx *ctx, const void *virt, int n_pages) +{ + if (n_pages < 1) + return 0; + + long n_length = n_pages * PAGE_SIZE; + struct virt_addr_node *node = ctx->start_node; + + for (; node != NULL; node = node->next) { + if (node->is_alloc) + continue; + + if (node->start > (uintptr_t)virt || + node->end < (uintptr_t)virt + n_length) + continue; + + // create new node on left + if (node->start < (uintptr_t)virt) { + struct virt_addr_node *left = get_node(ctx); + left->next = node; + left->prev = node->prev; + left->start = node->start; + left->end = (uintptr_t)virt; + left->is_used = true; + left->is_alloc = false; + node->prev->next = left; + node->prev = left; + } + + // create new node on right + if (node->end > (uintptr_t)virt + n_length) { + struct virt_addr_node *right = get_node(ctx); + right->prev = node; + right->next = node->next; + right->start = (uintptr_t)virt + n_length; + right->end = node->end; + right->is_used = true; + right->is_alloc = false; + node->next->prev = right; + node->next = right; + } + + node->start = (uintptr_t)virt; + node->end = node->start + n_length; + node->is_alloc = true; + node->is_used = true; + + return 0; + } + + return 1; +} + +long virtaddr_free(struct virt_ctx *ctx, const void *virtaddr) { if (virtaddr == NULL) return -1; |