Load our own GDT.
Replace the GDT from limine with our own.
This commit is contained in:
parent
872e6f3392
commit
03fe4d8c2e
|
@ -1,2 +1,2 @@
|
|||
#! /bin/bash
|
||||
cmake -B builddbg/ -G Ninja -D CMAKE_CXX_COMPILER=x86_64-elf-gcc -D CMAKE_ASM-ATT_COMPILER=x86_64-elf-as -D CMAKE_BUILD_TYPE=Debug
|
||||
cmake -B builddbg/ -G Ninja -D CMAKE_CXX_COMPILER=x86_64-elf-gcc -D CMAKE_ASM-ATT_COMPILER=x86_64-elf-gcc -D CMAKE_BUILD_TYPE=Debug
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
add_executable(zion
|
||||
common/gdt.cpp
|
||||
common/load_gdt.s
|
||||
debug/debug.cpp
|
||||
zion.cpp)
|
||||
|
||||
|
@ -7,20 +9,14 @@ target_include_directories(zion
|
|||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
# -c -- Don't run the linker.
|
||||
# -c -- Don't run the linker (only necessary for the assembler)
|
||||
# -ffreestanding
|
||||
# -nostdlib -- Don't include the standard library.
|
||||
# -mabi=sysv -- Explicitly specify the ABI since we will rely on it.
|
||||
# -mno-red-zone -- Don't put data below the stack pointer (clobbered by interrupts).
|
||||
# -mcmodel=kernel -- Assume the kernel code is running in the higher half.
|
||||
# -mgeneral-regs-only -- Prevent GCC from using a whole host of nonsense registers (that we have to enable).
|
||||
# Hopefully preceded by -mgeneral-regs-only
|
||||
# -mno-80387
|
||||
# -mno-mmx
|
||||
# -mno-3dnow
|
||||
# -mno-sse -mno-sse2
|
||||
# -MMD -- Something with the preprocessor?
|
||||
set(_Z_COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -nostdlib -mabi=sysv -mno-red-zone -mcmodel=kernel -mgeneral-regs-only")
|
||||
# -mno-80387 -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -MMD
|
||||
set(_Z_COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -c -ffreestanding -nostdlib -mabi=sysv -mno-red-zone -mcmodel=kernel -mgeneral-regs-only")
|
||||
|
||||
set(_Z_LINK_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld")
|
||||
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
#include "common/gdt.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GDT_ACCESSED 1
|
||||
#define GDT_READ_WRITE (1 << 1)
|
||||
#define GDT_EXECUTABLE (1 << 3)
|
||||
#define GDT_SEGMENT (1 << 4)
|
||||
#define GDT_RING3 (3 << 5)
|
||||
#define GDT_PRESENT (1 << 7)
|
||||
|
||||
#define GDT_FLAGS (1 << 7) | (1 << 5) // 4K granularity | long mode
|
||||
|
||||
struct TaskStateSegment {
|
||||
uint32_t reserved = 0;
|
||||
uint64_t rsp0 = 0;
|
||||
uint64_t rsp1 = 0;
|
||||
uint64_t rsp2 = 0;
|
||||
uint64_t reserved2 = 0;
|
||||
uint64_t ist1 = 0;
|
||||
uint64_t ist2 = 0;
|
||||
uint64_t ist3 = 0;
|
||||
uint64_t ist4 = 0;
|
||||
uint64_t ist5 = 0;
|
||||
uint64_t ist6 = 0;
|
||||
uint64_t ist7 = 0;
|
||||
uint64_t reserved3 = 0;
|
||||
uint16_t reserved4 = 0;
|
||||
uint16_t iomap_base = 0;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct GdtPointer {
|
||||
uint16_t size;
|
||||
uint64_t base;
|
||||
} __attribute__((packed));
|
||||
|
||||
static uint64_t gGdtSegments[7];
|
||||
static TaskStateSegment gTaskStateSegment;
|
||||
|
||||
// Defined in load_gdt.s
|
||||
extern "C" void ReloadSegments();
|
||||
|
||||
uint64_t CreateSegment(uint64_t access, uint64_t flags) {
|
||||
uint64_t base = 0;
|
||||
access &= 0xFF;
|
||||
flags &= 0xF0;
|
||||
flags |= 0xF; // For the highest 4 bits of the limit.
|
||||
// Lowest bits are the limit (always set to max);
|
||||
return (0xFFFF) | (access << 40) | (flags << 48);
|
||||
}
|
||||
|
||||
uint64_t CreateTssSegment(TaskStateSegment* tss) {
|
||||
uint64_t base = reinterpret_cast<uint64_t>(tss);
|
||||
uint64_t limit = sizeof(TaskStateSegment);
|
||||
uint64_t access = GDT_ACCESSED | GDT_PRESENT | GDT_EXECUTABLE;
|
||||
return limit | ((base & 0xFFFF) << 16) | ((base >> 16 & 0xFF) << 32) |
|
||||
(access << 40) | (((base >> 24) & 0xFF) << 56);
|
||||
}
|
||||
|
||||
void InitGdt() {
|
||||
gGdtSegments[0] = CreateSegment(0, 0);
|
||||
uint64_t default_bits = GDT_PRESENT | GDT_SEGMENT | GDT_READ_WRITE;
|
||||
|
||||
// Kernel CS
|
||||
gGdtSegments[1] = CreateSegment(default_bits | GDT_EXECUTABLE, GDT_FLAGS);
|
||||
|
||||
// Kernel DS
|
||||
gGdtSegments[2] = CreateSegment(default_bits, GDT_FLAGS);
|
||||
|
||||
// User CS
|
||||
gGdtSegments[3] =
|
||||
CreateSegment(default_bits | GDT_RING3 | GDT_EXECUTABLE, GDT_FLAGS);
|
||||
|
||||
// User DS
|
||||
gGdtSegments[4] = CreateSegment(default_bits | GDT_RING3, GDT_FLAGS);
|
||||
|
||||
gTaskStateSegment.iomap_base = sizeof(TaskStateSegment);
|
||||
gGdtSegments[5] = CreateTssSegment(&gTaskStateSegment);
|
||||
gGdtSegments[6] = reinterpret_cast<uint64_t>(&gTaskStateSegment) >> 32;
|
||||
|
||||
GdtPointer gdtp{
|
||||
.size = sizeof(gGdtSegments) - 1,
|
||||
.base = reinterpret_cast<uint64_t>(&gGdtSegments),
|
||||
};
|
||||
|
||||
asm volatile("lgdt %0" ::"m"(gdtp));
|
||||
ReloadSegments();
|
||||
asm volatile(
|
||||
"mov $0x28, %%ax;"
|
||||
"ltr %%ax;" ::
|
||||
: "rax");
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void InitGdt();
|
|
@ -0,0 +1,15 @@
|
|||
.global ReloadSegments
|
||||
ReloadSegments:
|
||||
push $0x08
|
||||
lea ._reload_cs, %rax
|
||||
push %rax
|
||||
retfq
|
||||
|
||||
._reload_cs:
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
ret
|
|
@ -1,9 +1,12 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "common/gdt.h"
|
||||
#include "debug/debug.h"
|
||||
|
||||
extern "C" void zion() {
|
||||
dbgln("Hello World!");
|
||||
InitGdt();
|
||||
dbgln("New GDT Loaded!");
|
||||
|
||||
while (1)
|
||||
;
|
||||
|
|
Loading…
Reference in New Issue