blob: 128de4e278e4e0f7cb1d0f336d428ae0e58eec19 [file] [log] [blame]
swissChili825d46b2021-02-21 10:14:16 -08001#include "paging.h"
2#include "io.h"
3#include "kint.h"
4#include "log.h"
5#include "pic.h"
6
7extern uint end;
8static size_t alloc_base = (size_t)&end;
9
10/* frames bitset, 0 = free, 1 = used */
11static uint *frames;
12static ulong num_frames;
13
14static uint first_page_table[1024] __attribute__((aligned(4096)));
15static uint *page_directory[1024] __attribute__((aligned(4096)));
16
17static uint ***current_directory;
18
19void *_kmalloc(size_t size, bool align, void **phys)
20{
21 if (align && (alloc_base & 0xfff)) // if not yet aligned
22 {
23 alloc_base &= ~0xfff;
24 alloc_base += 0x1000;
25 }
26
27 if (phys)
28 {
29 *phys = (void *)alloc_base;
30 }
31
32 size_t addr = alloc_base;
33 alloc_base += size;
34 return (void *)addr;
35}
36
37void *kmalloc(size_t size)
38{
39 return _kmalloc(size, false, NULL);
40}
41
42void *kmalloc_a(size_t size)
43{
44 return _kmalloc(size, true, NULL);
45}
46
47void *kmalloc_ap(size_t size, void **p)
48{
49 return _kmalloc(size, true, p);
50}
51
52/* frame utils */
53
54#define BITS 32
55
56static void set_frame(size_t frame_addr)
57{
58 uint frame = frame_addr / 0x1000; // page aligned
59 frames[frame / BITS] |= 1 << (frame % BITS);
60}
61
62static bool test_frame(size_t frame_addr)
63{
64 uint frame = frame_addr / 0x1000; // page aligned
65 return frames[frame / BITS] & 1 << (frame % BITS);
66}
67
68static void clear_frame(size_t frame_addr)
69{
70 uint frame = frame_addr / 0x1000; // page aligned
71 frames[frame / BITS] &= ~(1 << (frame % BITS));
72}
73
74static uint first_free_frame()
75{
76 for (int i = 0; i < num_frames / BITS; i++)
77 {
78 /*
79 * If there are any zeroes, ~ will yield a non-zero result,
80 * meaning that there are pages free. Otherwise, check next set
81 */
82 if (!~frames[i])
83 continue;
84
85 for (int j = 0; j < BITS; j++)
86 {
87 if ((frames[i] & 1 << j) == 0)
88 {
89 /* found unused frame */
90 return i * BITS + j;
91 }
92 }
93 }
94
95 /* did not find a free frame, panic */
96 kpanic("first_free_frame failed! no free frames");
97}
98
99void alloc_frame(uint *page, bool for_kernel, bool writable)
100{
101 if (*page >> 12)
102 return; /* frame already allocated */
103
104 uint frame = first_free_frame();
105 // kprintf("first_free_frame found %d\n", frame);
106 set_frame(frame * 0x1000); /* mark as mapped */
107}
108
109void free_frame(uint page)
110{
111 clear_frame(page / 0x1000);
112}
113
114/* paging stuff */
115
116void initialize_paging()
117{
118 for (int i = 0; i < 1024; i++)
119 {
120 page_directory[i] = (uint *) 0b010; // kernel, rw, not present
121 }
122
123 for (int i = 0; i < 1024; i++)
124 {
125 first_page_table[i] = (i * 0x1000) | 3;
126 }
127
128 page_directory[0] = (uint *) (((size_t) (uint *) first_page_table) | 3);
129
130 kprintf("Set up page directory[0], %x\n", (uint)first_page_table);
131
132 load_page_directory((uint) page_directory);
133 enable_paging();
134
135 add_interrupt_handler(14, page_fault);
136}
137
138void page_fault(struct registers *regs)
139{
140 kprintf("Page fault! eip = %d\n", regs->eip);
141 kpanic("Page fault");
142}