summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/memory/paging.c9
-rw-r--r--kernel/memory/virtalloc.c80
-rw-r--r--kernel/memory/virtalloc.h8
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