GDT finally works
This commit is contained in:
19
kernel/hal/hal.h
Normal file
19
kernel/hal/hal.h
Normal 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
9
kernel/hal/util.c
Normal 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
6
kernel/hal/util.h
Normal 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
94
kernel/hal/x86_64/gdt.c
Normal 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
6
kernel/hal/x86_64/gdt.h
Normal 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
21
kernel/hal/x86_64/hal.c
Normal 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
9
kernel/hal/x86_64/intr.S
Normal file
@ -0,0 +1,9 @@
|
||||
.global hal_intr_enable
|
||||
hal_intr_enable:
|
||||
sti
|
||||
ret
|
||||
|
||||
.global hal_intr_disable
|
||||
hal_intr_disable:
|
||||
cli
|
||||
ret
|
50
kernel/hal/x86_64/serial.c
Normal file
50
kernel/hal/x86_64/serial.c
Normal 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);
|
||||
}
|
8
kernel/hal/x86_64/serial.h
Normal file
8
kernel/hal/x86_64/serial.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef HAL_SERIAL_H_
|
||||
#define HAL_SERIAL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool serial_init(void);
|
||||
|
||||
#endif // HAL_SERIAL_H_
|
13
kernel/hal/x86_64/serial1.S
Normal file
13
kernel/hal/x86_64/serial1.S
Normal 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
|
Reference in New Issue
Block a user