GDT WORKS HOLY CRAP
This commit is contained in:
parent
94a8f74ada
commit
6c076be975
3 changed files with 71 additions and 6 deletions
|
@ -6,10 +6,19 @@
|
|||
* Oh god oh god. Descriptor tables.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "Descriptors.hh"
|
||||
|
||||
namespace kernel {
|
||||
|
||||
/**
|
||||
* SegmentDescriptors are entries in the GDT and LDT that describe memory
|
||||
* segments. Each descriptor is two double-words (8 bytes, 64 bits) long.
|
||||
*/
|
||||
typedef uint64_t SegmentDescriptor;
|
||||
|
||||
|
||||
/** Descriptor privilege level. */
|
||||
enum class DPL {
|
||||
Ring0 = 0x0,
|
||||
|
@ -18,6 +27,7 @@ enum class DPL {
|
|||
Ring3 = 0x3
|
||||
};
|
||||
|
||||
|
||||
/** A four bit value describing the type of the segment. */
|
||||
enum class Type {
|
||||
// Data segment types
|
||||
|
@ -41,13 +51,18 @@ enum class Type {
|
|||
CodeEXRCA = 0xf // Execute/read, conforming, accessed
|
||||
};
|
||||
|
||||
/**
|
||||
* SegmentDescriptors are entries in the GDT and LDT that describe memory
|
||||
* segments. Each descriptor is two double-words (8 bytes, 64 bits) long.
|
||||
*/
|
||||
typedef uint64_t SegmentDescriptor;
|
||||
|
||||
SegmentDescriptor sGDT[4];
|
||||
/** Six byte field containing the length and a linear address where the GDT lives. */
|
||||
struct GDTPointer
|
||||
{
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
} __attribute((__packed__));
|
||||
|
||||
|
||||
static const size_t GDTSize = 5;
|
||||
static SegmentDescriptor sGDT[GDTSize];
|
||||
|
||||
|
||||
static inline SegmentDescriptor
|
||||
createSegmentDescriptor(uint32_t base,
|
||||
|
@ -81,4 +96,39 @@ createSegmentDescriptor(uint32_t base,
|
|||
return descriptor;
|
||||
}
|
||||
|
||||
/*
|
||||
* Static
|
||||
*/
|
||||
|
||||
void
|
||||
initGDT()
|
||||
{
|
||||
sGDT[0] = 0; // First descriptor is always NULL.
|
||||
sGDT[1] = createSegmentDescriptor(0x00000000, 0x000FFFFF, Type::CodeEXR, DPL::Ring0);
|
||||
sGDT[2] = createSegmentDescriptor(0x00000000, 0x000FFFFF, Type::DataRW, DPL::Ring0);
|
||||
sGDT[3] = 0; // Unused for now.
|
||||
sGDT[4] = 0; // Unused for now.
|
||||
|
||||
GDTPointer gdt {GDTSize * sizeof(SegmentDescriptor) - 1, uint32_t(&sGDT)};
|
||||
|
||||
/*
|
||||
* Load the new GDT with the pointer defined above. The GDT isn't actually
|
||||
* used until the segment registers are reladed. Below, CS is reloaded by
|
||||
* a long jump into the new code segment. The rest of the segment registers
|
||||
* can be loaded directly.
|
||||
*/
|
||||
asm volatile(
|
||||
"lgdt %0\n"
|
||||
"ljmpl $0x08, $reloadSegments\n"
|
||||
"reloadSegments:\n"
|
||||
"movl $0x10, %%eax\n"
|
||||
"movl %%eax, %%ds\n"
|
||||
"movl %%eax, %%es\n"
|
||||
"movl %%eax, %%fs\n"
|
||||
"movl %%eax, %%gs\n"
|
||||
"movl %%eax, %%ss\n"
|
||||
: : "m" (gdt)
|
||||
: "%eax");
|
||||
}
|
||||
|
||||
} /* namespace kernel */
|
||||
|
|
12
src/Descriptors.hh
Normal file
12
src/Descriptors.hh
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* Descriptors.hh vim: set tw=80: Eryn Wells <eryn@erynwells.me>
|
||||
*/
|
||||
/**
|
||||
* Declaration of relevant classes and functions for dealing with the GDT and
|
||||
* IDT.
|
||||
*/
|
||||
|
||||
namespace kernel {
|
||||
|
||||
void initGDT();
|
||||
|
||||
} /* namespace kernel */
|
|
@ -1,6 +1,7 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "Console.hh"
|
||||
#include "Descriptors.hh"
|
||||
|
||||
#if defined(__linux__)
|
||||
#error "This file should be compiled with a cross-compiler, not the Linux system compiler!"
|
||||
|
@ -19,6 +20,8 @@ kearly()
|
|||
console.clear(kernel::Console::Color::Blue);
|
||||
console.writeString("Loading system ...\n");
|
||||
|
||||
kernel::initGDT();
|
||||
|
||||
volatile int foo = 0;
|
||||
int i = 0;
|
||||
for (;;) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue