From 94ac0609d84e05fd3334a2280ed8c950bc948274 Mon Sep 17 00:00:00 2001 From: Baptiste Wicht Date: Sat, 18 Jan 2014 23:39:27 +0100 Subject: [PATCH] Prepare Task State Segment --- kernel/include/gdt.hpp | 44 +++++++++++++++++++++++++++++++++++++ kernel/src/boot/boot_16.cpp | 40 +++++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/kernel/include/gdt.hpp b/kernel/include/gdt.hpp index 550f139e..5162e8c5 100644 --- a/kernel/include/gdt.hpp +++ b/kernel/include/gdt.hpp @@ -15,6 +15,50 @@ constexpr const uint16_t DATA_SELECTOR = 0x10; constexpr const uint16_t LONG_SELECTOR = 0x18; constexpr const uint16_t USER_DATA_SELECTOR = 0x20; constexpr const uint16_t USER_CODE_SELECTOR = 0x28; +constexpr const uint16_t TSS_SELECTOR = 0x30; + +struct gdt_ptr { + uint16_t length; + uint32_t pointer; +} __attribute__ ((packed)); + +struct tss_descriptor_t { + uint16_t limit_low : 16; + uint32_t base_low : 24; + uint8_t type : 4; + uint8_t always_0_1 : 1; + uint8_t dpl : 2; + uint8_t present : 1; + uint8_t limit_high : 4; + uint8_t avl : 1; + uint8_t always_0_2 : 2; + uint8_t granularity : 1; + uint8_t base_middle : 8; + uint32_t base_high : 32; + uint8_t reserved_1 : 8; + uint8_t always_0_3 : 5; + uint32_t reserved_2 : 19; +} __attribute__((packed)); + +static_assert(sizeof(tss_descriptor_t) == 16, "TSS descriptor in long mode is 128 bits long"); + +struct task_state_segment_t { + uint32_t reserved_0; + uint64_t rsp0; + uint64_t rsp1; + uint64_t rsp2; + uint64_t reserved_1; + uint64_t ist1; + uint64_t ist2; + uint64_t ist3; + uint64_t ist4; + uint64_t ist5; + uint64_t ist6; + uint64_t ist7; + uint64_t reserved_2; + uint16_t reserved_3; + uint16_t io_map_base_address; +}; } //end of namespace gdt diff --git a/kernel/src/boot/boot_16.cpp b/kernel/src/boot/boot_16.cpp index 10ef9553..2bff0236 100644 --- a/kernel/src/boot/boot_16.cpp +++ b/kernel/src/boot/boot_16.cpp @@ -32,6 +32,8 @@ constexpr const uint16_t DEFAULT_BPP = 32; } //end of anonymous namespace +#include "gdt.hpp" + #define CODE_16 #include "e820.hpp" //Just for the address of the e820 map @@ -46,11 +48,6 @@ bool vesa::vesa_enabled = false; namespace { -struct gdt_ptr { - uint16_t length; - uint32_t pointer; -} __attribute__ ((packed)); - void out_byte(uint8_t value, uint16_t port){ __asm__ __volatile__("out %1, %0" : : "a" (value), "dN" (port)); } @@ -238,7 +235,7 @@ void enable_a20_gate(){ } void setup_idt(){ - static const gdt_ptr null_idt = {0, 0}; + static const gdt::gdt_ptr null_idt = {0, 0}; asm volatile("lidt %0" : : "m" (null_idt)); } @@ -338,17 +335,42 @@ constexpr uint16_t user_code_64_selector(){ } void setup_gdt(){ + //The Task State Segment + static gdt::task_state_segment_t tss; + //TODO On some machines, this should be aligned to 16 bits - static const uint64_t gdt[] = { + static uint64_t gdt[] = { 0, //Null Selector gdt_entry(0, 0xFFFFF, code_32_selector()), gdt_entry(0, 0xFFFFF, data_selector()), gdt_entry(0, 0xFFFFF, code_64_selector()), gdt_entry(0, 0xFFFFF, user_data_selector()), - gdt_entry(0, 0xFFFFF, user_code_64_selector()) + gdt_entry(0, 0xFFFFF, user_code_64_selector()), + 0, //Make space for TSS selector + 0 //Make space for TSS selector }; - static gdt_ptr gdtr; + uint32_t base = reinterpret_cast(&tss); + uint32_t limit = base + sizeof(gdt::task_state_segment_t); + + auto tss_selector = reinterpret_cast(&gdt[6]); + tss_selector->type = 9; //64bit TSS (Available) + tss_selector->always_0_1 = 0; + tss_selector->always_0_2 = 0; + tss_selector->always_0_3 = 0; + tss_selector->dpl = 3; + tss_selector->present = 1; + tss_selector->avl = 0; + tss_selector->granularity = 0; + + tss_selector->base_low = base & 0xFFFFFF; //Bottom 24 bits + tss_selector->base_middle = (base & 0xFF000000) >> 24; //Top 8 bits + tss_selector->base_high = 0; //Top 32 bits are clear + + tss_selector->limit_low = limit & 0xFFFF; //Low 16 bits + tss_selector->limit_high = (limit&0xF0000) >> 16; //Top 4 bits + + static gdt::gdt_ptr gdtr; gdtr.length = sizeof(gdt) - 1; gdtr.pointer = reinterpret_cast(&gdt);