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
108
109
110
111
112
113
114
115
116
117
|
#include <io/io.h>
#include <lib/lib.h>
#include <memory/alloc.h>
#include <memory/mmap.h>
#include <memory/paging.h>
#include <stdint.h>
#include <system.h>
struct page_dir *kernel_page_directory;
void paging_install()
{
memory_init();
struct page_table *page_table;
page_table = kmalloc_frames(1);
memset(page_table, 0, sizeof(struct page_table));
for (u32 i = 0; i < PAGE_COUNT; i++) {
page_table->entries[i].present = 1;
page_table->entries[i].writable = 1;
page_table->entries[i].address = SHIFT(i * PAGE_SIZE);
}
kernel_page_directory = kmalloc_frames(1);
memset(kernel_page_directory, 0, sizeof(struct page_dir));
kernel_page_directory->entries[0].present = 1;
kernel_page_directory->entries[0].writable = 1;
kernel_page_directory->entries[0].address = SHIFT((u32)page_table);
paging_switch_dir((u32)kernel_page_directory);
paging_enable();
info("Installed paging");
// Test mallocing
u32 *c = malloc(2048);
c[42] = 0x4242;
assert(c[42] == 0x4242);
free(c);
info("Malloc test succeeded!");
}
void paging_disable()
{
u32 cr0 = cr0_get();
cr0 &= 0x7fffffff;
cr0_set(cr0);
paging_enabled = 0;
}
void paging_enable()
{
u32 cr0 = cr0_get();
cr0 |= 0x80000000;
cr0_set(cr0);
paging_enabled = 1;
}
void paging_switch_dir(u32 dir)
{
cr3_set(dir);
}
struct page_table_entry *paging_get_page(u32 address, struct page_dir *page_dir)
{
struct page_table *page_table;
address /= PAGE_SIZE;
u32 n = address / PAGE_COUNT;
if (page_dir->entries[n].present == 0) {
page_table = kmalloc_frames(1);
memset(page_table, 0, sizeof(struct page_table));
page_dir->entries[n].address = SHIFT((u32)page_table);
page_dir->entries[n].present = 1;
page_dir->entries[n].writable = 1;
page_dir->entries[n].user = 1;
} else {
page_table = (void *)UNSHIFT(page_dir->entries[n].address);
}
return &page_table->entries[address % PAGE_COUNT];
}
void paging_frame_alloc(struct page_table_entry *page)
{
void *ptr = kmalloc_frames(1);
if (page->address != 0) {
warn("Page is already allocated");
return;
}
page->address = SHIFT((u32)ptr);
page->present = 1;
page->user = 1;
}
void paging_frame_free(struct page_table_entry *page)
{
kfree_frames((void *)UNSHIFT(page->address), 1);
memset((void *)page, 0, sizeof(struct page_table_entry));
}
struct page_dir *paging_make_dir()
{
struct page_dir *ret = kmalloc_frames(1);
memcpy(ret, kernel_page_directory, sizeof(struct page_dir));
return ret;
}
void paging_free_dir(struct page_dir *page_dir)
{
kfree_frames(page_dir, 1);
}
|