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
|
//! Global Descriptor Table
const cpu = @import("../../asm/cpu.zig");
const gdt_const = @import("../../common/constants/gdt.zig");
const io = @import("../../asm/io.zig");
const ports = @import("../../common/constants/ports.zig");
const serial = @import("../../drivers/serial/serial.zig");
const tss = @import("../tss/tss.zig");
const types = @import("types.zig");
pub const KERNEL_CODE = gdt_const.KERNEL_CODE;
pub const KERNEL_DATA = gdt_const.KERNEL_DATA;
pub const USER_DATA = gdt_const.USER_DATA;
pub const USER_CODE = gdt_const.USER_CODE;
pub const TSS_SEGMENT = gdt_const.TSS_SEGMENT;
var gdt: [8]u64 align(16) = undefined;
var gdt_ptr: types.Pointer = undefined;
pub fn init() void {
gdt[0] = 0;
gdt[1] = create_code_descriptor(0, true);
gdt[2] = create_data_descriptor(0);
gdt[3] = create_data_descriptor(3);
gdt[4] = create_code_descriptor(3, true);
create_tss_descriptor(tss.get_address(), tss.get_size());
gdt_ptr = types.Pointer{
.limit = @sizeOf(@TypeOf(gdt)) - 1,
.base = @intFromPtr(&gdt),
};
cpu.load_global_descriptor_table(@intFromPtr(&gdt_ptr));
cpu.reload_segment_registers(KERNEL_DATA);
cpu.reload_code_segment(KERNEL_CODE);
cpu.load_task_register(TSS_SEGMENT);
io.out_byte(ports.PIC1_DATA, 0xFF);
io.out_byte(ports.PIC2_DATA, 0xFF);
serial.printf("GDT: code={x} data={x} ucode={x} udata={x} tss={x}\n", .{
KERNEL_CODE, KERNEL_DATA, USER_CODE, USER_DATA, TSS_SEGMENT,
});
}
fn create_code_descriptor(dpl: u8, long_mode: bool) u64 {
var desc: u64 = 0;
desc |= 0xFFFF;
desc |= (@as(u64, 0xF) << 48);
var access: u8 = 0;
access |= (1 << 0);
access |= (1 << 1);
access |= (1 << 3);
access |= (1 << 4);
access |= (@as(u8, dpl & 0x3) << 5);
access |= (1 << 7);
desc |= (@as(u64, access) << 40);
var flags: u8 = 0;
flags |= (1 << 3);
if (long_mode) {
flags |= (1 << 1);
} else {
flags |= (1 << 2);
}
desc |= (@as(u64, flags) << 52);
return desc;
}
fn create_data_descriptor(dpl: u8) u64 {
var desc: u64 = 0;
desc |= 0xFFFF;
desc |= (@as(u64, 0xF) << 48);
var access: u8 = 0;
access |= (1 << 0);
access |= (1 << 1);
access |= (1 << 4);
access |= (@as(u8, dpl & 0x3) << 5);
access |= (1 << 7);
desc |= (@as(u64, access) << 40);
var flags: u8 = 0;
flags |= (1 << 3);
flags |= (1 << 2);
desc |= (@as(u64, flags) << 52);
return desc;
}
fn create_tss_descriptor(base: u64, limit: u64) void {
var desc_low: u64 = 0;
desc_low |= (limit & 0xFFFF);
desc_low |= ((base & 0xFFFF) << 16);
desc_low |= ((base & 0xFF0000) >> 16) << 32;
desc_low |= (@as(u64, 0x89) << 40);
desc_low |= (((limit >> 16) & 0xF) << 48);
desc_low |= (((base & 0xFF000000) >> 24) << 56);
gdt[5] = desc_low;
gdt[6] = (base >> 32) & 0xFFFFFFFF;
}
|