GDT, page frame allocator
This commit is contained in:
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
@@ -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();
|
||||
};
|
||||
Reference in New Issue
Block a user