diff options
Diffstat (limited to '')
-rw-r--r-- | kernel/memory/paging.c | 9 | ||||
-rw-r--r-- | kernel/memory/virtalloc.c | 80 | ||||
-rw-r--r-- | kernel/memory/virtalloc.h | 8 |
3 files changed, 76 insertions, 21 deletions
diff --git a/kernel/memory/paging.c b/kernel/memory/paging.c index 2cc5b7e..ec3c5c7 100644 --- a/kernel/memory/paging.c +++ b/kernel/memory/paging.c @@ -736,6 +736,9 @@ void *mem_mapaddr(mem_ctx_t ctx, void *phys, void *virt, size_t len, if (virt == NULL) return NULL; + if (virtaddr_take(&ctx->virtctx, virt, pages)) + return NULL; + assert((uint64_t)virt % PAGE_SIZE == 0, "mem_mapaddr: vitural address not page aligned"); @@ -761,6 +764,9 @@ void *kmapuseraddr(mem_ctx_t ctx, const void *usrADDR, size_t len) if (vADDR == NULL) return NULL; + if (virtaddr_take(&kernel_mem_ctx->virtctx, vADDR, npages)) + return NULL; + assert((size_t)vADDR % PAGE_SIZE == 0, "kmapuseraddr: vitural address not page aligned"); @@ -847,6 +853,9 @@ void *mem_alloc_pages_at(mem_ctx_t ctx, size_t count, void *virt, struct phys_page_slice prev_phys_block = PHYS_PAGE_SLICE_NULL; struct phys_page_slice phys_pages; + if (virtaddr_take(&ctx->virtctx, virt, count)) + return NULL; + while (pages_needed > 0) { phys_pages = alloc_phys_page_withextra(pages_needed); if (phys_pages.pagestart == NULL) { diff --git a/kernel/memory/virtalloc.c b/kernel/memory/virtalloc.c index cbde9b4..863959e 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" @@ -177,32 +179,68 @@ 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; } +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) diff --git a/kernel/memory/virtalloc.h b/kernel/memory/virtalloc.h index 9a94208..5033242 100644 --- a/kernel/memory/virtalloc.h +++ b/kernel/memory/virtalloc.h @@ -65,6 +65,14 @@ int virtaddr_clone(struct virt_ctx *old, struct virt_ctx *new); void *virtaddr_alloc(struct virt_ctx *ctx, int pages); /** + * Take (yoink) a predefined virtual address of length x pages + * @param virt - the start of the vitural address to take + * @param pages - x pages + * @returns 0 on success, 1 on err + */ +int virtaddr_take(struct virt_ctx *ctx, const void *virt, int pages); + +/** * Free the virtual address from virtaddr_alloc * @param virtaddr - the addr to free * @returns number of pages used for virtaddr |