From 722fd080e0b1d0ed83490ea1890be3a7e6548b78 Mon Sep 17 00:00:00 2001 From: Nathan Cannon Date: Fri, 11 May 2018 02:07:40 +0100 Subject: [PATCH] GDT and IDT now exist in locations that aren't hard coded. Paging currently breaks interrupts. --- kernel/arch/i386/gdt.nim | 17 ++++++++++------- kernel/arch/i386/interrupts.nim | 12 ++++++++---- kernel/arch/i386/linker.ld | 2 +- kernel/arch/i386/paging.nim | 30 ++++++++++++++++++++---------- kernel/kernel.nim | 10 ++++++---- 5 files changed, 45 insertions(+), 26 deletions(-) diff --git a/kernel/arch/i386/gdt.nim b/kernel/arch/i386/gdt.nim index a3d4617..f0da5b7 100644 --- a/kernel/arch/i386/gdt.nim +++ b/kernel/arch/i386/gdt.nim @@ -13,18 +13,20 @@ type base: uint32 # GDT memory location AccessByte = uint8 Flags = uint8 + GDTEntries{.packed.} = array[0..2, GDTEntry] GDT{.packed.} = object descriptor: GDTPointer - entries: array[0..2, GDTEntry] + entries: GDTEntries -const - gdtAddress: uint32 = 0x800 - gdt = cast[ptr GDT](gdtAddress) +var + address: uint32 + gdt: GDT proc gdtFlush(){.inline,asmNoStackFrame.} = asm """ - lgdt (0x800) + lgdt (%%eax) ret + ::"a"(`address`) """ 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(4, 0'u16, 0xFFFFFFFF'u32, 0xF2, createFlags(true, true)); - serial.write("GDT Address:") - serial.writeLine(gdt.descriptor.base) serial.writeLine("Flushing GDT.") + address = cast[uint32](gdt.addr) + serial.write("GDT Address:") + serial.writeLine(address) gdtFlush() diff --git a/kernel/arch/i386/interrupts.nim b/kernel/arch/i386/interrupts.nim index fb8ee6f..a6a1767 100644 --- a/kernel/arch/i386/interrupts.nim +++ b/kernel/arch/i386/interrupts.nim @@ -18,14 +18,15 @@ type int_no, err_code: uint32 # Interrupt number and error code (if applicable) eip, cs, eflags, useresp, ss: uint32 # Pushed by the processor automatically. -const - idtAddress: uint32 = 0x00000000 - idt = cast[ptr IDT](idtAddress) +var + address: uint32 + idt: IDT proc idtFlush(){.inline,asmNoStackFrame.} = asm """ - lidtl (0x0) + lidt (%%eax) ret + ::"a"(`address`) """ #[ @@ -175,4 +176,7 @@ proc idtInstall*() = idtSetGate(30, cast[uint32](isr30), selector, flags) idtSetGate(31, cast[uint32](isr31), selector, flags) serial.writeLine("Flushing IDT.") + address = cast[uint32](idt.addr) + serial.write("IDT Address:") + serial.writeLine(address) idtFlush() \ No newline at end of file diff --git a/kernel/arch/i386/linker.ld b/kernel/arch/i386/linker.ld index e496e22..0509f7f 100644 --- a/kernel/arch/i386/linker.ld +++ b/kernel/arch/i386/linker.ld @@ -4,7 +4,7 @@ OUTPUT_FORMAT(elf32-i386) SECTIONS { - . = 1M; + . = 0x00100000; .text BLOCK(4K) : ALIGN(4K) { diff --git a/kernel/arch/i386/paging.nim b/kernel/arch/i386/paging.nim index d2e5e7b..6eb4089 100644 --- a/kernel/arch/i386/paging.nim +++ b/kernel/arch/i386/paging.nim @@ -10,8 +10,8 @@ const blankPageDirectory: PageDirectoryEntry = 0x00000002 var - pageDirectory: PageDirectory - pageTable: PageTable + pageDirectory{.exportc, codegenDecl: "$# $# __attribute__((aligned(0x1000)))".}: PageDirectory + 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 = 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 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 """ - mov `address`, %cr3 - mov %cr0, %eax - or $0x80000001, %eax - mov %eax, %cr0 + mov %%cr3, %%eax + mov %%eax, %%cr0 + or $0x80000001, %%eax + mov %%cr0, %%eax + ::"a"(`address`) """ proc init*() = @@ -34,6 +42,8 @@ proc init*() = for i in 0..1023: pageDirectory[i] = blankPageDirectory for i in 0..1023: - pageTable[i] = createEntry(address = uint32(i) * 0x1000, readWrite = true, present = true) - pageDirectory[0] = createEntry(address = cast[uint32](pageTable), readWrite = true, present = true) - loadPageDirectory(cast[uint32](pageDirectory.addr)) \ No newline at end of file + pageTable0[i] = createEntry(address = uint32(i) * 0x1000, readWrite = true, present = true) + pageDirectory[0] = createDirectory(address = cast[uint32](pageTable0), readWrite = true, present = true) + loadPageDirectory(cast[uint32](pageDirectory.addr)) + serial.write("Paging setup complete at ") + serial.writeLine(cast[uint32](pageDirectory.addr)) \ No newline at end of file diff --git a/kernel/kernel.nim b/kernel/kernel.nim index 9651f4d..1ba36fc 100644 --- a/kernel/kernel.nim +++ b/kernel/kernel.nim @@ -2,7 +2,7 @@ {.passL: "-ffreestanding -target i386 -nostdlib -T arch/i386/linker.ld".} {.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" @@ -23,11 +23,13 @@ proc memset*(dest: ByteAddress, value: char, count: int){.exportc.} = proc getMemoryMap(mbd: multiboot_info) = 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.writeLine("Version:" & (version)) serial.writeLine("Booting OS") - getMemoryMap(mbd) + #getMemoryMap(mbd) + #paging.init() gdt.gdtInstall() serial.writeLine("GDT installed") interrupts.idtInstall() @@ -37,7 +39,7 @@ proc kernelMain(mbd: multiboot_info, magic: uint) {.exportc: "kernel_main"}= tty.writeLine("Hello World!") tty.write("MAX_INT:") tty.writeLine(high(int)) - tty.write("LMIN_INT:") + tty.write("MIN_INT:") tty.writeLine((low(int)+1)) tty.write("MAX_UINT:") tty.writeLine(high(uint32))