Microkernel thing OS experiment (Zig ⚡)
1pub fn ControlRegister(comptime T: type, comptime reg: []const u8) type {
2 return struct {
3 pub fn read() T {
4 return asm volatile ("mov %%" ++ reg ++ ", %[output]"
5 : [output] "=r" (-> T),
6 );
7 }
8
9 pub fn write(value: T) void {
10 asm volatile ("mov %[input], %%" ++ reg
11 :
12 : [input] "r" (value),
13 );
14 }
15 };
16}
17
18pub fn GeneralPurpose(comptime T: type, comptime reg: []const u8) type {
19 return struct {
20 pub fn read() T {
21 return asm volatile ("mov %%" ++ reg ++ ", %[output]"
22 : [output] "=r" (-> T),
23 );
24 }
25
26 pub fn write(value: T) void {
27 asm volatile ("mov %[input], %%" ++ reg
28 :
29 : [input] "r" (value),
30 );
31 }
32 };
33}
34
35pub inline fn readMSR(comptime T: type, num: u32) T {
36 return switch (@bitSizeOf(T)) {
37 32 => @bitCast(asm volatile ("rdmsr"
38 : [_] "={eax}" (-> u32),
39 : [_] "{ecx}" (num),
40 )),
41 64 => blk: {
42 var low_val: u32 = undefined;
43 var high_val: u32 = undefined;
44 asm volatile ("rdmsr"
45 : [_] "={eax}" (low_val),
46 [_] "={edx}" (high_val),
47 : [_] "{ecx}" (num),
48 );
49 const combined_val = (@as(u64, high_val) << 32) | @as(u64, low_val);
50 break :blk @as(T, combined_val);
51 },
52 else => @compileError("Unimplemented for type of this size"),
53 };
54}
55
56pub inline fn writeMSR(comptime T: type, num: u32, val: T) void {
57 switch (@bitSizeOf(T)) {
58 32 => asm volatile ("wrmsr"
59 :
60 : [_] "{eax}" (val),
61 [_] "{edx}" (@as(u32, 0)),
62 [_] "{ecx}" (num),
63 ),
64 64 => {
65 const low_val: u32 = @truncate(@as(u64, val));
66 const high_val: u32 = @truncate(@as(u64, val >> 32));
67 asm volatile ("wrmsr"
68 :
69 : [_] "{eax}" (low_val),
70 [_] "{edx}" (high_val),
71 [_] "{ecx}" (num),
72 );
73 },
74 else => @compileError("Unimplemented for type of this size"),
75 }
76}
77
78pub fn MSR(comptime T: type, comptime num: u32) type {
79 return struct {
80 pub fn read() T {
81 return readMSR(T, num);
82 }
83 pub fn write(val: T) void {
84 writeMSR(T, num, val);
85 }
86 };
87}
88
89pub const ControlRegisters = struct {
90 pub const Cr0 = ControlRegister(u64, "cr0");
91 pub const Cr2 = ControlRegister(u64, "cr2");
92 pub const Cr3 = ControlRegister(u64, "cr3");
93 pub const Cr4 = ControlRegister(u64, "cr4");
94};
95
96pub const Segmentation = struct {
97 pub const Cs = GeneralPurpose(u16, "cs");
98 pub const Ds = GeneralPurpose(u16, "ds");
99 pub const Ss = GeneralPurpose(u16, "ss");
100 pub const Es = GeneralPurpose(u16, "es");
101 pub const Fs = GeneralPurpose(u16, "fs");
102 pub const Gs = GeneralPurpose(u16, "gs");
103};