aboutsummaryrefslogtreecommitdiff
path: root/hikari/asm/asm.zig
blob: 962fe60f76d5d7fe72430231f4ea2a68822bbccc (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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! Hikari Assembly Operations

pub inline fn read_cr3() u64 {
    return asm volatile ("mov %cr3, %[ret]"
        : [ret] "=r" (-> u64),
    );
}

pub inline fn write_cr3(value: u64) void {
    asm volatile ("mov %[value], %cr3"
        :
        : [value] "r" (value),
        : .{ .memory = true });
}

pub inline fn read_cr0() u64 {
    return asm volatile ("mov %cr0, %[ret]"
        : [ret] "=r" (-> u64),
    );
}

pub inline fn write_cr0(value: u64) void {
    asm volatile ("mov %[value], %cr0"
        :
        : [value] "r" (value),
    );
}

pub inline fn read_cr4() u64 {
    return asm volatile ("mov %cr4, %[ret]"
        : [ret] "=r" (-> u64),
    );
}

pub inline fn write_cr4(value: u64) void {
    asm volatile ("mov %[value], %cr4"
        :
        : [value] "r" (value),
    );
}

pub inline fn read_msr(msr: u32) u64 {
    var low: u32 = undefined;
    var high: u32 = undefined;
    asm volatile ("rdmsr"
        : [low] "={eax}" (low),
          [high] "={edx}" (high),
        : [msr] "{ecx}" (msr),
    );
    return (@as(u64, high) << 32) | low;
}

pub inline fn write_msr(msr: u32, value: u64) void {
    const low: u32 = @truncate(value);
    const high: u32 = @truncate(value >> 32);
    asm volatile ("wrmsr"
        :
        : [msr] "{ecx}" (msr),
          [low] "{eax}" (low),
          [high] "{edx}" (high),
    );
}

pub inline fn halt() noreturn {
    while (true) {
        asm volatile ("hlt");
    }
}

pub inline fn disable_interrupts() void {
    asm volatile ("cli");
}

pub inline fn enable_interrupts() void {
    asm volatile ("sti");
}

pub inline fn invlpg(address: u64) void {
    asm volatile ("invlpg (%[addr])"
        :
        : [addr] "r" (address),
        : .{ .memory = true });
}

pub inline fn flush_tlb() void {
    const cr3 = read_cr3();
    write_cr3(cr3);
}

pub const msr_efer: u32 = 0xC0000080;
pub const efer_sce: u64 = 1 << 0;
pub const efer_lme: u64 = 1 << 8;
pub const efer_lma: u64 = 1 << 10;
pub const efer_nxe: u64 = 1 << 11;

pub const cr0_pe: u64 = 1 << 0;
pub const cr0_mp: u64 = 1 << 1;
pub const cr0_em: u64 = 1 << 2;
pub const cr0_ts: u64 = 1 << 3;
pub const cr0_et: u64 = 1 << 4;
pub const cr0_ne: u64 = 1 << 5;
pub const cr0_wp: u64 = 1 << 16;
pub const cr0_am: u64 = 1 << 18;
pub const cr0_nw: u64 = 1 << 29;
pub const cr0_cd: u64 = 1 << 30;
pub const cr0_pg: u64 = 1 << 31;

pub const cr4_vme: u64 = 1 << 0;
pub const cr4_pvi: u64 = 1 << 1;
pub const cr4_tsd: u64 = 1 << 2;
pub const cr4_de: u64 = 1 << 3;
pub const cr4_pse: u64 = 1 << 4;
pub const cr4_pae: u64 = 1 << 5;
pub const cr4_mce: u64 = 1 << 6;
pub const cr4_pge: u64 = 1 << 7;
pub const cr4_pce: u64 = 1 << 8;
pub const cr4_osfxsr: u64 = 1 << 9;
pub const cr4_osxmmexcpt: u64 = 1 << 10;
pub const cr4_fsgsbase: u64 = 1 << 16;
pub const cr4_osxsave: u64 = 1 << 18;
pub const cr4_smep: u64 = 1 << 20;
pub const cr4_smap: u64 = 1 << 21;

pub fn jump_to_kernel(
    entry_point: u64,
    stack_top: u64,
    boot_params: u64,
    pml4_address: u64,
) noreturn {
    disable_interrupts();

    write_cr3(pml4_address);

    asm volatile (
        \\mov %[stack], %%rsp
        \\mov %[params], %%rdi
        \\xor %%rbp, %%rbp
        \\jmp *%[entry]
        :
        : [stack] "r" (stack_top),
          [params] "r" (boot_params),
          [entry] "r" (entry_point),
        : .{ .memory = true });

    unreachable;
}