aboutsummaryrefslogtreecommitdiff
path: root/hikari/paging/types.zig
blob: 0cb512e83b54bdb51b2ff72509f23682091b5d61 (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
//! Hikari Paging Types

const constants = @import("constants.zig");

pub const PageTableEntry = packed struct(u64) {
    present: bool,
    writable: bool,
    user: bool,
    write_through: bool,
    cache_disable: bool,
    accessed: bool,
    dirty: bool,
    huge_page: bool,
    global: bool,
    available_low: u3,
    address_bits: u40,
    available_high: u11,
    no_execute: bool,

    pub fn empty() PageTableEntry {
        return @bitCast(@as(u64, 0));
    }

    pub fn from_address(address: u64, flags: u64) PageTableEntry {
        const entry: u64 = (address & constants.address_mask) | flags;
        return @bitCast(entry);
    }

    pub fn get_address(self: PageTableEntry) u64 {
        const raw: u64 = @bitCast(self);
        return raw & constants.address_mask;
    }

    pub fn is_present(self: PageTableEntry) bool {
        return self.present;
    }

    pub fn is_huge(self: PageTableEntry) bool {
        return self.huge_page;
    }

    pub fn to_raw(self: PageTableEntry) u64 {
        return @bitCast(self);
    }
};

pub const PageTable = struct {
    entries: [512]PageTableEntry,

    pub fn clear(self: *PageTable) void {
        for (&self.entries) |*entry| {
            entry.* = PageTableEntry.empty();
        }
    }

    pub fn get_entry(self: *PageTable, index: usize) *PageTableEntry {
        return &self.entries[index];
    }

    pub fn set_entry(self: *PageTable, index: usize, entry: PageTableEntry) void {
        self.entries[index] = entry;
    }
};

// Page table levels (L4 = top, L1 = bottom)
pub const TableL4 = PageTable; // PML4
pub const TableL3 = PageTable; // PDPT
pub const TableL2 = PageTable; // PD
pub const TableL1 = PageTable; // PT

pub fn get_l4_index(address: u64) usize {
    return @truncate((address >> constants.pml4_shift) & 0x1FF);
}

pub fn get_l3_index(address: u64) usize {
    return @truncate((address >> constants.pdpt_shift) & 0x1FF);
}

pub fn get_l2_index(address: u64) usize {
    return @truncate((address >> constants.pd_shift) & 0x1FF);
}

pub fn get_l1_index(address: u64) usize {
    return @truncate((address >> constants.pt_shift) & 0x1FF);
}

pub fn get_page_offset(address: u64) usize {
    return @truncate(address & 0xFFF);
}