GDT and IDT now exist in locations that aren't hard coded. Paging currently breaks interrupts.

This commit is contained in:
neviyn 2018-05-11 02:07:40 +01:00
parent ada7e292f8
commit 722fd080e0
5 changed files with 45 additions and 26 deletions

View File

@ -13,18 +13,20 @@ type
base: uint32 # GDT memory location base: uint32 # GDT memory location
AccessByte = uint8 AccessByte = uint8
Flags = uint8 Flags = uint8
GDTEntries{.packed.} = array[0..2, GDTEntry]
GDT{.packed.} = object GDT{.packed.} = object
descriptor: GDTPointer descriptor: GDTPointer
entries: array[0..2, GDTEntry] entries: GDTEntries
const var
gdtAddress: uint32 = 0x800 address: uint32
gdt = cast[ptr GDT](gdtAddress) gdt: GDT
proc gdtFlush(){.inline,asmNoStackFrame.} = proc gdtFlush(){.inline,asmNoStackFrame.} =
asm """ asm """
lgdt (0x800) lgdt (%%eax)
ret ret
::"a"(`address`)
""" """
proc gdtSetGate(num: int, base: uint16, limit: uint32, access: AccessByte, flags: Flags) = proc gdtSetGate(num: int, base: uint16, limit: uint32, access: AccessByte, flags: Flags) =
@ -68,7 +70,8 @@ proc gdtInstall*() =
#gdtSetGate(3, 0'u16, 0xFFFFFFFF'u32, 0xFA, createFlags(true, true)); #gdtSetGate(3, 0'u16, 0xFFFFFFFF'u32, 0xFA, createFlags(true, true));
#gdtSetGate(4, 0'u16, 0xFFFFFFFF'u32, 0xF2, createFlags(true, true)); #gdtSetGate(4, 0'u16, 0xFFFFFFFF'u32, 0xF2, createFlags(true, true));
serial.write("GDT Address:")
serial.writeLine(gdt.descriptor.base)
serial.writeLine("Flushing GDT.") serial.writeLine("Flushing GDT.")
address = cast[uint32](gdt.addr)
serial.write("GDT Address:")
serial.writeLine(address)
gdtFlush() gdtFlush()

View File

@ -18,14 +18,15 @@ type
int_no, err_code: uint32 # Interrupt number and error code (if applicable) int_no, err_code: uint32 # Interrupt number and error code (if applicable)
eip, cs, eflags, useresp, ss: uint32 # Pushed by the processor automatically. eip, cs, eflags, useresp, ss: uint32 # Pushed by the processor automatically.
const var
idtAddress: uint32 = 0x00000000 address: uint32
idt = cast[ptr IDT](idtAddress) idt: IDT
proc idtFlush(){.inline,asmNoStackFrame.} = proc idtFlush(){.inline,asmNoStackFrame.} =
asm """ asm """
lidtl (0x0) lidt (%%eax)
ret ret
::"a"(`address`)
""" """
#[ #[
@ -175,4 +176,7 @@ proc idtInstall*() =
idtSetGate(30, cast[uint32](isr30), selector, flags) idtSetGate(30, cast[uint32](isr30), selector, flags)
idtSetGate(31, cast[uint32](isr31), selector, flags) idtSetGate(31, cast[uint32](isr31), selector, flags)
serial.writeLine("Flushing IDT.") serial.writeLine("Flushing IDT.")
address = cast[uint32](idt.addr)
serial.write("IDT Address:")
serial.writeLine(address)
idtFlush() idtFlush()

View File

@ -4,7 +4,7 @@ OUTPUT_FORMAT(elf32-i386)
SECTIONS SECTIONS
{ {
. = 1M; . = 0x00100000;
.text BLOCK(4K) : ALIGN(4K) .text BLOCK(4K) : ALIGN(4K)
{ {

View File

@ -10,8 +10,8 @@ const
blankPageDirectory: PageDirectoryEntry = 0x00000002 blankPageDirectory: PageDirectoryEntry = 0x00000002
var var
pageDirectory: PageDirectory pageDirectory{.exportc, codegenDecl: "$# $# __attribute__((aligned(0x1000)))".}: PageDirectory
pageTable: PageTable pageTable0{.exportc, codegenDecl: "$# $# __attribute__((aligned(0x1000)))".}: PageTable
proc createEntry(address: uint32, present: bool = false, readWrite: bool = false, userAccessible: bool = false, writeThrough: bool = false, disableCache: bool = false): uint32 = proc createEntry(address: uint32, present: bool = false, readWrite: bool = false, userAccessible: bool = false, writeThrough: bool = false, disableCache: bool = false): uint32 =
result = address and 0xFFFFF000'u32 # Set attributes section to zero result = address and 0xFFFFF000'u32 # Set attributes section to zero
@ -21,12 +21,20 @@ proc createEntry(address: uint32, present: bool = false, readWrite: bool = false
if writeThrough: result = result or 0b1000 if writeThrough: result = result or 0b1000
if disableCache: result = result or 0b10000 if disableCache: result = result or 0b10000
proc loadPageDirectory(address: uint32){.asmNoStackFrame.} = proc createDirectory(address: uint32, present: bool = false, readWrite: bool = false, userAccessible: bool = false, writeThrough: bool = false, disableCache: bool = false, pageSize: bool = false): uint32 =
var checkAddress = address
if pageSize: checkAddress = checkAddress and 0xFFFF0000'u32
result = createEntry(address, present, readWrite, userAccessible, writeThrough, disableCache)
if pageSize: result = result or 0b10000000
proc loadPageDirectory(address: uint32){.inline.} =
serial.writeLine("Loading paging data")
asm """ asm """
mov `address`, %cr3 mov %%cr3, %%eax
mov %cr0, %eax mov %%eax, %%cr0
or $0x80000001, %eax or $0x80000001, %%eax
mov %eax, %cr0 mov %%cr0, %%eax
::"a"(`address`)
""" """
proc init*() = proc init*() =
@ -34,6 +42,8 @@ proc init*() =
for i in 0..1023: for i in 0..1023:
pageDirectory[i] = blankPageDirectory pageDirectory[i] = blankPageDirectory
for i in 0..1023: for i in 0..1023:
pageTable[i] = createEntry(address = uint32(i) * 0x1000, readWrite = true, present = true) pageTable0[i] = createEntry(address = uint32(i) * 0x1000, readWrite = true, present = true)
pageDirectory[0] = createEntry(address = cast[uint32](pageTable), readWrite = true, present = true) pageDirectory[0] = createDirectory(address = cast[uint32](pageTable0), readWrite = true, present = true)
loadPageDirectory(cast[uint32](pageDirectory.addr)) loadPageDirectory(cast[uint32](pageDirectory.addr))
serial.write("Paging setup complete at ")
serial.writeLine(cast[uint32](pageDirectory.addr))

View File

@ -2,7 +2,7 @@
{.passL: "-ffreestanding -target i386 -nostdlib -T arch/i386/linker.ld".} {.passL: "-ffreestanding -target i386 -nostdlib -T arch/i386/linker.ld".}
{.passC: "-ffreestanding -nostdlib --target=i386-pc-none-elf -march=i386".} {.passC: "-ffreestanding -nostdlib --target=i386-pc-none-elf -march=i386".}
import tty, gdt, interrupts, serial, multiboot import tty, gdt, interrupts, serial, multiboot, paging
const version {.strdefine.} = "UNKNOWN" const version {.strdefine.} = "UNKNOWN"
@ -23,11 +23,13 @@ proc memset*(dest: ByteAddress, value: char, count: int){.exportc.} =
proc getMemoryMap(mbd: multiboot_info) = proc getMemoryMap(mbd: multiboot_info) =
discard # Use this if we need to do anything with the GRUB memory map discard # Use this if we need to do anything with the GRUB memory map
proc kernelMain(mbd: multiboot_info, magic: uint) {.exportc: "kernel_main"}= #proc kernelMain(mbd: multiboot_info, magic: uint) {.exportc: "kernel_main"}=
proc kernelMain() {.exportc: "kernel_main"}=
serial.init() serial.init()
serial.writeLine("Version:" & (version)) serial.writeLine("Version:" & (version))
serial.writeLine("Booting OS") serial.writeLine("Booting OS")
getMemoryMap(mbd) #getMemoryMap(mbd)
#paging.init()
gdt.gdtInstall() gdt.gdtInstall()
serial.writeLine("GDT installed") serial.writeLine("GDT installed")
interrupts.idtInstall() interrupts.idtInstall()
@ -37,7 +39,7 @@ proc kernelMain(mbd: multiboot_info, magic: uint) {.exportc: "kernel_main"}=
tty.writeLine("Hello World!") tty.writeLine("Hello World!")
tty.write("MAX_INT:") tty.write("MAX_INT:")
tty.writeLine(high(int)) tty.writeLine(high(int))
tty.write("LMIN_INT:") tty.write("MIN_INT:")
tty.writeLine((low(int)+1)) tty.writeLine((low(int)+1))
tty.write("MAX_UINT:") tty.write("MAX_UINT:")
tty.writeLine(high(uint32)) tty.writeLine(high(uint32))