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