From 31f671f2137bc09e62de09142bea232c1975c76b Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Sun, 26 Apr 2020 20:12:05 +0200
Subject: Complete rewrite of paging and allocation libs

-> This was REALLY needed.
---
 src/kernel/fs/ata.c          |   2 +-
 src/kernel/fs/elf.c          |  10 +-
 src/kernel/graphics/vesa.c   |  12 +-
 src/kernel/kernel.c          |   3 +-
 src/kernel/lib/memory.c      |  10 +-
 src/kernel/lib/stdlib/itoa.c |   5 +-
 src/kernel/memory/alloc.c    | 552 ++++++++++---------------------------------
 src/kernel/memory/alloc.h    |  61 +++--
 src/kernel/memory/paging.c   | 225 +++++++-----------
 src/kernel/memory/paging.h   |  75 +++---
 src/kernel/system.c          |   6 +-
 11 files changed, 310 insertions(+), 651 deletions(-)

(limited to 'src')

diff --git a/src/kernel/fs/ata.c b/src/kernel/fs/ata.c
index d5c758c..2a1ab6f 100644
--- a/src/kernel/fs/ata.c
+++ b/src/kernel/fs/ata.c
@@ -117,4 +117,4 @@ void read_abs_sectors(uint32_t lba, uint8_t sector_count, uint16_t buf[])
 		asm("rep insw" ::"c"(SECTOR_SIZE / 2), "d"(sel_base_port + DATA), "D"(buf + i));
 		i += SECTOR_SIZE / 2;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/kernel/fs/elf.c b/src/kernel/fs/elf.c
index b9ea22a..fe024e3 100644
--- a/src/kernel/fs/elf.c
+++ b/src/kernel/fs/elf.c
@@ -43,9 +43,9 @@ void elf_load(char *path)
 			seg_begin = program_header->vaddr;
 			seg_end = seg_begin + program_header->memsz;
 
-			for (uint32_t z = 0; z < seg_end - seg_begin; z += 4096)
-				paging_map((uint32_t)seg_begin + z, (uint32_t)seg_begin + z,
-					   PT_PRESENT | PT_RW | PT_USED | PT_ALL_PRIV);
+			/* for (uint32_t z = 0; z < seg_end - seg_begin; z += 4096) */
+			/* 	paging_map((uint32_t)seg_begin + z, (uint32_t)seg_begin + z, */
+			/* 		   PT_PRESENT | PT_RW | PT_USED | PT_ALL_PRIV); */
 
 			memcpy((void *)seg_begin, file + program_header->offset,
 			       program_header->filesz);
@@ -68,8 +68,8 @@ void elf_load(char *path)
 	set_kernel_stack(sp);
 
 	// paging_switch_directory(1);
-	uint32_t esp = paging_alloc_pages(0x1000);
-	asm("mov %0, %%esp" ::"r"(esp + 0x1000));
+	/* uint32_t esp = paging_alloc_pages(0x1000); */
+	/* asm("mov %0, %%esp" ::"r"(esp + 0x1000)); */
 
 	log("Jumping to usermode!");
 	asm volatile("\
diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c
index e8ef0e0..f116146 100644
--- a/src/kernel/graphics/vesa.c
+++ b/src/kernel/graphics/vesa.c
@@ -184,11 +184,11 @@ void set_optimal_resolution()
 
 	uint32_t fb_size = vbe_width * vbe_height * vbe_bpl;
 	cursor_buffer = kmalloc(fb_size);
-	for (uint32_t z = 0; z < fb_size; z += 4096) {
-		paging_map((uint32_t)fb + z, (uint32_t)fb + z, PT_PRESENT | PT_RW | PT_USED);
-		paging_map((uint32_t)cursor_buffer + z, (uint32_t)cursor_buffer + z,
-			   PT_PRESENT | PT_RW | PT_USED);
-	}
+	/* for (uint32_t z = 0; z < fb_size; z += 4096) { */
+	/* 	paging_map((uint32_t)fb + z, (uint32_t)fb + z, PT_PRESENT | PT_RW | PT_USED); */
+	/* 	paging_map((uint32_t)cursor_buffer + z, (uint32_t)cursor_buffer + z, */
+	/* 		   PT_PRESENT | PT_RW | PT_USED); */
+	/* } */
 
 	if (vbe_height > 1440)
 		vesa_set_font(32);
@@ -368,4 +368,4 @@ void vesa_set_color(uint32_t color)
 {
 	vesa_convert_color(terminal_color, color);
 	vesa_convert_color(terminal_background, default_background_color);
-}
\ No newline at end of file
+}
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index da3a8ef..756721f 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -39,8 +39,9 @@ void kernel_main(uint32_t magic, uint32_t multiboot_address)
 	idt_install();
 	isrs_install();
 	irq_install();
-	paging_install(multiboot_address);
 
+	memory_init(multiboot_address);
+	paging_install();
 	multiboot_parse(multiboot_address);
 
 	// Install drivers
diff --git a/src/kernel/lib/memory.c b/src/kernel/lib/memory.c
index c244052..5347add 100644
--- a/src/kernel/lib/memory.c
+++ b/src/kernel/lib/memory.c
@@ -52,7 +52,7 @@ uint32_t memory_get_all()
 
 uint32_t memory_get_free()
 {
-	return memory_get_all() - paging_get_used_pages() * 4;
+	return memory_get_all() /*- paging_get_used_pages() * 4*/;
 }
 
 void memory_print()
@@ -81,12 +81,12 @@ void memory_mmap_init(struct multiboot_tag_mmap *tag)
 					       ((struct multiboot_tag_mmap *)tag)->entry_size)) {
 		if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) {
 			debug("Found free memory");
-			paging_set_present(mmap->addr, mmap->len >> 12);
+			/* paging_set_present(mmap->addr, mmap->len >> 12); */
 			sum += mmap->len;
 		} else if (mmap->type == MULTIBOOT_MEMORY_RESERVED) {
 			debug("Found reserved memory");
-			paging_set_present(mmap->addr, mmap->len >> 12);
-			paging_set_used(mmap->addr, mmap->len >> 12);
+			/* paging_set_present(mmap->addr, mmap->len >> 12); */
+			/* paging_set_used(mmap->addr, mmap->len >> 12); */
 		} else if (mmap->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) {
 			debug("Found ACPI reclaimable memory");
 		} else if (mmap->type == MULTIBOOT_MEMORY_NVS) {
@@ -116,4 +116,4 @@ int memory_init(uint32_t multiboot_address)
 		}
 	}
 	return ret;
-}
\ No newline at end of file
+}
diff --git a/src/kernel/lib/stdlib/itoa.c b/src/kernel/lib/stdlib/itoa.c
index 94c3351..e6300d9 100644
--- a/src/kernel/lib/stdlib/itoa.c
+++ b/src/kernel/lib/stdlib/itoa.c
@@ -8,9 +8,6 @@ static const char ITOA_TABLE[] = "0123456789";
 
 char *itoa(int n)
 {
-	if (paging_enabled == 0)
-		return "0"; // kmalloc isn't available
-
 	if (!n) {
 		char *ret = (char *)kmalloc(2);
 		ret[0] = '0';
@@ -44,4 +41,4 @@ char *itoa(int n)
 
 	strinv(ret);
 	return ret;
-}
\ No newline at end of file
+}
diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c
index 174f298..fbf97d8 100644
--- a/src/kernel/memory/alloc.c
+++ b/src/kernel/memory/alloc.c
@@ -2,478 +2,188 @@
 #include <stdint.h>
 #include <kernel/memory/paging.h>
 #include <kernel/memory/alloc.h>
+#include <kernel/system.h>
+#include <kernel/lib/lib.h>
 
-int liballoc_lock()
-{
-	// cli();
-	return 0;
-}
+uint32_t placement_address;
 
-int liballoc_unlock()
-{
-	// sti();
-	return 0;
-}
-
-void *liballoc_alloc(size_t p)
-{
-	uint32_t ptr = paging_alloc_pages((uint32_t)p);
-	return (void *)ptr;
-}
+struct heap_header *kheap = NULL;
+struct heap_header *uheap = NULL;
 
-int liballoc_free(void *ptr, size_t p)
+void kheap_init()
 {
-	paging_set_free((uint32_t)ptr, (uint32_t)p);
-	return 0;
+	placement_address = &ASM_KERNEL_END;
+	kheap = (struct heap_header *)fmalloc(KHEAP_SIZE);
+	init_heap(kheap, KHEAP_SIZE);
+
+	// Make user heap
+	uheap = (struct heap_header *)kmalloc_a(UHEAP_SIZE);
+	init_heap(uheap, UHEAP_SIZE);
+	paging_map_user(paging_root_directory, (uint32_t)&uheap, (uint32_t)&uheap);
 }
 
-#define ALIGNMENT 16ul
-#define ALIGN_TYPE char
-#define ALIGN_INFO sizeof(ALIGN_TYPE) * 16
-#define USE_CASE1
-#define USE_CASE2
-#define USE_CASE3
-#define USE_CASE4
-#define USE_CASE5
-
-#define ALIGN(ptr)                                                                                 \
-	if (ALIGNMENT > 1) {                                                                       \
-		uintptr_t diff;                                                                    \
-		ptr = (void *)((uintptr_t)ptr + ALIGN_INFO);                                       \
-		diff = (uintptr_t)ptr & (ALIGNMENT - 1);                                           \
-		if (diff != 0) {                                                                   \
-			diff = ALIGNMENT - diff;                                                   \
-			ptr = (void *)((uintptr_t)ptr + diff);                                     \
-		}                                                                                  \
-		*((ALIGN_TYPE *)((uintptr_t)ptr - ALIGN_INFO)) = diff + ALIGN_INFO;                \
-	}
-
-#define UNALIGN(ptr)                                                                               \
-	if (ALIGNMENT > 1) {                                                                       \
-		uintptr_t diff = *((ALIGN_TYPE *)((uintptr_t)ptr - ALIGN_INFO));                   \
-		if (diff < (ALIGNMENT + ALIGN_INFO)) {                                             \
-			ptr = (void *)((uintptr_t)ptr - diff);                                     \
-		}                                                                                  \
-	}
-
-#define LIBALLOC_MAGIC 0x900df00d
-#define LIBALLOC_DEAD 0xbaadf00d
-
-struct liballoc_major {
-	struct liballoc_major *prev;
-	struct liballoc_major *next;
-	unsigned int pages;
-	unsigned int size;
-	unsigned int usage;
-	struct liballoc_minor *first;
-};
-
-struct liballoc_minor {
-	struct liballoc_minor *prev;
-	struct liballoc_minor *next;
-	struct liballoc_major *block;
-	unsigned int magic;
-	unsigned int size;
-	unsigned int req_size;
-};
-
-static struct liballoc_major *l_memRoot = NULL;
-static struct liballoc_major *l_bestBet = NULL;
-
-static unsigned int l_pageSize = 4096;
-static unsigned int l_pageCount = 16;
-static unsigned long long l_allocated = 0;
-static unsigned long long l_inuse = 0;
-
-static long long l_warningCount = 0;
-static long long l_errorCount = 0;
-static long long l_possibleOverruns = 0;
-
-static void *liballoc_memset(void *s, int c, size_t n)
+void *fmalloc(uint32_t size)
 {
-	unsigned int i;
-	for (i = 0; i < n; i++)
-		((char *)s)[i] = c;
-
-	return s;
+	//assert(placement_address + size < MEM_END);
+	uint32_t hold = placement_address;
+	memset((void *)hold, 0, size);
+	placement_address += size;
+	return (void *)hold;
 }
 
-static void *liballoc_memcpy(void *s1, const void *s2, size_t n)
+void *kmalloc_a(uint32_t size)
 {
-	char *cdest;
-	char *csrc;
-	unsigned int *ldest = (unsigned int *)s1;
-	unsigned int *lsrc = (unsigned int *)s2;
-
-	while (n >= sizeof(unsigned int)) {
-		*ldest++ = *lsrc++;
-		n -= sizeof(unsigned int);
-	}
+	//assert(((placement_address & 0xFFFFF000) + 0x1000) + size < MEM_END);
+	placement_address &= 0xFFFFF000;
+	placement_address += 0x1000;
 
-	cdest = (char *)ldest;
-	csrc = (char *)lsrc;
+	uint32_t hold = placement_address;
+	placement_address += size;
 
-	while (n > 0) {
-		*cdest++ = *csrc++;
-		n -= 1;
-	}
-	return s1;
+	return (void *)hold;
 }
 
-static struct liballoc_major *allocate_new_page(unsigned int size)
+struct heap_header *find_sized_heap(struct heap_header *heap, size_t size)
 {
-	unsigned int st;
-	struct liballoc_major *maj;
+	while ((heap->size < HEAP_FIND_SIZE + size) || (heap->free != true)) {
+		assert(heap->magic == KHEAP_MAGIC);
+		assert(heap->magic2 == KHEAP_MAGIC2);
+		struct heap_footer *foot =
+			(struct heap_footer *)((uint32_t)heap + HEAP_S + heap->size);
+		assert(foot->magic == KHEAP_MAGIC);
+		assert(foot->magic2 == KHEAP_MAGIC2);
 
-	st = size + sizeof(struct liballoc_major);
-	st += sizeof(struct liballoc_minor);
+		if (foot->size == KHEAP_END)
+			panic("Out of heap space");
 
-	if ((st % l_pageSize) == 0)
-		st = st / (l_pageSize);
-	else
-		st = st / (l_pageSize) + 1;
+		if (foot->size != heap->size)
+			panic("Heap footer/header mismatch");
 
-	if (st < l_pageCount)
-		st = l_pageCount;
-
-	maj = (struct liballoc_major *)liballoc_alloc(st);
-
-	if (maj == NULL) {
-		l_warningCount += 1;
-		return NULL;
+		heap = (struct heap_header *)((uint32_t)foot + sizeof(struct heap_footer));
 	}
 
-	maj->prev = NULL;
-	maj->next = NULL;
-	maj->pages = st;
-	maj->size = st * l_pageSize;
-	maj->usage = sizeof(struct liballoc_major);
-	maj->first = NULL;
-
-	l_allocated += maj->size;
-
-	return maj;
+	return heap;
 }
 
-void *PREFIX(malloc)(size_t req_size)
+void split_heap(struct heap_header *heap, size_t size)
 {
-	int startedBet = 0;
-	unsigned long long bestSize = 0;
-	void *p = NULL;
-	uintptr_t diff;
-	struct liballoc_major *maj;
-	struct liballoc_minor *min;
-	struct liballoc_minor *new_min;
-	unsigned long size = req_size;
-
-	if (ALIGNMENT > 1) {
-		size += ALIGNMENT + ALIGN_INFO;
-	}
-
-	liballoc_lock();
-
-	if (size == 0) {
-		l_warningCount += 1;
-		liballoc_unlock();
-		return PREFIX(malloc)(1);
-	}
-
-	if (l_memRoot == NULL) {
-		l_memRoot = allocate_new_page(size);
-		if (l_memRoot == NULL) {
-			liballoc_unlock();
-			return NULL;
-		}
-	}
+	struct heap_footer *foot = (struct heap_footer *)((uint32_t)heap + HEAP_S + size);
+	foot->magic = KHEAP_MAGIC;
+	foot->magic2 = KHEAP_MAGIC2;
+	foot->size = size;
 
-	maj = l_memRoot;
-	startedBet = 0;
+	size_t new_size = heap->size - HEAP_TOTAL - size;
+	heap->size = size;
 
-	if (l_bestBet != NULL) {
-		bestSize = l_bestBet->size - l_bestBet->usage;
+	heap = (struct heap_header *)((uint32_t)foot + sizeof(struct heap_footer));
+	heap->size = new_size;
+	heap->free = true;
+	heap->magic = KHEAP_MAGIC;
+	heap->magic2 = KHEAP_MAGIC2;
 
-		if (bestSize > (size + sizeof(struct liballoc_minor))) {
-			maj = l_bestBet;
-			startedBet = 1;
-		}
+	foot = (struct heap_footer *)((uint32_t)heap + HEAP_S + heap->size);
+	if ((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)) {
+		warn("Invalid footer in split");
 	}
 
-	while (maj != NULL) {
-		diff = maj->size - maj->usage;
-		if (bestSize < diff) {
-			l_bestBet = maj;
-			bestSize = diff;
-		}
-
-#ifdef USE_CASE1
-		if (diff < (size + sizeof(struct liballoc_minor))) {
-			if (maj->next != NULL) {
-				maj = maj->next;
-				continue;
-			}
-
-			if (startedBet == 1) {
-				maj = l_memRoot;
-				startedBet = 0;
-				continue;
-			}
-
-			maj->next = allocate_new_page(size);
-			if (maj->next == NULL)
-				break;
-			maj->next->prev = maj;
-			maj = maj->next;
-		}
-#endif
-
-#ifdef USE_CASE2
-		if (maj->first == NULL) {
-			maj->first = (struct liballoc_minor *)((uintptr_t)maj +
-							       sizeof(struct liballoc_major));
-
-			maj->first->magic = LIBALLOC_MAGIC;
-			maj->first->prev = NULL;
-			maj->first->next = NULL;
-			maj->first->block = maj;
-			maj->first->size = size;
-			maj->first->req_size = req_size;
-			maj->usage += size + sizeof(struct liballoc_minor);
-			l_inuse += size;
-			p = (void *)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor));
-			ALIGN(p);
-			liballoc_unlock();
-			return p;
-		}
-#endif
-
-#ifdef USE_CASE3
-		diff = (uintptr_t)(maj->first);
-		diff -= (uintptr_t)maj;
-		diff -= sizeof(struct liballoc_major);
-
-		if (diff >= (size + sizeof(struct liballoc_minor))) {
-			maj->first->prev = (struct liballoc_minor *)((uintptr_t)maj +
-								     sizeof(struct liballoc_major));
-			maj->first->prev->next = maj->first;
-			maj->first = maj->first->prev;
-			maj->first->magic = LIBALLOC_MAGIC;
-			maj->first->prev = NULL;
-			maj->first->block = maj;
-			maj->first->size = size;
-			maj->first->req_size = req_size;
-			maj->usage += size + sizeof(struct liballoc_minor);
-			l_inuse += size;
-			p = (void *)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor));
-			ALIGN(p);
-			liballoc_unlock();
-			return p;
-		}
-#endif
-
-#ifdef USE_CASE4
-		min = maj->first;
-
-		while (min != NULL) {
-			if (min->next == NULL) {
-				diff = (uintptr_t)(maj) + maj->size;
-				diff -= (uintptr_t)min;
-				diff -= sizeof(struct liballoc_minor);
-				diff -= min->size;
-				if (diff >= (size + sizeof(struct liballoc_minor))) {
-					min->next = (struct liballoc_minor
-							     *)((uintptr_t)min +
-								sizeof(struct liballoc_minor) +
-								min->size);
-					min->next->prev = min;
-					min = min->next;
-					min->next = NULL;
-					min->magic = LIBALLOC_MAGIC;
-					min->block = maj;
-					min->size = size;
-					min->req_size = req_size;
-					maj->usage += size + sizeof(struct liballoc_minor);
-					l_inuse += size;
-					p = (void *)((uintptr_t)min +
-						     sizeof(struct liballoc_minor));
-					ALIGN(p);
-					liballoc_unlock();
-					return p;
-				}
-			}
-
-			if (min->next != NULL) {
-				diff = (uintptr_t)(min->next);
-				diff -= (uintptr_t)min;
-				diff -= sizeof(struct liballoc_minor);
-				diff -= min->size;
-
-				if (diff >= (size + sizeof(struct liballoc_minor))) {
-					new_min = (struct liballoc_minor
-							   *)((uintptr_t)min +
-							      sizeof(struct liballoc_minor) +
-							      min->size);
-					new_min->magic = LIBALLOC_MAGIC;
-					new_min->next = min->next;
-					new_min->prev = min;
-					new_min->size = size;
-					new_min->req_size = req_size;
-					new_min->block = maj;
-					min->next->prev = new_min;
-					min->next = new_min;
-					maj->usage += size + sizeof(struct liballoc_minor);
-					l_inuse += size;
-					p = (void *)((uintptr_t)new_min +
-						     sizeof(struct liballoc_minor));
-					ALIGN(p);
-					liballoc_unlock();
-					return p;
-				}
-			}
-
-			min = min->next;
-		}
-#endif
-
-#ifdef USE_CASE5
-		if (maj->next == NULL) {
-			if (startedBet == 1) {
-				maj = l_memRoot;
-				startedBet = 0;
-				continue;
-			}
-			maj->next = allocate_new_page(size);
-			if (maj->next == NULL)
-				break;
-			maj->next->prev = maj;
-		}
-#endif
-		maj = maj->next;
-	}
-
-	liballoc_unlock();
-
-	return NULL;
+	if (foot->size != KHEAP_END)
+		foot->size = new_size;
 }
 
-void PREFIX(free)(void *ptr)
+void free_internal(struct heap_header *heap, void *address)
 {
-	struct liballoc_minor *min;
-	struct liballoc_major *maj;
-
-	if (ptr == NULL) {
-		l_warningCount += 1;
+	struct heap_header *head = (struct heap_header *)((uint32_t)address - HEAP_S);
+	if (head == heap) {
+		warn("Can't collapse top of heap");
+		head->free = true;
 		return;
 	}
 
-	UNALIGN(ptr);
-	liballoc_lock();
+	if ((head->magic != KHEAP_MAGIC) || (head->magic2 != KHEAP_MAGIC2)) {
+		//warn("Invalid header in heap");
+		return;
+	}
 
-	min = (struct liballoc_minor *)((uintptr_t)ptr - sizeof(struct liballoc_minor));
+	struct heap_footer *foot = (struct heap_footer *)((uint32_t)head + HEAP_S + head->size);
+	if ((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2))
+		panic("Bad heap call");
 
-	if (min->magic != LIBALLOC_MAGIC) {
-		l_errorCount += 1;
+	foot = (struct heap_footer *)((uint32_t)head - sizeof(struct heap_footer));
+	if ((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)) {
+		//warn("Invalid footer in heap");
+		return;
+	}
 
-		if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
-		    ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
-		    ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
-			l_possibleOverruns += 1;
-		}
+	if (foot->size == KHEAP_END)
+		panic("Impossible condition for heap");
 
-		liballoc_unlock();
+	heap = (struct heap_header *)((uint32_t)foot - foot->size - HEAP_S);
+	if ((heap->magic != KHEAP_MAGIC) || (heap->magic2 != KHEAP_MAGIC2)) {
+		warn("Invalid parent in heap");
 		return;
 	}
 
-	maj = min->block;
-	l_inuse -= min->size;
-	maj->usage -= (min->size + sizeof(struct liballoc_minor));
-	min->magic = LIBALLOC_DEAD;
-
-	if (min->next != NULL)
-		min->next->prev = min->prev;
-	if (min->prev != NULL)
-		min->prev->next = min->next;
-	if (min->prev == NULL)
-		maj->first = min->next;
-	if (maj->first == NULL) {
-		if (l_memRoot == maj)
-			l_memRoot = maj->next;
-		if (l_bestBet == maj)
-			l_bestBet = NULL;
-		if (maj->prev != NULL)
-			maj->prev->next = maj->next;
-		if (maj->next != NULL)
-			maj->next->prev = maj->prev;
-		l_allocated -= maj->size;
-		liballoc_free(maj, maj->pages);
-	} else {
-		if (l_bestBet != NULL) {
-			int bestSize = l_bestBet->size - l_bestBet->usage;
-			int majSize = maj->size - maj->usage;
-			if (majSize > bestSize)
-				l_bestBet = maj;
-		}
+	foot = (struct heap_footer *)((uint32_t)heap + (heap->size + head->size + HEAP_TOTAL) +
+				      HEAP_S);
+	if ((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)) {
+		/*vga_puts("Footer with size of ");
+		vga_puts_hex(foot->size);
+		vga_puts(" / head size of ");
+		vga_puts_hex(heap->size);
+		vga_puts("\n");
+		dump_struct(foot, sizeof(struct heap_footer));
+		warn("fatal arithmetic error in free() call");
+		*/
+		return;
 	}
-	liballoc_unlock();
+
+	heap->size += head->size + HEAP_TOTAL;
+	foot->size = heap->size;
 }
 
-void *PREFIX(calloc)(size_t nobj, size_t size)
+void *malloc_internal(struct heap_header *heap, size_t size)
 {
-	int real_size;
-	void *p;
-
-	real_size = nobj * size;
-
-	p = PREFIX(malloc)(real_size);
-
-	liballoc_memset(p, 0, real_size);
-
-	return p;
+	heap = find_sized_heap(heap, size + 8);
+	heap->free = false;
+	split_heap(heap, size);
+	return (void *)((uint32_t)heap + HEAP_S);
 }
 
-void *PREFIX(realloc)(void *p, size_t size)
+void init_heap(struct heap_header *heap, size_t size)
 {
-	void *ptr;
-	struct liballoc_minor *min;
-	unsigned int real_size;
-
-	if (size == 0) {
-		PREFIX(free)(p);
-		return NULL;
-	}
-
-	if (p == NULL)
-		return PREFIX(malloc)(size);
-
-	ptr = p;
-	UNALIGN(ptr);
-	liballoc_lock();
-	min = (struct liballoc_minor *)((uintptr_t)ptr - sizeof(struct liballoc_minor));
-
-	if (min->magic != LIBALLOC_MAGIC) {
-		l_errorCount += 1;
-		if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
-		    ((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
-		    ((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
-			l_possibleOverruns += 1;
-		}
+	heap->magic = KHEAP_MAGIC;
+	heap->magic2 = KHEAP_MAGIC2;
+	heap->free = true;
+	heap->size = size - HEAP_TOTAL;
+
+	struct heap_footer *foot = (struct heap_footer *)((uint32_t)heap + HEAP_S + heap->size);
+	foot->magic = KHEAP_MAGIC;
+	foot->magic2 = KHEAP_MAGIC2;
+	foot->size = KHEAP_END;
+}
 
-		liballoc_unlock();
-		return NULL;
-	}
+void *kmalloc(uint32_t size)
+{
+	if (kheap == NULL)
+		return fmalloc(size);
 
-	real_size = min->req_size;
+	return malloc_internal(kheap, size);
+}
 
-	if (real_size >= size) {
-		min->req_size = size;
-		liballoc_unlock();
-		return p;
-	}
+void kfree(void *address)
+{
+	if (kheap == NULL)
+		return;
 
-	liballoc_unlock();
+	free_internal(kheap, address);
+}
 
-	ptr = PREFIX(malloc)(size);
-	liballoc_memcpy(ptr, p, real_size);
-	PREFIX(free)(p);
+void *umalloc(size_t size)
+{
+	return malloc_internal(uheap, size);
+}
 
-	return ptr;
-}
\ No newline at end of file
+void ufree(void *address)
+{
+	free_internal(uheap, address);
+}
diff --git a/src/kernel/memory/alloc.h b/src/kernel/memory/alloc.h
index 3ddc8d8..16d61f5 100644
--- a/src/kernel/memory/alloc.h
+++ b/src/kernel/memory/alloc.h
@@ -2,23 +2,44 @@
 #define MELVIX_ALLOC_H
 
 #include <stddef.h>
-
-#define PREFIX(func) k##func
-
-int liballoc_lock();
-
-int liballoc_unlock();
-
-void *liballoc_alloc(size_t);
-
-int liballoc_free(void *, size_t);
-
-void *PREFIX(malloc)(size_t);
-
-void *PREFIX(realloc)(void *, size_t);
-
-void *PREFIX(calloc)(size_t, size_t);
-
-void PREFIX(free)(void *);
-
-#endif
\ No newline at end of file
+#include <stdint.h>
+#include <stdbool.h>
+
+#define KHEAP_MAGIC 0x04206969
+#define KHEAP_MAGIC2 0xDEADBEEF
+#define KHEAP_END 0xFFFFDEAD
+#define MEM_END 0x8000000
+
+struct heap_header {
+	uint32_t magic;
+	bool free;
+	uint32_t size;
+	uint32_t magic2;
+};
+
+struct heap_footer {
+	uint32_t magic;
+	uint32_t size;
+	uint32_t magic2;
+};
+
+void kheap_init();
+
+void *fmalloc(uint32_t size);
+void *kmalloc(uint32_t size);
+void *kmalloc_a(uint32_t size);
+void kfree(void *ptr);
+
+void *umalloc(size_t size);
+void ufree(void *address);
+
+void init_heap(struct heap_header *heap, size_t size);
+
+#define KHEAP_SIZE 0xFFFFF
+#define UHEAP_SIZE 0xFFFFF
+#define HEAP_S (sizeof(struct heap_header))
+#define HEAP_TOTAL (sizeof(struct heap_footer) + HEAP_S)
+#define HEAP_MINIMUM 1
+#define HEAP_FIND_SIZE (HEAP_TOTAL + HEAP_MINIMUM)
+
+#endif
diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c
index e237a90..910b569 100644
--- a/src/kernel/memory/paging.c
+++ b/src/kernel/memory/paging.c
@@ -1,198 +1,143 @@
 #include <stdint.h>
 #include <kernel/memory/paging.h>
+#include <kernel/memory/alloc.h>
 #include <kernel/system.h>
 #include <kernel/lib/lib.h>
 #include <kernel/io/io.h>
 #include <kernel/acpi/acpi.h>
 
-int paging_enabled = 0;
+struct page_directory *paging_current_directory = NULL;
+struct page_directory *paging_root_directory = NULL;
 
-uint32_t *current_page_directory;
-uint32_t (*current_page_tables)[1024];
-uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
-uint32_t kernel_page_tables[1024][1024] __attribute__((aligned(4096)));
-uint32_t user_page_directory[1024] __attribute__((aligned(4096)));
-uint32_t user_page_tables[1024][1024] __attribute__((aligned(4096)));
+/* void paging_install(uint32_t multiboot_address) */
+/* { */
+/* 	if (!memory_init(multiboot_address)) */
+/* 		paging_set_present(0, memory_get_all() >> 3); // /4 */
+/* 	paging_set_used(0, ((uint32_t)ASM_KERNEL_END >> 12) + 1); // /4096 */
+/* } */
 
-void paging_init()
+struct page_table *get_cr3()
 {
-	for (uint32_t i = 0; i < 1024; i++) {
-		for (uint32_t j = 0; j < 1024; j++) {
-			current_page_tables[i][j] = ((j * 0x1000) + (i * 0x400000)) | PT_RW;
-		}
-	}
-
-	for (uint32_t i = 0; i < 1024; i++) {
-		current_page_directory[i] = ((uint32_t)current_page_tables[i]) | PD_RW | PD_PRESENT;
-	}
-}
-
-void paging_install(uint32_t multiboot_address)
-{
-	// User paging
-	paging_switch_directory(1);
-	paging_init();
-	paging_set_user(0, memory_get_all() >> 3);
-
-	// Kernel paging
-	paging_switch_directory(0);
-	paging_init();
-
-	// if mmap approach didn't work
-	if (!memory_init(multiboot_address))
-		paging_set_present(0, memory_get_all() >> 3); // /4
-	paging_set_used(0, ((uint32_t)ASM_KERNEL_END >> 12) + 1); // /4096
-	// paging_set_user(0, memory_get_all() >> 3); // HMM
-
-	paging_enable();
-	log("Installed paging");
+	uint32_t cr3;
+	asm volatile("movl %%cr3, %%eax" : "=a"(cr3));
+	return (struct page_table *)cr3;
 }
 
-void paging_disable()
+uint32_t get_cr0()
 {
 	uint32_t cr0;
-	asm("mov %%cr0, %0" : "=r"(cr0));
-	cr0 &= 0x7fffffff;
-	asm("mov %0, %%cr0" ::"r"(cr0));
-	paging_enabled = 0;
+	asm volatile("movl %%cr0, %%eax" : "=a"(cr0));
+	return cr0;
 }
 
-void paging_enable()
+void set_cr3(struct page_directory *dir)
 {
-	asm("mov %0, %%cr3" ::"r"(current_page_directory));
-	uint32_t cr0;
-	asm("mov %%cr0, %0" : "=r"(cr0));
-	cr0 |= 0x80000000;
-	asm("mov %0, %%cr0" ::"r"(cr0));
-	paging_enabled = 1;
+	uint32_t addr = (uint32_t)&dir->tables[0];
+	asm volatile("movl %%eax, %%cr3" ::"a"(addr));
 }
 
-void paging_switch_directory(int user)
+void set_cr0(uint32_t cr0)
 {
-	if (user == 1) {
-		current_page_tables = user_page_tables;
-		current_page_directory = user_page_directory;
-	} else {
-		current_page_tables = kernel_page_tables;
-		current_page_directory = kernel_page_directory;
-	}
-	asm("mov %0, %%cr3" ::"r"(current_page_directory));
+	asm volatile("movl %%eax, %%cr0" ::"a"(cr0));
 }
 
-void invlpg(uint32_t addr)
+void paging_switch_directory(struct page_directory *dir)
 {
-	asm("invlpg (%0)" ::"r"(addr) : "memory");
+	set_cr3(dir);
+	set_cr0(get_cr0() | 0x80000000);
 }
 
-void paging_map(uint32_t phy, uint32_t virt, uint16_t flags)
+struct page_directory *paging_make_directory()
 {
-	uint32_t pdi = virt >> 22;
-	uint32_t pti = virt >> 12 & 0x03FF;
-	current_page_tables[pdi][pti] = phy | flags;
-	invlpg(virt);
-}
+	struct page_directory *dir =
+		(struct page_directory *)kmalloc_a(sizeof(struct page_directory));
 
-uint32_t paging_get_phys(uint32_t virt)
-{
-	uint32_t pdi = virt >> 22;
-	uint32_t pti = (virt >> 12) & 0x03FF;
-	return current_page_tables[pdi][pti] & 0xFFFFF000;
-}
+	for (int i = 0; i < 1024; i++)
+		dir->tables[i] = EMPTY_TAB;
 
-uint16_t paging_get_flags(uint32_t virt)
-{
-	uint32_t pdi = virt >> 22;
-	uint32_t pti = (virt >> 12) & 0x03FF;
-	return current_page_tables[pdi][pti] & 0xFFF;
+	return dir;
 }
 
-void paging_set_flag_up(uint32_t virt, uint32_t count, uint32_t flag)
+struct page_table *paging_make_table()
 {
-	uint32_t page_n = virt / 0x1000;
-	for (uint32_t i = page_n; i < page_n + count; i++) {
-		current_page_tables[i / 1024][i % 1024] |= flag;
-		invlpg(i * 0x1000);
+	struct page_table *tab = (struct page_table *)kmalloc_a(sizeof(struct page_table));
+
+	for (int i = 0; i < 1024; i++) {
+		tab->pages[i].present = 0;
+		tab->pages[i].rw = 1;
 	}
+
+	return tab;
 }
 
-void paging_set_flag_down(uint32_t virt, uint32_t count, uint32_t flag)
+void paging_map(struct page_directory *dir, uint32_t phys, uint32_t virt)
 {
-	uint32_t page_n = virt / 0x1000;
-	for (uint32_t i = page_n; i < page_n + count; i++) {
-		current_page_tables[i / 1024][i % 1024] &= ~flag;
-		invlpg(i * 0x1000);
+	short id = virt >> 22;
+	struct page_table *tab = paging_make_table();
+
+	dir->tables[id] = ((struct page_table *)((uint32_t)tab | 3)); // RW
+
+	for (int i = 0; i < 1024; i++) {
+		tab->pages[i].frame = phys >> 12;
+		tab->pages[i].present = 1;
+		phys += 4096;
 	}
 }
 
-void paging_set_present(uint32_t virt, uint32_t count)
+void paging_map_user(struct page_directory *dir, uint32_t phys, uint32_t virt)
 {
-	paging_set_flag_up(virt, count, PT_PRESENT);
-}
+	short id = virt >> 22;
+	struct page_table *tab = paging_make_table();
 
-void paging_set_absent(uint32_t virt, uint32_t count)
-{
-	paging_set_flag_down(virt, count, PT_PRESENT);
-}
+	dir->tables[id] = ((struct page_table *)((uint32_t)tab | 3 | 4)); // RW + usermode
 
-void paging_set_used(uint32_t virt, uint32_t count)
-{
-	paging_set_flag_up(virt, count, PT_USED);
+	int i;
+	for (i = 0; i < 1024; i++) {
+		tab->pages[i].frame = phys >> 12;
+		tab->pages[i].present = 1;
+		tab->pages[i].user = 1;
+		phys += 4096;
+	}
 }
 
-void paging_set_free(uint32_t virt, uint32_t count)
+void paging_install()
 {
-	paging_set_flag_down(virt, count, PT_USED);
-}
+	kheap_init();
 
-void paging_set_user(uint32_t virt, uint32_t count)
-{
-	uint32_t page_n = virt / 0x1000;
-	for (uint32_t i = page_n; i < page_n + count; i += 1024) {
-		current_page_directory[i / 1024] |= PD_ALL_PRIV;
-	}
-	paging_set_flag_up(virt, count, PT_ALL_PRIV);
+	paging_current_directory = paging_make_directory();
+	paging_root_directory = paging_current_directory;
+
+	for (uint32_t i = 0; i < 0xF0000000; i += PAGE_S)
+		paging_map(paging_root_directory, i, i);
 }
 
-uint32_t paging_find_pages(uint32_t count)
+void paging_convert_page(struct page_directory *kdir)
 {
-	uint32_t continuous = 0;
-	uint32_t startDir = 0;
-	uint32_t startPage = 0;
-	for (uint32_t i = 0; i < 1024; i++) {
-		for (uint32_t j = 0; j < 1024; j++) {
-			if (!(current_page_tables[i][j] & PT_PRESENT) ||
-			    (current_page_tables[i][j] & PT_USED)) {
-				continuous = 0;
-				startDir = i;
-				startPage = j + 1;
-			} else {
-				if (++continuous == count)
-					return (startDir * 0x400000) + (startPage * 0x1000);
-			}
+	for (int i = 0; i < 1024; i++) {
+		kdir->tables[i] = (struct page_table *)((uint32_t)kdir->tables[i] | 4); // Usermode
+
+		if (((uint32_t)kdir->tables[i]) & 1) { // Is present
+			for (int j = 0; j < 1024; j++)
+				kdir->tables[i]->pages[j].user = 1; // Usermode
 		}
 	}
-
-	panic("Out of memory!");
-	return 0;
 }
 
-uint32_t paging_alloc_pages(uint32_t count)
+struct page_directory *paging_copy_user_directory(struct page_directory *dir)
 {
-	uint32_t ptr = paging_find_pages(count);
-	paging_set_used(ptr, count);
-	paging_set_user(ptr, count);
-	return ptr;
-}
+	struct page_directory *copy = paging_make_directory();
+	memcpy(copy, paging_root_directory, sizeof(struct page_directory));
 
-uint32_t paging_get_used_pages()
-{
-	uint32_t n = 0;
 	for (uint32_t i = 0; i < 1024; i++) {
-		for (uint32_t j = 0; j < 1024; j++) {
-			uint8_t flags = current_page_tables[i][j] & PT_USED;
-			if (flags == 1)
-				n++;
+		if (((uint32_t)dir->tables[i]) & 4) {
+			struct page_table *tab =
+				(struct page_table *)((uint32_t)dir->tables[i] & 0xFFFFF000);
+
+			void *buffer = kmalloc_a(PAGE_S);
+			memcpy(buffer, (void *)(tab->pages[0].frame << 12), PAGE_S);
+			paging_map_user(copy, (uint32_t)buffer, (uint32_t)i << 22);
 		}
 	}
-	return n;
+
+	return copy;
 }
diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h
index 1578e2a..c02cd3a 100644
--- a/src/kernel/memory/paging.h
+++ b/src/kernel/memory/paging.h
@@ -3,62 +3,47 @@
 
 #include <stdint.h>
 
-#define PD_PRESENT 1 << 0
-#define PD_RW 1 << 1
-#define PD_ALL_PRIV 1 << 2
-#define PD_WRITETHR 1 << 3
-#define PD_CACHE_D 1 << 4
-#define PD_ACCESSED 1 << 5
-#define PD_4M_PAGE 1 << 7
+struct page {
+	uint32_t present : 1;
+	uint32_t rw : 1;
+	uint32_t user : 1;
+	uint32_t accessed : 1;
+	uint32_t dirty : 1;
+	uint32_t unused : 7;
+	uint32_t frame : 20;
+};
 
-#define PT_PRESENT 1 << 0
-#define PT_RW 1 << 1
-#define PT_ALL_PRIV 1 << 2
-#define PT_WRITETHR 1 << 3
-#define PT_CACHE_D 1 << 4
-#define PT_ACCESSED 1 << 5
-#define PT_DIRTY 1 << 6
-#define PT_GLOBAL 1 << 8
-#define PT_USED 1 << 9
+struct page_table {
+	struct page pages[1024];
+};
 
-int paging_enabled;
+struct page_directory {
+	struct page_table *tables[1024];
+};
 
-uint32_t *current_page_directory;
+struct page_directory *paging_root_directory;
 
-void paging_install(uint32_t multiboot_address);
+struct page_table *get_cr3();
+uint32_t get_cr0();
 
-void paging_enable();
+void set_cr3(struct page_directory *dir);
+void set_cr0(uint32_t new_cr0);
 
-void paging_disable();
+void paging_switch_directory(struct page_directory *dir);
 
-void paging_switch_directory(int user);
+struct page_directory *paging_make_directory();
+struct page_table *paging_make_table();
 
-void paging_map(uint32_t phy, uint32_t virt, uint16_t flags);
+void paging_install();
 
-uint32_t paging_get_phys(uint32_t virt);
+void paging_map(struct page_directory *cr3, uint32_t virt, uint32_t phys);
+void paging_map_user(struct page_directory *cr3, uint32_t virt, uint32_t phys);
 
-uint16_t paging_get_flags(uint32_t virt);
+void paging_convert_page(struct page_directory *kdir);
 
-void paging_set_flags(uint32_t virt, uint32_t count, uint16_t flags);
+struct page_directory *paging_copy_user_directory(struct page_directory *dir);
 
-void paging_set_flag_up(uint32_t virt, uint32_t count, uint32_t flag);
-
-void paging_set_flag_down(uint32_t virt, uint32_t count, uint32_t flag);
-
-void paging_set_present(uint32_t virt, uint32_t count);
-
-void paging_set_absent(uint32_t virt, uint32_t count);
-
-void paging_set_used(uint32_t virt, uint32_t count);
-
-void paging_set_free(uint32_t virt, uint32_t count);
-
-void paging_set_user(uint32_t virt, uint32_t count);
-
-uint32_t paging_find_pages(uint32_t count);
-
-uint32_t paging_alloc_pages(uint32_t count);
-
-uint32_t paging_get_used_pages();
+#define EMPTY_TAB ((struct page_table *)0x00000002)
+#define PAGE_S 0x400000
 
 #endif
diff --git a/src/kernel/system.c b/src/kernel/system.c
index f2e3d55..18fbaf4 100644
--- a/src/kernel/system.c
+++ b/src/kernel/system.c
@@ -121,7 +121,7 @@ loop:
 
 void v86(uint8_t code, regs16_t *regs)
 {
-	paging_disable();
+	/* paging_disable(); */
 	int32(code, regs);
-	paging_enable();
-}
\ No newline at end of file
+	/* paging_enable(); */
+}
-- 
cgit v1.2.3