summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/inc/vm/phys.h15
-rw-r--r--sys/vm/vm_phys.c66
2 files changed, 81 insertions, 0 deletions
diff --git a/sys/inc/vm/phys.h b/sys/inc/vm/phys.h
index 805759a..93bbf39 100644
--- a/sys/inc/vm/phys.h
+++ b/sys/inc/vm/phys.h
@@ -32,6 +32,21 @@
#include <sys/types.h>
+/*
+ * Initialize the physical memory manager
+ */
void vm_phys_init(void);
+/*
+ * Allocate a number of contigious physical memory
+ * frames
+ */
+uintptr_t vm_phys_alloc(size_t count);
+
+/*
+ * Free a contigious region of physical memory
+ * frames
+ */
+void vm_phys_free(uintptr_t base, size_t count);
+
#endif /* !_VM_PHYS_H_ */
diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c
index ecbc857..717b1f4 100644
--- a/sys/vm/vm_phys.c
+++ b/sys/vm/vm_phys.c
@@ -31,6 +31,7 @@
#include <sys/cdefs.h>
#include <sys/param.h>
#include <kern/panic.h>
+#include <mu/spinlock.h>
#include <os/trace.h>
#include <vm/phys.h>
#include <vm/vm.h>
@@ -59,7 +60,9 @@
typedef struct limine_memmap_entry mementry_t;
/* Bitmap */
+static volatile size_t bitmap_lock = 0;
static uint8_t *bitmap = NULL;
+static size_t last_index = 0;
/* Memory statistics */
static size_t total_mem = 0;
@@ -210,6 +213,69 @@ vm_probe(void)
vm_alloc_bitmap();
}
+/*
+ * Lockless frame allocation routine
+ */
+static uintptr_t
+__vm_phys_alloc(size_t count)
+{
+ size_t frames_found = 0;
+ size_t max_index;
+ ssize_t index_start = -1;
+ uintptr_t start, end;
+
+ max_index = highest_usable / PAGESIZE;
+ for (size_t i = last_index; i < max_index; ++i) {
+ if (!testbit(bitmap, i)) {
+ if (index_start < 0)
+ index_start = i;
+ if ((++frames_found) >= count)
+ break;
+
+ continue;
+ }
+
+ index_start = -1;
+ }
+
+ if (index_start < 0) {
+ return 0;
+ }
+
+ start = index_start * PAGESIZE;
+ end = start + (count * PAGESIZE);
+ bitmap_set_range(start, end, true);
+ return start;
+}
+
+void
+vm_phys_free(uintptr_t base, size_t count)
+{
+ uintptr_t end;
+
+ base = ALIGN_DOWN(base, PAGESIZE);
+ end = base + (count * PAGESIZE);
+
+ mu_spinlock_acq(&bitmap_lock, 0);
+ bitmap_set_range(base, end, false);
+ mu_spinlock_rel(&bitmap_lock, 0);
+}
+
+uintptr_t
+vm_phys_alloc(size_t count)
+{
+ uintptr_t base;
+
+ mu_spinlock_acq(&bitmap_lock, 0);
+ base = __vm_phys_alloc(count);
+ if (base == 0) {
+ last_index = 0;
+ base = __vm_phys_alloc(count);
+ }
+ mu_spinlock_rel(&bitmap_lock, 0);
+ return base;
+}
+
void
vm_phys_init(void)
{