feat: gdt
This commit is contained in:
parent
14ab06110b
commit
65a0eb1cda
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <io/stream.h>
|
#include <io/stream.h>
|
||||||
|
|
||||||
void hal_setup(void);
|
Res hal_setup(void);
|
||||||
|
|
||||||
/* --- Assembly function --------------------------------------------------- */
|
/* --- 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 <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$();
|
||||||
}
|
}
|
|
@ -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 (;;)
|
||||||
;
|
;
|
||||||
}
|
}
|
Loading…
Reference in a new issue