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
|
//! Page Table Allocation
const common = @import("root").common;
const pmm = @import("../../pmm/pmm.zig");
const types = @import("../types/types.zig");
const walk = @import("walk.zig");
const paging = common.constants.paging;
const memory = common.constants.memory;
const AllocationError = common.errors.memory.AllocationError;
const Entry = types.Entry;
const Table = types.Table;
const Kagami = types.Kagami;
pub fn allocate_table() AllocationError!u64 {
const physical_address = try pmm.allocate_page_zeroed();
return physical_address;
}
pub fn free_table(physical_address: u64) void {
pmm.free_page(physical_address);
}
pub fn ensure_pdpt(kagami: *Kagami, virtual_address: u64) AllocationError!*Table {
const pml4 = walk.get_pml4(kagami.pml4_physical);
const pml4_index = paging.indices.extract_pml4_index(virtual_address);
const entry = pml4.get_entry(pml4_index);
if (entry.is_present()) {
return walk.get_table_from_physical(entry.get_physical_address());
}
const new_table_physical = try allocate_table();
kagami.add_table();
entry.* = Entry{
.present = true,
.writable = true,
.user_accessible = (pml4_index < 256),
};
entry.set_physical_address(new_table_physical);
return walk.get_table_from_physical(new_table_physical);
}
pub fn ensure_pd(kagami: *Kagami, pdpt: *Table, virtual_address: u64) AllocationError!*Table {
const pdpt_index = paging.indices.extract_pdpt_index(virtual_address);
const entry = pdpt.get_entry(pdpt_index);
if (entry.is_present()) {
return walk.get_table_from_physical(entry.get_physical_address());
}
const new_table_physical = try allocate_table();
kagami.add_table();
const pml4_index = paging.indices.extract_pml4_index(virtual_address);
entry.* = Entry{
.present = true,
.writable = true,
.user_accessible = (pml4_index < 256),
};
entry.set_physical_address(new_table_physical);
return walk.get_table_from_physical(new_table_physical);
}
pub fn ensure_pt(kagami: *Kagami, pd: *Table, virtual_address: u64) AllocationError!*Table {
const pd_index = paging.indices.extract_pd_index(virtual_address);
const entry = pd.get_entry(pd_index);
if (entry.is_present()) {
return walk.get_table_from_physical(entry.get_physical_address());
}
const new_table_physical = try allocate_table();
kagami.add_table();
const pml4_index = paging.indices.extract_pml4_index(virtual_address);
entry.* = Entry{
.present = true,
.writable = true,
.user_accessible = (pml4_index < 256),
};
entry.set_physical_address(new_table_physical);
return walk.get_table_from_physical(new_table_physical);
}
pub fn ensure_tables(kagami: *Kagami, virtual_address: u64) AllocationError!*Entry {
const pdpt = try ensure_pdpt(kagami, virtual_address);
const pd = try ensure_pd(kagami, pdpt, virtual_address);
const pt = try ensure_pt(kagami, pd, virtual_address);
const pt_index = paging.indices.extract_pt_index(virtual_address);
return pt.get_entry(pt_index);
}
|