summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2024-03-15 13:16:02 -0400
committerJon Santmyer <jon@jonsantmyer.com>2024-03-15 13:16:02 -0400
commitdd5d9e1d48396cbc226ff14fe557a55613c91fcb (patch)
treeb0ec9f54b80f26777ac08b723b42c1c64c5a2bda
parentf46ab8ca2050ee77edf6e6b979875426bdaf29dc (diff)
downloadjove-kernel-dd5d9e1d48396cbc226ff14fe557a55613c91fcb.tar.gz
jove-kernel-dd5d9e1d48396cbc226ff14fe557a55613c91fcb.tar.bz2
jove-kernel-dd5d9e1d48396cbc226ff14fe557a55613c91fcb.zip
better buddy memory allocator
-rw-r--r--abi/syscall.h20
-rw-r--r--arch/x86_64/paging.c6
-rw-r--r--boot/boot.h2
-rw-r--r--lib/buddymap.c168
-rw-r--r--lib/buddymap.h35
-rw-r--r--lib/jove.h2
-rw-r--r--main.c8
-rw-r--r--mem/buddymap.c151
-rw-r--r--mem/buddymap.h21
-rw-r--r--mem/memory.c10
-rw-r--r--mem/memory.h12
-rw-r--r--mem/phys.c13
-rw-r--r--mem/zone.c97
-rw-r--r--mem/zone.h52
-rw-r--r--usr/syscall.c1
15 files changed, 386 insertions, 212 deletions
diff --git a/abi/syscall.h b/abi/syscall.h
index 54a67b9..e336fe6 100644
--- a/abi/syscall.h
+++ b/abi/syscall.h
@@ -12,23 +12,18 @@ struct syscall_log {
const char *message;
};
-struct syscall_tid {
+struct syscall_mem_takefree {
syscall_t syscall;
- intmax_t value;
-};
-
-struct syscall_mem_map {
- syscall_t syscall;
- uintptr_t phys;
- uintptr_t virt;
- intmax_t tid;
+ uintptr_t npages;
};
enum
{
SYSCALL_LOG = 0,
SYSCALL_TID,
- SYSCALL_MEM_MAP,
+
+ SYSCALL_MEM_TAKEFREE,
+
SYSCALL_COUNT
};
@@ -50,9 +45,4 @@ intmax_t _syscall_tid(void) {
_SYSCALL(&syscall_data);
}
-void __syscall_mem_map(uintptr_t phys, uintptr_t virt, intmax_t tid)
-{
-
-}
-
#endif
diff --git a/arch/x86_64/paging.c b/arch/x86_64/paging.c
index 29c4863..9e8a5ed 100644
--- a/arch/x86_64/paging.c
+++ b/arch/x86_64/paging.c
@@ -43,7 +43,7 @@ s_paging_fetch_table(union PageEntry *pt, size_t l, uintptr_t virt)
bool entry_new = false;
if(!entry.p) {
entry_new = true;
- entry.value = mem_phys_take4k();
+ entry.value = mem_phys_alloc(1);
entry.p = 1;
entry.rw = 1;
entry.us = 1;
@@ -116,7 +116,7 @@ mem_pd_ensure_4k(struct PageDirectory *pd, uintptr_t virt, uint8_t flg)
{
union PageEntry pml1e = mem_paging_fetch4k(pd, virt);
if(!pml1e.p) {
- uintptr_t phys = mem_phys_take4k();
+ uintptr_t phys = mem_phys_alloc(1);
mem_paging_map4k(pd, phys, virt, flg);
}
}
@@ -143,7 +143,7 @@ mem_ensure_range(uintptr_t from, uintptr_t to, bool rw, bool user)
void mem_pd_new(struct PageDirectory *pd)
{
- physptr_t pml4p = mem_phys_take4k();
+ physptr_t pml4p = mem_phys_alloc(1);
union PageEntry *pml4 = (union PageEntry*)mem_phys_tolinear(pml4p);
memset(pml4, 0, PAGESIZE);
memcpy(&pml4[256], &pd->pml4_vaddr[256], PAGESIZE / 2);
diff --git a/boot/boot.h b/boot/boot.h
index d7571d8..cfdfa68 100644
--- a/boot/boot.h
+++ b/boot/boot.h
@@ -11,7 +11,7 @@ struct MemoryMapEntry {
bool usable;
};
-#define MEMORY_MAP_MAX_ENTRIES 64
+#define MEMORY_MAP_MAX_ENTRIES 128
struct MemoryMap {
size_t count;
struct MemoryMapEntry entries[MEMORY_MAP_MAX_ENTRIES];
diff --git a/lib/buddymap.c b/lib/buddymap.c
new file mode 100644
index 0000000..6a616c9
--- /dev/null
+++ b/lib/buddymap.c
@@ -0,0 +1,168 @@
+#include "buddymap.h"
+#include "jove.h"
+
+#define BLOCK_AT_LAYER(blocks, l, i) blocks[l][i / BUDDY_BLOCK_BITS]
+#define BLOCK_BITMASK(i) (1ULL << (i % BUDDY_BLOCK_BITS))
+
+bool
+buddy_bit_test(struct BuddyMap *map, size_t l, size_t i)
+{
+ return (BLOCK_AT_LAYER(map->blocks, l, i) & BLOCK_BITMASK(i)) > 0;
+}
+
+void
+buddy_bit_mark(struct BuddyMap *map, size_t l, size_t i)
+{
+ size_t wi = i << l;
+ size_t bits = 1ULL << l;
+ for(size_t wl = 0; wl < map->orders; wl++) {
+ if(bits == 0) {
+ if(buddy_bit_test(map, wl - 1, (wi << 1) + 1)) bits = 1;
+ }
+ for(size_t bit = 0; bit < bits; bit++) {
+ size_t rbit = bit + wi;
+ if(l == 0 && !buddy_bit_test(map, 0, rbit)) map->free--;
+ BLOCK_AT_LAYER(map->blocks, wl, rbit) |= BLOCK_BITMASK(rbit);
+ }
+ bits >>= 1;
+ wi >>= 1;
+ }
+}
+
+void
+buddy_bit_free(struct BuddyMap *map, size_t l, size_t i)
+{
+ size_t wi = i << l;
+ size_t bits = 1ULL << l;
+ for(size_t wl = 0; wl < map->orders; wl++) {
+ if(bits == 0) bits = 1;
+ for(size_t bit = 0; bit < bits; bit++) {
+ size_t rbit = bit + wi;
+ if(l == 0 && buddy_bit_test(map, 0, rbit)) map->free++;
+ BLOCK_AT_LAYER(map->blocks, wl, rbit) &= ~BLOCK_BITMASK(rbit);
+ }
+ bits >>= 1;
+ wi >>= 1;
+ }
+}
+
+static void
+s_buddy_op_range(
+ struct BuddyMap *map,
+ size_t l,
+ size_t start,
+ size_t end,
+ void (*op)(struct BuddyMap*, size_t, size_t))
+{
+ size_t layerw = 1ULL << l;
+ size_t start_off = start % layerw;
+ size_t end_off = end % layerw;
+
+ size_t start_real = start + (start_off > 0 ? (layerw - start_off) : 0);
+ size_t end_real = end - end_off;
+
+ if(start_real != start) s_buddy_op_range(map, l - 1, start, start_real, op);
+ if(end_real != end) s_buddy_op_range(map, l - 1, end_real, end, op);
+
+ size_t start_bit = start_real >> l;
+ size_t end_bit = end_real >> l;
+ if(start_bit == end_bit || end_bit < start_bit) return;
+ for(size_t bit = start_bit; bit < end_bit; bit++)
+ op(map, l, bit);
+}
+
+static size_t
+s_buddy_layer_bestfit(struct BuddyMap *map, size_t length)
+{
+ if(length == 1) return 0;
+ size_t length_log2 = LOG2(length);
+ if(length_log2 > map->orders) length_log2 = map->orders - 1;
+ return length_log2;
+}
+
+void
+buddy_mark_range(struct BuddyMap *map, size_t start, size_t end)
+{
+ size_t l = s_buddy_layer_bestfit(map, end - start);
+ s_buddy_op_range(map, l, start, end, buddy_bit_mark);
+}
+void
+buddy_free_range(struct BuddyMap *map, size_t start, size_t end)
+{
+ size_t l = s_buddy_layer_bestfit(map, end - start);
+ s_buddy_op_range(map, l, start, end, buddy_bit_free);
+}
+
+static intmax_t
+s_buddy_top_firstfree(struct BuddyMap *map)
+{
+ size_t layer = map->orders - 1;
+ size_t layer_bits = map->bits >> layer;
+ size_t layer_blocks = layer_bits / BUDDY_BLOCK_BITS;
+ for(size_t i = 0; i < layer_blocks; i++) {
+ if(map->blocks[layer][i] == (uintptr_t)-1) continue;
+ for(size_t j = 0; j < BUDDY_BLOCK_BITS; j++) {
+ size_t bit = (i * BUDDY_BLOCK_BITS) + j;
+ if(buddy_bit_test(map, layer, bit)) continue;
+ return bit;
+ }
+ }
+ return -1;
+}
+
+static intmax_t
+s_buddy_top_alloc_contig(struct BuddyMap *map, size_t length)
+{
+ size_t layer = map->orders - 1;
+ size_t layer_bits = map->bits >> layer;
+
+ size_t contig_base = 0;
+ size_t contig_bits = 0;
+ for(size_t i = 0; i < layer_bits; i++) {
+ if(buddy_bit_test(map, layer, i)) {
+ contig_base = i + 1;
+ contig_bits = 0;
+ continue;
+ }
+ if(++contig_bits == length) {
+ return contig_base;
+ }
+ }
+ return -1;
+}
+
+intmax_t
+buddy_alloc(struct BuddyMap *map, size_t length)
+{
+ size_t layer = s_buddy_layer_bestfit(map, length);
+ size_t layerw = 1ULL << layer;
+ size_t allocw = length / layerw;
+
+ if(allocw == 0) allocw = 1;
+ if(allocw > 1)
+ return s_buddy_top_alloc_contig(map, length);
+
+ intmax_t alloci = s_buddy_top_firstfree(map);
+ if(alloci < 0) {
+ klogf("Top layer is full!\n");
+ return -1;
+ }
+
+ for(int wlayer = map->orders - 2; wlayer > layer; wlayer--) {
+ alloci <<= 1;
+ if(buddy_bit_test(map, wlayer, alloci)) {
+ alloci++;
+ }
+ }
+ alloci <<= 1;
+ if(buddy_bit_test(map, layer, alloci)) alloci++;
+
+ s_buddy_op_range(map, layer, alloci, alloci + length, buddy_bit_mark);
+ return alloci;
+}
+
+void
+buddy_free(struct BuddyMap *map, size_t i, size_t length)
+{
+ buddy_free_range(map, i, i + length);
+}
diff --git a/lib/buddymap.h b/lib/buddymap.h
new file mode 100644
index 0000000..1af8dfb
--- /dev/null
+++ b/lib/buddymap.h
@@ -0,0 +1,35 @@
+#ifndef JOVE_LIB_BUDDYMAP_H
+#define JOVE_LIB_BUDDYMAP_H 1
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#define BUDDY_BLOCK_BYTES sizeof(intmax_t)
+#define BUDDY_BLOCK_BITS (BUDDY_BLOCK_BYTES * 8)
+
+#define BUDDY_BITS_FOR(range) (range * 2)
+#define BUDDY_BLOCKS_FOR(range) (BUDDY_BITS_FOR(range) / BUDDY_BLOCK_BITS)
+
+struct BuddyMap
+{
+ size_t orders;
+ size_t bits;
+ size_t free;
+ uintmax_t **blocks;
+};
+
+#define BUDDY_BIT_PARTIAL 0
+#define BUDDY_BIT_FULL 1
+
+bool buddy_bit_test(struct BuddyMap *map, size_t l, size_t i);
+void buddy_bit_mark(struct BuddyMap *map, size_t l, size_t i);
+void buddy_bit_free(struct BuddyMap *map, size_t l, size_t i);
+
+void buddy_mark_range(struct BuddyMap *map, size_t start, size_t end);
+void buddy_free_range(struct BuddyMap *map, size_t start, size_t end);
+
+intmax_t buddy_alloc(struct BuddyMap *map, size_t length);
+void buddy_free(struct BuddyMap *map, size_t i, size_t length);
+
+#endif
diff --git a/lib/jove.h b/lib/jove.h
index 4aa60ed..6015112 100644
--- a/lib/jove.h
+++ b/lib/jove.h
@@ -4,7 +4,7 @@
#define ALWAYS_INLINE inline __attribute__((always_inline))
#define PAGEALIGN __attribute__((aligned(0x1000)))
-//#define LOG2(n) (__builtin_clz(n) ^ 31)
+#define LOG2(n) (31 - __builtin_clz(n))
extern void *_kernel_start;
extern void *_kernel_end;
diff --git a/main.c b/main.c
index e74d8df..9341489 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,7 @@
#include "arch/arch.h"
#include "io/log.h"
-#include "mem/buddymap.h"
#include "mem/memory.h"
+#include "mem/zone.h"
#include "boot/cmdline.h"
#include "tsk/tasking.h"
#include "ird/initrd.h"
@@ -12,11 +12,9 @@ void
kernel_main(void)
{
serial_setup();
- arch_tables_setup();
+ //arch_tables_setup();
- mem_buddy_setup();
- mem_paging_setup();
- mem_slab_setup();
+ mem_setup();
cmdline_kernel_setup();
diff --git a/mem/buddymap.c b/mem/buddymap.c
deleted file mode 100644
index 5165876..0000000
--- a/mem/buddymap.c
+++ /dev/null
@@ -1,151 +0,0 @@
-#include "buddymap.h"
-#include "lib/string.h"
-#include "boot/boot.h"
-#include "io/log.h"
-#include <stdbool.h>
-
-#define ENTRY_BITS (sizeof(uintmax_t) * 8)
-#define ENTRY_SIZE (ENTRY_BITS * PAGESIZE)
-#define ENTRY_COUNT (MEMMAP_BUDDY_LIMIT / ENTRY_SIZE)
-#define BUDDY_LAYERS 4
-
-uintmax_t s_buddy_l0[ENTRY_COUNT];
-uintmax_t s_buddy_l1[ENTRY_COUNT << 1];
-uintmax_t s_buddy_l2[ENTRY_COUNT << 2];
-uintmax_t s_buddy_l3[ENTRY_COUNT << 3];
-uintmax_t *s_buddies[BUDDY_LAYERS] = {
- s_buddy_l0,
- s_buddy_l1,
- s_buddy_l2,
- s_buddy_l3
-};
-size_t s_buddies_lastfree[BUDDY_LAYERS] = { 1, 1, 1, 1 };
-
-static bool
-s_buddy_test(size_t l, size_t i)
-{
- return (s_buddies[l][i / (ENTRY_BITS)] & (1ULL << (i % (ENTRY_BITS)))) > 0;
-}
-
-static void
-s_buddy_set(size_t l, size_t i)
-{
- size_t j = i << l;
- size_t w = 1 << l;
- for(int layer = 0; layer < BUDDY_LAYERS; layer++)
- {
- if(w == 0) w = 1;
- for(size_t bit = 0; bit < w; bit++) {
- size_t entry = (j + bit) / ENTRY_BITS;
- s_buddies[layer][entry] |= (1ULL << (j + bit % ENTRY_BITS));
- }
- j >>= 1;
- w >>= 1;
- }
-}
-
-static void
-s_buddy_unset(size_t l, size_t i)
-{
- size_t j = i << l;
- size_t w = 1 << l;
- bool free_upper = false;
- for(int layer = 0; layer < BUDDY_LAYERS; layer++)
- {
- if(w == 0) {
- size_t lower = (j << 1) % ENTRY_BITS;
- size_t other = (lower + 1);
- size_t entry = (j << 1) / ENTRY_BITS;
- if((s_buddies[layer-1][entry] & (1ULL << lower)) > 0 &&
- (s_buddies[layer-1][entry] & (1ULL << other)) > 0)
- s_buddies[layer][entry >> 1] &= ~(1ULL << (j % ENTRY_BITS));
- }
-
- for(size_t bit = 0; bit < w; bit++) {
- size_t entry = j / ENTRY_BITS;
- s_buddies[layer][entry] |= (1ULL << bit);
- }
- j >>= 1;
- w >>= 1;
- }
-}
-
-void
-mem_buddy_set_range(uintptr_t base, size_t length)
-{
- for(int l = 0; l < BUDDY_LAYERS; l++) {
- size_t bits = (length / PAGESIZE) >> l;
- size_t biti = (base / PAGESIZE) >> l;
-
- if(bits == 0) bits = 1;
- for(size_t i = 0; i < bits; i++) {
- size_t entry = (biti + i) / ENTRY_BITS;
- s_buddies[l][entry] |= 1ULL << ((biti + i) % ENTRY_BITS);
- }
- }
-}
-
-void
-mem_buddy_free_range(uintptr_t base, size_t length)
-{
- for(int l = 0; l < BUDDY_LAYERS; l++) {
- size_t bits = (length / PAGESIZE) >> l;
- size_t biti = (base / PAGESIZE) >> l;
- size_t bitbase = (biti * PAGESIZE) << l;
-
- if(bits == 0) continue;
- for(size_t i = 0; i < bits; i++, bitbase += (PAGESIZE << l)) {
- if(bitbase < base) continue;
- size_t entry = (biti + i) / ENTRY_BITS;
- s_buddies[l][entry] &= ~(1ULL << ((biti+ i) % ENTRY_BITS));
- }
- }
-}
-
-
-uintptr_t
-mem_buddy_takefree(size_t l)
-{
- uintmax_t *layer = s_buddies[l];
- size_t lastfree = s_buddies_lastfree[l];
- if(s_buddy_test(l, lastfree)) lastfree = 0;
- size_t entries = ENTRY_COUNT >> l;
- for(size_t i = lastfree / ENTRY_BITS; i < entries; i++) {
- uintmax_t entry = layer[i];
- if(entry == (uintmax_t)-1LL) continue;
- for(size_t j = 0; j < ENTRY_BITS; j++) {
- if((entry & (1ULL << j)) == 0) {
- size_t bit = (i * ENTRY_BITS) + j;
- s_buddies_lastfree[l] = bit + 1;
- s_buddy_set(l, bit);
- return bit * (PAGESIZE << l);
- }
- }
- }
- return 0;
-}
-
-void
-mem_buddy_setup()
-{
- memset(s_buddy_l0, 0xFF, sizeof(s_buddy_l0));
- memset(s_buddy_l1, 0xFF, sizeof(s_buddy_l1));
- memset(s_buddy_l2, 0xFF, sizeof(s_buddy_l2));
- memset(s_buddy_l3, 0xFF, sizeof(s_buddy_l3));
-
- for(int i = 0; i < boot_memorymap.count; i++) {
- struct MemoryMapEntry *entry = &boot_memorymap.entries[i];
- klogf("%2i\t%#016X -> %#016X (%i)\n",
- i, entry->base, entry->base + entry->length, entry->usable);
- if(entry->base > MEMMAP_BUDDY_LIMIT) continue;
- size_t length = entry->length;
- if(entry->base + length > MEMMAP_BUDDY_LIMIT) length = MEMMAP_BUDDY_LIMIT - (entry->base + length);
- if(entry->usable)
- mem_buddy_free_range(entry->base, entry->length);
- }
-
- s_buddies[0][0] |= 1;
- s_buddies[1][0] |= 1;
- s_buddies[2][0] |= 1;
- s_buddies[3][0] |= 1;
-}
diff --git a/mem/buddymap.h b/mem/buddymap.h
deleted file mode 100644
index 2f4f5dc..0000000
--- a/mem/buddymap.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef JOVE_MEMORY_BUDDYMAP_H
-#define JOVE_MEMORY_BUDDYMAP_H 1
-
-#include "memory.h"
-#include <stdint.h>
-#include <stddef.h>
-
-#define MEMMAP_BUDDY_LIMIT (4 * GiB)
-
-void mem_buddy_set_range(uintptr_t base, size_t length);
-void mem_buddy_free_range(uintptr_t base, size_t length);
-uintptr_t mem_buddy_takefree(size_t layer);
-
-#define mem_buddy_takefree_4k() mem_buddy_takefree(0)
-#define mem_buddy_takefree_8k() mem_buddy_takefree(1)
-#define mem_buddy_takefree_16k() mem_buddy_takefree(2)
-#define mem_buddy_takefree_32k() mem_buddy_takefree(3)
-
-void mem_buddy_setup(void);
-
-#endif
diff --git a/mem/memory.c b/mem/memory.c
new file mode 100644
index 0000000..26bbbd8
--- /dev/null
+++ b/mem/memory.c
@@ -0,0 +1,10 @@
+#include "memory.h"
+#include "zone.h"
+
+void
+mem_setup(void)
+{
+ mem_zone_setup_standard();
+ mem_paging_setup();
+ mem_slab_setup();
+}
diff --git a/mem/memory.h b/mem/memory.h
index 3956852..41323ed 100644
--- a/mem/memory.h
+++ b/mem/memory.h
@@ -32,12 +32,12 @@ bool mem_check_ptr(const void *ptr);
* @param user flag to mark page as user accessable*/
void mem_ensure_range(uintptr_t from, uintptr_t to, bool rw, bool user);
-/**Make sure the range indicated is available in memory for specified pd
+/** Make sure the range indicated is available in memory for specified pd
* If necessary, allocate new pages using the passed flags
* @param pd pointer to page directory to edit
- * @param from start of the range.
- * @param to end of the range.
- * @param rw flag to mark page is writeable.
+ * @param from start of the range
+ * @param to end of the range
+ * @param rw flag to mark page is writeable
* @param user flag to mark page as user accessable*/
void mem_ensure_range_for(void *pd, uintptr_t from, uintptr_t to, bool rw, bool user);
@@ -52,7 +52,9 @@ void mem_free(void *ptr);
/*Physical*/
-physptr_t mem_phys_take4k(void);
+physptr_t mem_phys_alloc(size_t pages);
void mem_phys_reserve(physptr_t start, size_t len);
+void mem_setup(void);
+
#endif
diff --git a/mem/phys.c b/mem/phys.c
index e56a4d6..00f3531 100644
--- a/mem/phys.c
+++ b/mem/phys.c
@@ -1,14 +1,9 @@
#include "memory.h"
-#include "buddymap.h"
+#include "zone.h"
physptr_t
-mem_phys_take4k(void)
+mem_phys_alloc(size_t pages)
{
- return mem_buddy_takefree_4k();
-}
-
-void
-mem_phys_reserve(physptr_t start, size_t len)
-{
- mem_buddy_set_range(start, len);
+ physptr_t ptr = mem_zone_alloc(MEM_ZONE_STANDARD, pages);
+ return ptr;
}
diff --git a/mem/zone.c b/mem/zone.c
new file mode 100644
index 0000000..489383a
--- /dev/null
+++ b/mem/zone.c
@@ -0,0 +1,97 @@
+#include "zone.h"
+#include "memory.h"
+#include "boot/boot.h"
+#include "lib/string.h"
+#include "io/log.h"
+
+#define MEM_ZONE_STANDARD_PAGES (MEM_ZONE_STANDARD_LIMIT >> 12)
+
+static uintmax_t
+ s_zone_standard_freemap_blocks_flat[BUDDY_BLOCKS_FOR(MEM_ZONE_STANDARD_PAGES)];
+static uintmax_t*
+ s_zone_standard_freemap_blocks[MEM_BUDDY_ORDERS];
+
+static struct PhysicalMemoryZone s_zones[MEM_ZONE_COUNT] =
+{
+ {
+ .name = "Standard",
+ .base = MEM_ZONE_STANDARD_BASE,
+ .limit = MEM_ZONE_STANDARD_LIMIT,
+ .npages_total = MEM_ZONE_STANDARD_PAGES,
+ .npages_free = 0,
+ .freemap = {
+ .orders = MEM_BUDDY_ORDERS,
+ .bits = MEM_ZONE_STANDARD_PAGES,
+ .free = 0,
+ .blocks = s_zone_standard_freemap_blocks
+ }
+ },
+ {
+ .name = "Higher",
+ .base = MEM_ZONE_HIGHER_BASE,
+ .limit = -1,
+ .freemap = {
+ .orders = MEM_BUDDY_ORDERS
+ }
+ }
+};
+
+void
+mem_zone_resv(size_t zone, uintptr_t base, uintptr_t limit)
+{
+ size_t base_off = base % PAGESIZE;
+ size_t limit_off = limit % PAGESIZE;
+
+ if(base_off > 0) base += (PAGESIZE - base_off);
+ limit -= limit_off;
+
+ buddy_mark_range(&s_zones[zone].freemap, base >> 12, limit >> 12);
+}
+
+void
+mem_zone_free(size_t zone, uintptr_t base, uintptr_t limit)
+{
+ size_t base_off = base % PAGESIZE;
+ size_t limit_off = limit % PAGESIZE;
+
+ if(base_off > 0) base += (PAGESIZE - base_off);
+ limit -= limit_off;
+
+ size_t npages = (limit - base) >> 12;
+ s_zones[zone].npages_free += npages;
+ buddy_free_range(&s_zones[zone].freemap, base >> 12, limit >> 12);
+}
+
+uintptr_t
+mem_zone_alloc(size_t zone, size_t pages)
+{
+ struct PhysicalMemoryZone *pmz = &s_zones[zone];
+ intmax_t pagei = buddy_alloc(&pmz->freemap, pages);
+ if(pagei < 0) return 0;
+
+ return (((uintmax_t)pagei) << 12) + pmz->base;
+}
+
+void
+mem_zone_setup_standard(void)
+{
+ struct PhysicalMemoryZone *standard_zone = &s_zones[MEM_ZONE_STANDARD];
+ uintmax_t *map_block_layer_base = s_zone_standard_freemap_blocks_flat;
+ for(size_t i = 0; i < MEM_BUDDY_ORDERS; i++) {
+ size_t layer_entries = (standard_zone->freemap.bits / BUDDY_BLOCK_BITS) >> i;
+ standard_zone->freemap.blocks[i] = map_block_layer_base;
+ memset(map_block_layer_base, 0xFF, layer_entries * sizeof(uintmax_t));
+ map_block_layer_base = &map_block_layer_base[layer_entries];
+ }
+
+ for(int i = 0; i < boot_memorymap.count; i++) {
+ struct MemoryMapEntry *entry = &boot_memorymap.entries[i];
+ klogf("%2i\t%#016X -> %#016X (%i)\n",
+ i, entry->base, entry->base + entry->length, entry->usable);
+ if(entry->base > MEM_ZONE_STANDARD_LIMIT) continue;
+ size_t limit = entry->base + entry->length;
+ if(limit > MEM_ZONE_STANDARD_LIMIT) limit = MEM_ZONE_STANDARD_LIMIT;
+ if(entry->usable)
+ mem_zone_free(MEM_ZONE_STANDARD, entry->base, limit);
+ }
+}
diff --git a/mem/zone.h b/mem/zone.h
new file mode 100644
index 0000000..7e863bf
--- /dev/null
+++ b/mem/zone.h
@@ -0,0 +1,52 @@
+#ifndef JOVE_MEM_ZONE_H
+#define JOVE_MEM_ZONE_H 1
+
+#include <stdint.h>
+#include "lib/buddymap.h"
+
+enum {
+ MEM_ZONE_STANDARD = 0, /* First GiB of physical memory. */
+ MEM_ZONE_HIGHER,
+ MEM_ZONE_COUNT
+};
+
+#define MEM_ZONE_STANDARD_BASE 0
+#define MEM_ZONE_STANDARD_LIMIT (1 * GiB)
+#define MEM_ZONE_HIGHER_BASE MEM_ZONE_STANDARD_LIMIT
+
+#define MEM_BUDDY_ORDERS 12
+struct PhysicalMemoryZone
+{
+ const char *name;
+
+ uintptr_t base;
+ uintptr_t limit;
+
+ size_t npages_total;
+ size_t npages_free;
+
+ struct BuddyMap freemap;
+};
+
+/** Using a given zone, reserve a range of physical addresses
+ * @param zone identifier of zone to modify
+ * @param base starting address to reserve
+ * @param limit ending address to reserve*/
+void mem_zone_resv(size_t zone, uintptr_t base, uintptr_t limit);
+
+/** Using a given zone, free a range of physical addresses
+ * @param zone identifier of zone to modify
+ * @param base starting address to free
+ * @param limit ending address to free*/
+void mem_zone_free(size_t zone, uintptr_t base, uintptr_t limit);
+
+/** Allocate a number of pages from the given zone
+ * @param zone identifier of the zone to modify
+ * @param pages number of pages to allocate
+ * @return physical memory address of allocation
+ * zero if allocation failed*/
+uintptr_t mem_zone_alloc(size_t zone, size_t pages);
+
+void mem_zone_setup_standard(void);
+
+#endif
diff --git a/usr/syscall.c b/usr/syscall.c
index 834bd5b..8680845 100644
--- a/usr/syscall.c
+++ b/usr/syscall.c
@@ -5,7 +5,6 @@
int _syscall_handler_log(struct syscall_log *req)
{
- klogf("Message ptr %#016X\n", req->message);
if(!mem_check_ptr(req->message)) return -1;
klogf("%s", req->message);
return 0;