summaryrefslogtreecommitdiff
path: root/src/stem/mem.c
blob: babe07990eb72bafd9eed937efe9870a6cff1b27 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "mem.h"
#include "sys.h"
#include "paging.h"
#include "heap.h"
#include "monitor.h"

#define FREEPAGESTOKEEP 5

#define KHEAP_IDXSIZE 0x1000
#define KHEAP_INITSIZE 0x8000
#define KHEAP_MAXSIZE 0x08000000

size_t mem_placementAddr;
static uint32_t kheap_working = 0;


// ******************************
// 									PAGE ALLOCATION
// 															****************************
static struct freepage {
   size_t virt, phys;
} freepages[FREEPAGESTOKEEP];
uint32_t freepagecount = 0;

static void get_free_pages() {
	static uint32_t locked = 0;
	uint32_t i;
	if (locked) return;
	locked = 1;
	while (freepagecount < FREEPAGESTOKEEP) {
		if (kheap_working) {
			for (i = 0xFFFFF000; i >= 0xF0000000; i -= 0x1000) {
				if (pagedir_getPage(kernel_pagedir, i, 1)->frame == 0) break;
			}
			freepages[freepagecount].virt = i;
			freepages[freepagecount].phys = frame_alloc() * 0x1000;
			page_map(pagedir_getPage(kernel_pagedir, i, 0), i, 0, 0);
		} else {
			if (mem_placementAddr & 0xFFFFF000) {
				mem_placementAddr &= 0xFFFFF000;
				mem_placementAddr += 0x1000;
			}
			freepages[freepagecount].virt = (size_t)kmalloc(0x1000);
			freepages[freepagecount].phys = freepages[freepagecount].virt - 0xE0000000;
			freepagecount++;
		}
	}
	locked = 0;
}

void* kmalloc_page(size_t *phys) {
	cli();
	get_free_pages();
	freepagecount--;
	*phys = freepages[freepagecount].phys;
	size_t tmp = freepages[freepagecount].virt;
	sti();
	return (void*)tmp;
}

void kfree_page(void* ptr) {
	size_t addr = (size_t)ptr;
	if (kheap_working) {		//With this we can know if paging works
		page_unmapFree(pagedir_getPage(kernel_pagedir, addr, 0));
	}
}

//***********************************
//										NORMAL MEMORY ALLOCATION
//																	*************************

static struct heap kheap;

void kheap_init() {
	heap_create(&kheap, (mem_placementAddr & 0xFFFFF000) + 0x1000, KHEAP_IDXSIZE, KHEAP_INITSIZE, KHEAP_MAXSIZE);
	kheap_working = 1;
	monitor_write("Kernel heap ok\n");
}

void* kmalloc(size_t size) {
	if (kheap_working) {
		return heap_alloc(&kheap, size);
	} else {
		size_t tmp = mem_placementAddr;
		mem_placementAddr += size;
		return (void*)tmp;
	}
}

void kfree(void* ptr) {
	if (kheap_working) {
		heap_free(&kheap, ptr);
	}
}