aboutsummaryrefslogtreecommitdiff
path: root/mirai/kagami/tables/allocate.zig
blob: ee3f928aebf102cece805b03b8d0bf561a733208 (plain)
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);
}