Skip to content

Commit

Permalink
Update GDT with TSS segment
Browse files Browse the repository at this point in the history
  • Loading branch information
Kfeavel committed Jun 17, 2021
1 parent 15c507e commit fa70a3c
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 15 deletions.
35 changes: 31 additions & 4 deletions kernel/arch/i386/gdt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,45 @@
#include <lib/stdio.hpp>
#include <dev/tty/tty.hpp>

#define GDT_NUM_ENTRIES 6

// Defined in the gdt_flush.s file.
extern "C" void gdt_flush(uintptr_t);
// Function declarations
void kernel_stack(uintptr_t stack);
void tss_set_gate(int32_t num, uint16_t ss0, uint32_t esp0);
void gdt_set_gate(uint8_t num, uint64_t base, uint64_t limit, uint16_t flags);
// Define our local variables
gdt_entry_t gdt_entries[5];
gdt_entry_t gdt_entries[GDT_NUM_ENTRIES];
gdt_ptr_t gdt_ptr;
tss_entry_t tss_entry;

void kernel_stack(uint32_t stack) {
// Update TSS kernel stack location
tss_entry.esp0 = stack;
}

void tss_set_gate(int32_t num, uint16_t ss0, uint32_t esp0) {
// Convert the TSS locations to GDT data
uintptr_t base = (uintptr_t)&tss_entry;
uintptr_t limit = base + sizeof(tss_entry);

// Ensure all values are zero
memset(&tss_entry, 0x0, sizeof(tss_entry));
// Update specific TSS register values
tss_entry.ss0 = ss0;
tss_entry.esp0 = esp0;
tss_entry.iomap_base = sizeof(tss_entry);

// Install the TSS in the last GDT location
gdt_set_gate(num, base, limit, SEG_PRES(1) | SEG_CODE_EXA | SEG_SIZE(1));
}

void gdt_set_gate(uint8_t num, uint64_t base, uint64_t limit, uint16_t flags) {
// 32-bit address space
// Now we have to squeeze the (32-bit) limit into 2.5 regiters (20-bit).
// This is done by discarding the 12 least significant bits, but this
// is only legal, if they are all ==1, so they are implicitly still there
// is only legal, if they are all == 1, so they are implicitly still there

// so if the last bits aren't all 1, we have to set them to 1, but this
// would increase the limit (cannot do that, because we might go beyond
Expand All @@ -50,18 +76,19 @@ void gdt_set_gate(uint8_t num, uint64_t base, uint64_t limit, uint16_t flags) {
memcpy(&gdt_entries[num], &descriptor, sizeof(uint64_t));
}

//gdt_flush((uintptr_t)gdtp);
void gdt_install() {
kprintf(DBG_INFO "Installing the GDT...\n");
gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
gdt_ptr.limit = sizeof(gdt_entries) - 1;
gdt_ptr.base = (uint32_t)&gdt_entries;

gdt_set_gate(0, 0, 0, 0); // Null segment
gdt_set_gate(1, 0, 0x000FFFFF, GDT_CODE_PL0); // Kernel code segment
gdt_set_gate(2, 0, 0x000FFFFF, GDT_DATA_PL0); // Kernel data segment
gdt_set_gate(3, 0, 0x000FFFFF, GDT_CODE_PL3); // User mode code segment
gdt_set_gate(4, 0, 0x000FFFFF, GDT_DATA_PL3); // User mode data segment
tss_set_gate(5, 0x10, 0x0); // TSS entry

gdt_flush((uint32_t)&gdt_ptr);
tss_flush();
kprintf(DBG_OKAY "Installed the GDT.\n");
}
1 change: 1 addition & 0 deletions sysroot/usr/include/kernel/arch/arch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ void parse_stivale2(void* info);
// Shared library code for i386+ & amd64 family
#include <cpuid.h>
#include <arch/i386/gdt.hpp>
#include <arch/i386/tss.hpp>
#include <arch/i386/idt.hpp>
#include <arch/i386/isr.hpp>
#include <arch/i386/timer.hpp>
Expand Down
22 changes: 11 additions & 11 deletions sysroot/usr/include/kernel/arch/i386/tss.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,6 @@

#include <stdint.h>

/**
* @brief This function is defined in flush.s (assembly) and is
* used to flush the TSS when we (re)load into the kernel or
* into userspace. The extern "C" syntax tells the compiler that
* our function is defined somewhere else and the "C" part tells
* the compiler to not string mangle our function and to instead
* look for a literal "tss_flush" function in assembly.
*
*/
extern "C" void tss_flush();

/**
* @brief The Task State Segment (TSS) is a special data structure for x86 processors
* which holds information about a task. The TSS is primarily suited for hardware
Expand Down Expand Up @@ -62,3 +51,14 @@ typedef struct tss_entry {
uint16_t trap;
uint16_t iomap_base;
} __attribute__ ((packed)) tss_entry_t;

/**
* @brief This function is defined in flush.s (assembly) and is
* used to flush the TSS when we (re)load into the kernel or
* into userspace. The extern "C" syntax tells the compiler that
* our function is defined somewhere else and the "C" part tells
* the compiler to not string mangle our function and to instead
* look for a literal "tss_flush" function in assembly.
*
*/
extern "C" void tss_flush();

0 comments on commit fa70a3c

Please sign in to comment.