aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/memory/mmap.c
blob: 2e4821df7fa28cf9219c87ac2fe8b98b53560079 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <memory/mmap.h>
#include <stddef.h>
#include <stdint.h>
#include <system.h>

#define FRAME_SIZE 0x1000
#define FRAME_COUNT (total_memory / 4)
#define FRAME_TABLE_SIZE (FRAME_COUNT / 32)

#define FREE 0x0
#define USED 0x1

void *kmalloc(u32 size);

extern u32 kernel_end;
u32 kernel_end_address = (u32)&kernel_end;

u32 total_memory;

u32 *frame_table;

// Not to be used externally!
void *kmalloc(u32 size)
{
	void *ret;

	ret = (void *)kernel_end_address;
	kernel_end_address += size;

	return ret;
}

// TODO: Efficiency
void *kmalloc_frames(u32 num)
{
	u8 found;

	for (u32 i = 0; i < FRAME_COUNT; i++) {
		found = 1;
		for (u32 j = 0; j < num; j++) {
			if (mmap_index_check(i + j) == USED) {
				found = 0;
				break;
			}
		}
		if (found) {
			for (u32 j = 0; j < num; j++) {
				mmap_index_set_used(i + j);
			}
			return (void *)(i * FRAME_SIZE);
		}
	}

	warn("Not enough frames");
	return NULL;
}

void kfree_frames(void *ptr, u32 num)
{
	u32 address = (u32)ptr;
	u32 i = address;

	while (i < address + (num * FRAME_SIZE)) {
		mmap_address_set_free(address);
		i += FRAME_SIZE;
	}
}

u8 mmap_index_check(u32 n)
{
	return (frame_table[n / 32] >> (n % 32)) & 0x1;
}

void mmap_init(u32 size)
{
	total_memory = size;
	frame_table = kmalloc(FRAME_TABLE_SIZE);
}

void mmap_init_finalize()
{
	// TODO: Efficiency
	//memset(frame_table, 0xFF, (&kernel_end / FRAME_SIZE) / 8);
	for (u32 i = 0; i < kernel_end_address; i += FRAME_SIZE) {
		mmap_address_set_used(i);
	}
}

void mmap_address_set_free(u32 address)
{
	frame_table[(address / FRAME_SIZE) / 32] &= ~(1 << ((address / FRAME_SIZE) % 32));
}

void mmap_address_set_used(u32 address)
{
	frame_table[(address / FRAME_SIZE) / 32] |= (1 << ((address / FRAME_SIZE) % 32));
}

void mmap_index_set_free(u32 n)
{
	frame_table[n / 32] &= ~(1 << (n % 32));
}

void mmap_index_set_used(u32 n)
{
	frame_table[n / 32] |= 1 << (n % 32);
}