feat: gdt
This commit is contained in:
parent
14ab06110b
commit
65a0eb1cda
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <io/stream.h>
|
||||
|
||||
void hal_setup(void);
|
||||
Res hal_setup(void);
|
||||
|
||||
/* --- Assembly function --------------------------------------------------- */
|
||||
|
||||
|
|
81
src/kernel/archs/x86_64/gdt.c
Normal file
81
src/kernel/archs/x86_64/gdt.c
Normal 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");
|
||||
}
|
91
src/kernel/archs/x86_64/gdt.h
Normal file
91
src/kernel/archs/x86_64/gdt.h
Normal 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);
|
22
src/kernel/archs/x86_64/helper.s
Normal file
22
src/kernel/archs/x86_64/helper.s
Normal 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
|
|
@ -1,6 +1,9 @@
|
|||
#include <hal.h>
|
||||
#include <io/stream.h>
|
||||
#include <res.h>
|
||||
|
||||
#include "e9.h"
|
||||
#include "gdt.h"
|
||||
|
||||
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$();
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
#include <dbg/log.h>
|
||||
#include <hal.h>
|
||||
|
||||
_Noreturn int _start()
|
||||
{
|
||||
log$("Hello, world!");
|
||||
hal_setup();
|
||||
for (;;)
|
||||
;
|
||||
}
|
Loading…
Reference in a new issue