From abaa007c5492a1b741da8639e7efe5b2a60f91cb Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Thu, 17 May 2018 01:39:47 -0700 Subject: [PATCH] Set TSS and load it --- src/kernel/interrupts.cpp | 56 +++++++++++++++++++++++++++++++++++++-- src/kernel/interrupts.s | 1 + 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/kernel/interrupts.cpp b/src/kernel/interrupts.cpp index 16e2a3c..18ae760 100644 --- a/src/kernel/interrupts.cpp +++ b/src/kernel/interrupts.cpp @@ -44,6 +44,30 @@ struct idt_descriptor uint32_t reserved; // must be zero } __attribute__ ((packed)); +struct tss_descriptor +{ + uint16_t limit_low; + uint16_t base_00; + uint8_t base_16; + gdt_type type; + uint8_t size; + uint8_t base_24; + uint32_t base_32; + uint32_t reserved; +} __attribute__ ((packed)); + +struct tss_entry +{ + uint32_t reserved0; + + uint64_t rsp[3]; // stack pointers for CPL 0-2 + uint64_t ist[8]; // ist[0] is reserved + + uint64_t reserved1; + uint16_t reserved2; + uint16_t iomap_offset; +}; + struct table_ptr { uint16_t limit; @@ -54,6 +78,7 @@ gdt_descriptor g_gdt_table[10]; idt_descriptor g_idt_table[256]; table_ptr g_gdtr; table_ptr g_idtr; +tss_entry g_tss; struct registers; @@ -61,7 +86,7 @@ extern "C" { void idt_write(); void idt_load(); - void gdt_write(uint16_t cs, uint16_t ds); + void gdt_write(uint16_t cs, uint16_t ds, uint16_t tr); void gdt_load(); void isr_handler(registers); @@ -116,6 +141,26 @@ set_gdt_entry(uint8_t i, uint32_t base, uint64_t limit, bool is64, gdt_type type g_gdt_table[i].type = type | gdt_type::system | gdt_type::present; } +void +set_tss_entry(uint8_t i, uint64_t base, uint64_t limit) +{ + tss_descriptor tssd; + tssd.limit_low = limit & 0xffff; + tssd.size = (limit >> 16) & 0xf; + + tssd.base_00 = base & 0xffff; + tssd.base_16 = (base >> 16) & 0xff; + tssd.base_24 = (base >> 24) & 0xff; + tssd.base_32 = (base >> 32) & 0xffffffff; + + tssd.type = + gdt_type::accessed | + gdt_type::execute | + gdt_type::ring3 | + gdt_type::present; + kutil::memcpy(&g_gdt_table[i], &tssd, sizeof(tss_descriptor)); +} + void set_idt_entry(uint8_t i, uint64_t addr, uint16_t selector, uint8_t flags) { @@ -173,7 +218,14 @@ interrupts_init() set_gdt_entry(3, 0, 0xfffff, true, gdt_type::ring3 | gdt_type::read_write | gdt_type::execute); set_gdt_entry(4, 0, 0xfffff, true, gdt_type::ring3 | gdt_type::read_write); - gdt_write(1 << 3, 2 << 3); + kutil::memset(&g_tss, 0, sizeof(tss_entry)); + addr_t tss_base = reinterpret_cast(&g_tss); + + // Note that this takes TWO GDT entries + set_tss_entry(6, tss_base, sizeof(tss_entry)); + // TODO: Set up TSS stack pointers! + + gdt_write(1 << 3, 2 << 3, 6 << 3); g_idtr.limit = sizeof(g_idt_table) - 1; g_idtr.base = reinterpret_cast(&g_idt_table); diff --git a/src/kernel/interrupts.s b/src/kernel/interrupts.s index ddc626f..34c3842 100644 --- a/src/kernel/interrupts.s +++ b/src/kernel/interrupts.s @@ -25,6 +25,7 @@ gdt_write: push rax o64 retf .next: + ltr dx ret global gdt_load