GDT finally works

This commit is contained in:
2025-08-10 21:29:16 +02:00
parent f8f00cc608
commit 8ee1ea1292
36 changed files with 868 additions and 206 deletions

19
kernel/hal/hal.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef KERNEL_HAL_HAL_H_
#define KERNEL_HAL_HAL_H_
#include <stdint.h>
#include "util.h"
__attribute__((noreturn)) void hal_hang(void);
void hal_init(void);
void hal_intr_disable(void);
void hal_intr_enable(void);
void hal_memset(void *mem, uint8_t v, uint32_t size);
#if defined(__x86_64__)
# define HAL_PAGE_SIZE 0x1000
#endif
#endif // KERNEL_HAL_HAL_H_

9
kernel/hal/util.c Normal file
View File

@ -0,0 +1,9 @@
#include <stdint.h>
#include "hal.h"
void hal_memset(void *mem, uint8_t v, uint32_t size) {
uint8_t *mem1 = mem;
for (uint32_t i = 0; i < size; i++) {
mem1[i] = v;
}
}

6
kernel/hal/util.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef HAL_UTIL_H_
#define HAL_UTIL_H_
#define HAL_MEMSET(m, v, n) hal_memset((void *)(m), (v), (n))
#endif // HAL_UTIL_H_

94
kernel/hal/x86_64/gdt.c Normal file
View File

@ -0,0 +1,94 @@
#include <stdint.h>
#include <stddef.h>
#include "compiler/attr.h"
#include "hal/hal.h"
#define GDT_SIZE 5
typedef struct {
uint16_t limitlow;
uint16_t baselow;
uint8_t basemid;
uint8_t access;
uint8_t gran;
uint8_t basehigh;
} PACKED GdtEntry;
typedef struct {
uint16_t limit;
uint64_t base;
} PACKED GdtPtr;
typedef struct {
GdtEntry old[5];
GdtEntry tsslow;
GdtEntry tsshigh;
} PACKED ExtendedGdt;
typedef struct {
uint32_t resv0;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t resv1;
uint64_t ist[7];
uint64_t resv2;
uint16_t resv3;
uint16_t iopb_off;
} PACKED Tss;
static Tss tss = {0};
static ExtendedGdt *curgdt = NULL;
#define KCODE 0x08
#define KDATA 0x10
#define UCODE 0x18
#define UDATA 0x20
#define TSS 0x28
#define GDT_PRESENT 0x80
#define GDT_TSS 0x89
static uint64_t gdt_curretbase(void) {
GdtPtr gdtr;
asm volatile("sgdt %0" : "=m"(gdtr));
return gdtr.base;
}
void gdt_setenty(GdtEntry *entry, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
entry->baselow = base & 0xffff;
entry->basemid = (base >> 16) & 0xff;
entry->basehigh = (base >> 24) & 0xff;
entry->limitlow = limit & 0xffff;
entry->gran = (limit >> 16) & 0x0f | (gran & 0xf0);
entry->access = access;
}
void gdt_init(void) {
uint64_t base = gdt_curretbase();
curgdt = (ExtendedGdt *)base;
HAL_MEMSET(&tss, 0, sizeof(tss));
tss.iopb_off = sizeof(tss);
uint64_t tss_base = (uint64_t)&tss;
uint32_t tss_limit = sizeof(tss) - 1;
gdt_setenty(&curgdt->tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0);
GdtEntry *tsshigh = &curgdt->tsshigh;
tsshigh->baselow = (tss_base >> 32) & 0xffff;
tsshigh->basemid = (tss_base >> 48) & 0xff;
tsshigh->basehigh = (tss_base >> 56) & 0xff;
tsshigh->access = 0;
tsshigh->gran = 0;
tsshigh->limitlow = 0;
GdtPtr gdtr;
asm volatile("sgdt %0" : "=m"(gdtr));
gdtr.limit = sizeof(ExtendedGdt) - 1;
asm volatile("lgdt %0" :: "m"(gdtr));
asm volatile("ltr %0" :: "r"((uint16_t)0x28));
}

6
kernel/hal/x86_64/gdt.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef HAL_GDT_H_
#define HAL_GDT_H_
void gdt_init(void);
#endif // HAL_GDT_H_

21
kernel/hal/x86_64/hal.c Normal file
View File

@ -0,0 +1,21 @@
#include <stdint.h>
#include <stdbool.h>
#include "hal/hal.h"
#include "kprintf.h"
#include "serial.h"
#include "gdt.h"
void hal_init(void) {
if (!serial_init()) {
hal_hang(); // going further makes no sense
}
LOG("hal", "serial init\n");
gdt_init();
}
__attribute__((noreturn)) void hal_hang(void) {
for(;;) {
asm("hlt");
}
}

9
kernel/hal/x86_64/intr.S Normal file
View File

@ -0,0 +1,9 @@
.global hal_intr_enable
hal_intr_enable:
sti
ret
.global hal_intr_disable
hal_intr_disable:
cli
ret

View File

@ -0,0 +1,50 @@
#include <stdint.h>
#include <stdbool.h>
#define SERIAL_PORT 0x3f8
extern uint8_t serial_inb(uint16_t port);
extern void serial_outb(uint16_t port, uint8_t value);
static int serial_received(void) {
return serial_inb(SERIAL_PORT + 5) & 1;
}
static uint8_t serial_read(void) {
while (serial_received() == 0);
return serial_inb(SERIAL_PORT);
}
static int serial_trans_empty(void) {
return serial_inb(SERIAL_PORT + 5) & 0x20;
}
static void serial_write(uint8_t value) {
while (!serial_trans_empty());
serial_outb(SERIAL_PORT, value);
}
// REFERENCE: https://wiki.osdev.org/Serial_Ports
bool serial_init(void) {
serial_outb(SERIAL_PORT + 1, 0x00);
serial_outb(SERIAL_PORT + 3, 0x80);
serial_outb(SERIAL_PORT + 0, 0x03);
serial_outb(SERIAL_PORT + 1, 0x00);
serial_outb(SERIAL_PORT + 3, 0x03);
serial_outb(SERIAL_PORT + 2, 0xc7);
serial_outb(SERIAL_PORT + 4, 0x0b);
serial_outb(SERIAL_PORT + 4, 0x1e);
serial_outb(SERIAL_PORT + 0, 0xae);
if (serial_inb(SERIAL_PORT + 0) != 0xae) {
return false;
}
serial_outb(SERIAL_PORT + 4, 0x0f);
return true;
}
// For printf library
void putchar_(char c) {
serial_write(c);
}

View File

@ -0,0 +1,8 @@
#ifndef HAL_SERIAL_H_
#define HAL_SERIAL_H_
#include <stdbool.h>
bool serial_init(void);
#endif // HAL_SERIAL_H_

View File

@ -0,0 +1,13 @@
.global serial_outb
serial_outb:
mov %di, %dx
mov %sil, %al
out %al, %dx
ret
.global serial_inb
serial_inb:
mov %di, %dx
in %dx, %al
movzx %al, %rax
ret