feat: gdt

This commit is contained in:
Jordan ⌨️ 2023-12-10 23:22:54 +01:00
parent 14ab06110b
commit 65a0eb1cda
6 changed files with 203 additions and 2 deletions

View file

@ -2,7 +2,7 @@
#include <io/stream.h> #include <io/stream.h>
void hal_setup(void); Res hal_setup(void);
/* --- Assembly function --------------------------------------------------- */ /* --- Assembly function --------------------------------------------------- */

View file

@ -0,0 +1,81 @@
#include <dbg/log.h>
#include <hal.h>
#include <string.h>
#include <sync/spinlock.h>
#include "gdt.h"
static Gdt gdt = {0};
static Spinlock lock = SPINLOCK_INIT;
static GdtDescriptor gdt_desc = {
.size = sizeof(gdt) - 1,
.offset = (uintptr_t)&gdt,
};
static void gdt_lazy_init(GdtEntry self[static 1], uint8_t access, uint8_t flags)
{
memset(self, 0, sizeof(GdtEntry));
if (access == 0 && flags == 0)
{
return;
}
self->access = access | GDT_ACCESS_PRESENT | GDT_ACCESS_READ_WRITE | GDT_ACCESS_DESCRIPTOR;
self->flags = flags | GDT_FLAGS_GRANULARITY;
self->base_high = 0;
self->base_middle = 0;
self->base_low = 0;
self->limit_low = 0xffff;
self->limit_high = 0x0f;
}
void gdt_load_tss(Tss *tss)
{
uintptr_t tss_ptr = (uintptr_t)tss;
spinlock_acquire(&lock);
gdt.tss_entry = (TssEntry){
.length = sizeof(TssEntry),
.base_low = tss_ptr & 0xffff,
.base_mid = (tss_ptr >> 16) & 0xff,
.base_high = (tss_ptr >> 24) & 0xff,
.base_upper = tss_ptr >> 32,
.flags1 = TSS_FLAGS_PRESENT | TSS_FLAGS_64BITS_AVAILABLE,
.flags2 = 0,
.reserved = 0,
};
spinlock_release(&lock);
}
uintptr_t gdt_descriptor(void)
{
return (uintptr_t)&gdt_desc;
}
void gdt_init(void)
{
gdt_lazy_init(&gdt.entries[GDT_NULL_DESC], 0, 0);
gdt_lazy_init(&gdt.entries[GDT_KERNEL_CODE], GDT_ACCESS_EXE, GDT_FLAGS_LONG_MODE);
gdt_lazy_init(&gdt.entries[GDT_KERNEL_DATA], 0, GDT_FLAGS_SIZE);
gdt_lazy_init(&gdt.entries[GDT_USER_DATA], GDT_ACCESS_USER, GDT_FLAGS_SIZE);
gdt_lazy_init(&gdt.entries[GDT_USER_CODE], GDT_ACCESS_USER | GDT_ACCESS_EXE, GDT_FLAGS_LONG_MODE);
gdt_load_tss(NULL);
gdt_flush(gdt_descriptor());
log$("GDT loaded");
tss_flush();
log$("TSS loaded");
}

View file

@ -0,0 +1,91 @@
#pragma once
#include <res.h>
#include <stdint.h>
enum gdtaccess : uint8_t
{
GDT_ACCESS_READ_WRITE = (1 << 1),
GDT_ACCESS_EXE = (1 << 3),
GDT_ACCESS_DESCRIPTOR = (1 << 4),
GDT_ACCESS_USER = (3 << 5),
GDT_ACCESS_PRESENT = (1 << 7),
};
enum gdtflags : uint8_t
{
GDT_FLAGS_LONG_MODE = (1 << 1),
GDT_FLAGS_SIZE = (1 << 2),
GDT_FLAGS_GRANULARITY = (1 << 3),
};
enum tssflags : uint8_t
{
TSS_FLAGS_PRESENT = (1 << 7),
TSS_FLAGS_64BITS_AVAILABLE = (0x9),
};
enum
{
GDT_NULL_DESC,
GDT_KERNEL_CODE,
GDT_KERNEL_DATA,
GDT_USER_DATA,
GDT_USER_CODE,
GDT_ENTRIES_LENGTH
};
typedef struct [[gnu::packed]]
{
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t limit_high : 4;
uint8_t flags : 4;
uint8_t base_high;
} GdtEntry;
typedef struct [[gnu::packed]]
{
uint16_t length;
uint16_t base_low;
uint8_t base_mid;
uint8_t flags1;
uint8_t flags2;
uint8_t base_high;
uint32_t base_upper;
uint32_t reserved;
} TssEntry;
typedef struct [[gnu::packed]]
{
uint32_t reserved;
uint64_t rsp[3];
uint64_t reserved0;
uint64_t ist[7];
uint32_t reserved1;
uint32_t reserved2;
uint16_t reserved3;
uint16_t iopb_offset;
} Tss;
typedef struct [[gnu::packed]]
{
uint16_t size;
uintptr_t offset;
} GdtDescriptor;
typedef struct [[gnu::packed]]
{
GdtEntry entries[GDT_ENTRIES_LENGTH];
TssEntry tss_entry;
} Gdt;
void gdt_init(void);
void gdt_load_tss(Tss *self);
uintptr_t gdt_descriptor(void);
extern void gdt_flush(uintptr_t);
extern void tss_flush(void);

View file

@ -0,0 +1,22 @@
.globl gdt_flush
.globl tss_flush
gdt_flush:
lgdt (%rdi)
mov $0x10, %ax
mov %ax, %ss
mov %ax, %ds
mov %ax, %es
pop %rdi
mov $0x08, %rax
push %rax
push %rdi
lretq
tss_flush:
mov $0x28, %ax
ltr %ax
ret

View file

@ -1,6 +1,9 @@
#include <hal.h>
#include <io/stream.h> #include <io/stream.h>
#include <res.h>
#include "e9.h" #include "e9.h"
#include "gdt.h"
Stream hal_dbg_stream(void) Stream hal_dbg_stream(void)
{ {
@ -9,6 +12,8 @@ Stream hal_dbg_stream(void)
}; };
} }
void hal_setup(void) Res hal_setup(void)
{ {
gdt_init();
return ok$();
} }

View file

@ -1,8 +1,10 @@
#include <dbg/log.h> #include <dbg/log.h>
#include <hal.h>
_Noreturn int _start() _Noreturn int _start()
{ {
log$("Hello, world!"); log$("Hello, world!");
hal_setup();
for (;;) for (;;)
; ;
} }