Prepare Task State Segment

This commit is contained in:
Baptiste Wicht 2014-01-18 23:39:27 +01:00
parent c48cbd2c65
commit 94ac0609d8
2 changed files with 75 additions and 9 deletions

View File

@ -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

View File

@ -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<uint32_t>(&tss);
uint32_t limit = base + sizeof(gdt::task_state_segment_t);
auto tss_selector = reinterpret_cast<gdt::tss_descriptor_t*>(&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<uint32_t>(&gdt);