blob: d91abed5da86cde2017a2d44e4ebac4496056bf9 (
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
|
#include "gdt.h"
#include <cpu/arch_inst.h>
#include <interrupts.h>
extern void flush_tss(void);
extern void load_gdt(void *);
typedef struct tss_entry_struct tss_entry_t;
tss_entry_t tss_entry;
typedef union {
struct GDT_Entry s;
u64 raw;
} GDT_Entry;
GDT_Entry gdt_entries[6] = {0};
GDT_Pointer gdtr;
extern u32 inital_esp;
void write_tss(struct GDT_Entry *gdt_entry) {
u32 base = (u32)&tss_entry;
u32 limit = sizeof(tss_entry);
gdt_entry->limit_low = limit;
gdt_entry->base_low = base;
gdt_entry->accessed = 1;
gdt_entry->read_write = 0;
gdt_entry->conforming_expand_down = 0;
gdt_entry->code = 1;
gdt_entry->code_data_segment = 0;
gdt_entry->DPL = 0;
gdt_entry->present = 1;
gdt_entry->limit_high = limit >> 16;
gdt_entry->available = 0;
gdt_entry->long_mode = 0;
gdt_entry->big = 0;
gdt_entry->gran = 0;
gdt_entry->base_high = (base & ((u32)0xff << 24)) >> 24;
memset(&tss_entry, 0, sizeof tss_entry);
tss_entry.ss0 = GDT_KERNEL_DATA_SEGMENT * GDT_ENTRY_SIZE;
tss_entry.esp0 = get_current_sp();
}
void gdt_init() {
gdt_entries[GDT_NULL_SEGMENT].raw = 0x0;
gdt_entries[GDT_KERNEL_CODE_SEGMENT].raw =
0xCF9A000000FFFF; // Kernel code segment
gdt_entries[GDT_KERNEL_DATA_SEGMENT].raw =
0xCF92000000FFFF; // Kernel data segment
// Usermode code segment
memcpy(&gdt_entries[GDT_USERMODE_CODE_SEGMENT],
&gdt_entries[GDT_KERNEL_CODE_SEGMENT], GDT_ENTRY_SIZE);
// Usermode data segment
memcpy(&gdt_entries[GDT_USERMODE_DATA_SEGMENT],
&gdt_entries[GDT_KERNEL_DATA_SEGMENT], GDT_ENTRY_SIZE);
// Set DPL to 3 to indicate that the segment is in ring 3
gdt_entries[GDT_USERMODE_CODE_SEGMENT].s.DPL = 3;
gdt_entries[GDT_USERMODE_DATA_SEGMENT].s.DPL = 3;
write_tss((struct GDT_Entry *)&gdt_entries[GDT_TSS_SEGMENT]);
gdtr.offset = (u32)&gdt_entries;
gdtr.size = sizeof(gdt_entries) - 1;
disable_interrupts();
load_gdt(&gdtr);
flush_tss();
}
|