GDT, page frame allocator

This commit is contained in:
Daniel Hammer
2025-02-27 19:48:03 +04:00
commit 6f1c6f1316
31 changed files with 2016 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
;
; gdt.asm
; Copyright (c) 2025 Daniel Hammer
;
[bits 64]
section .text ; Text/code section
global ReloadSegments
global LoadGDT
LoadGDT:
lgdt [rdi] ; Run LGDT on the contents of 1st C parameter
ret
ReloadSegments:
push 0x08 ; CS descriptor
lea rax, [rel .reload_CS]
push rax
retfq
.reload_CS:
mov ax, 0x10 ; DS descriptor
; ds, es, fs, gs, ss are segment registers on x86_64
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
+70
View File
@@ -0,0 +1,70 @@
/*
* gdt.hpp
*/
#include "GDT.hpp"
#include "../KernelTerminal/terminal.hpp"
// Limine loads a GDT of course, (CS = 0x28) but we will need to make a TSS someday... therefore we load our own now
namespace Hal {
using namespace Kt;
GDTPointer gdtPointer{};
BasicGDT kernelGDT{};
void PrepareGDT() {
kout << "[Hal] GDT at " << base::hex << (uint64_t)&kernelGDT << "\n";
kernelGDT = {
// Code segment offset 0x08
// Data segment offset 0x10
// Not sure if having LimitLow set to 0xFFFF for the Null segment is kosher
{0xFFFF, 0, 0, 0x00, 0x00, 0},
// Kernel code/data
{0xFFFF, 0, 0, 0x9A, 0xA0, 0},
{0xFFFF, 0, 0, 0x92, 0xA0, 0},
// User code/data
{0xFFFF, 0, 0, 0x9A, 0xA0, 0},
{0xFFFF, 0, 0, 0x92, 0xA0, 0},
// One day this will point to our actual TSS
{
// Limit = sizeof(TSS) - 1
0,
// Base = &TSS
0,
0,
// Access byte = 0xFA
0xFA,
// Granularity = 0x00
0x00,
0x0
}
};
gdtPointer = GDTPointer{
.Size = sizeof(kernelGDT) - 1,
.GDTAddress = (uint64_t)&kernelGDT
};
}
// Helpers implemented in gdt.asm
extern "C" void LoadGDT(GDTPointer *gdtPointer);
extern "C" void ReloadSegments();
void BridgeLoadGDT() {
// Puts the GDT pointer structure into the GDTR
kout << "[Hal] Setting GDTR" << Kt::newline;
LoadGDT(&gdtPointer);
kout << "[Hal] Reloading segments" << Kt::newline;
ReloadSegments();
}
};
+62
View File
@@ -0,0 +1,62 @@
/*
* gdt.hpp
* Copyright (c) 2025 Daniel Hammer
*/
#pragma once
#include <cstdint>
using namespace std;
// __attribute__((packed)) is the GCC extensions way of telling the compiler to ensure that it doesn't mess with these structures or add packing bytes
// for optimization because that would easily result in a triple fault.
namespace Hal {
class GDTEntry {
public:
// Base/Limit are obsolete in Long mode because segmentation is no longer used
// Sadly we must still build and load the GDT during kernel init
uint16_t LimitLow;
uint16_t BaseLow;
uint8_t BaseMiddle;
// Determine which processor rings this segment can be used in
uint8_t AccessByte;
// Lower 4 bits are the higher 4 bits of limit
uint8_t GranularityByte;
uint8_t BaseHigh;
// 16 + 16 + 8 + 8 = 48 bits
}__attribute__((packed));
struct BasicGDT {
// Conventionally the first entry of the GDT has all values zeroed out.
GDTEntry Null;
// Kernel code segment descriptor
GDTEntry KernelCode;
// Kernel data segment descriptor
GDTEntry KernelData;
// UM code segment descriptor
GDTEntry UserCode;
// UM data segment descriptor
GDTEntry UserData;
// Task State Segment
GDTEntry TSS;
}__attribute__((packed));
// Simple structure that tells the CPU the size of the GDT, and it's address
struct GDTPointer {
uint16_t Size;
uint64_t GDTAddress;
}__attribute__((packed));
void BridgeLoadGDT();
void PrepareGDT();
};