diff options
Diffstat (limited to 'gdt.cpp')
-rw-r--r-- | gdt.cpp | 90 |
1 files changed, 89 insertions, 1 deletions
@@ -19,7 +19,21 @@ struct gdt_entry_bits { std::uint32_t base_high : 8; } __attribute__((packed)); -constinit static const std::array<gdt_entry_bits, 3> gdt {{ +struct TSSEntry +{ + std::uint32_t prevTSS; + std::uint32_t esp0; + std::uint32_t ss0; + std::uint32_t unused[23]; +} __attribute__((packed)); + +static TSSEntry tss = { + .prevTSS = 0, + .esp0 = 0, + .ss0 = 0x10 +}; + +static const std::array<gdt_entry_bits, 6> gdt {{ {}, /* kernel_code = */ { .limit_low = 0xFFFF, @@ -54,6 +68,57 @@ constinit static const std::array<gdt_entry_bits, 3> gdt {{ .big = 1, .gran = 1, .base_high = 0x00 + }, + /* user_code = */ { + .limit_low = 0xFFFF, + .base_low = 0x0000, + .accessed = 0, + .read_write = 1, + .conforming_expand_down = 0, + .code = 1, + .code_data_segment = 1, + .DPL = 3, + .present = 1, + .limit_high = 0xF, + .available = 0, + .long_mode = 0, + .big = 1, + .gran = 1, + .base_high = 0x00 + }, + /* user_data = */ { + .limit_low = 0xFFFF, + .base_low = 0x0000, + .accessed = 0, + .read_write = 1, + .conforming_expand_down = 0, + .code = 0, + .code_data_segment = 1, + .DPL = 3, + .present = 1, + .limit_high = 0xF, + .available = 0, + .long_mode = 0, + .big = 1, + .gran = 1, + .base_high = 0x00 + }, + /* tss = */ { + .limit_low = sizeof(TSSEntry), + .base_low = (std::uint32_t)&tss & 0xFFFFFF, + .accessed = 1, + .read_write = 0, + .conforming_expand_down = 0, + .code = 1, + .code_data_segment = 0, + .DPL = 0, + .present = 1, + .limit_high = 0, + .available = 0, + .long_mode = 0, + .big = 0, + .gran = 0, + .base_high = (std::uint32_t)&tss >> 24 } }}; @@ -76,6 +141,29 @@ void gdt_initialize() mov %%eax, %%fs mov %%eax, %%gs mov %%eax, %%ss + + mov $0x28, %%ax + ltr %%ax )" :: "m"(gdtr)); } +void enter_user_mode(void (*func)()) +{ + asm volatile("mov %%esp, %0" : "=r" (tss.esp0)); + + asm volatile(R"( + mov $0x23, %%ax + mov %%ax, %%ds + mov %%ax, %%es + mov %%ax, %%fs + mov %%ax, %%gs + mov %%esp, %%eax + push $0x23 + push %%esp + pushf + push $0x1b + push %0 + iret + )" :: "b"(func)); +} + |