From cea54a8b77dcbe93f0124817502267216b606c15 Mon Sep 17 00:00:00 2001 From: Nathan Cannon Date: Fri, 11 May 2018 22:41:52 +0100 Subject: [PATCH] Paging now works. Is initially bootstrapped by GRUB then later OS accessible. Some memory maybe wasted on bootstrap page table? --- kernel/arch/i386/boot.s | 39 ++++++++++++++++++++++++++++++++- kernel/arch/i386/interrupts.nim | 10 ++++----- kernel/arch/i386/linker.ld | 15 +++++++------ kernel/arch/i386/paging.nim | 33 +++++++++++++++++++--------- kernel/arch/i386/tty.nim | 2 +- kernel/kernel.nim | 3 ++- 6 files changed, 77 insertions(+), 25 deletions(-) diff --git a/kernel/arch/i386/boot.s b/kernel/arch/i386/boot.s index 8d6a396..eaaae2a 100644 --- a/kernel/arch/i386/boot.s +++ b/kernel/arch/i386/boot.s @@ -10,16 +10,53 @@ .long FLAGS .long CHECKSUM -.section .bss +.section .bootstrap_stack, "aw", @nobits .align 16 stack_bottom: .skip 16384 # 16 KiB stack_top: +.section .bss, "aw", @nobits +.align 4096 +boot_pagedir: + .skip 4096 +boot_pagetab1: + .skip 4096 + .section .text .global _start .type _start, @function _start: + mov $(boot_pagetab1 - 0xC0000000), %edi + mov $0, %esi + mov $1023, %ecx +1: + cmp $(_kernel_start - 0xC0000000), %esi + jl 2f + cmp $(_kernel_end - 0xC0000000), %esi + jge 3f + mov %esi, %edx + or $0x003, %edx + mov %edx, (%edi) +2: + add $4096, %esi + add $4, %edi + loop 1b +3: + movl $(boot_pagetab1 - 0xC0000000 + 0x003), boot_pagedir - 0xC0000000 + 0 + movl $(boot_pagetab1 - 0xC0000000 + 0x003), boot_pagedir - 0xC0000000 + 768 * 4 + movl $(boot_pagedir - 0xC0000000), %ecx + mov %ecx, %cr3 + mov %cr0, %ecx + or $0x80010000, %ecx + mov %ecx, %cr0 + lea 4f, %ecx + jmp *%ecx + +4: + movl $0, boot_pagedir + 0 + mov %cr3, %ecx + mov %ecx, %cr3 mov $stack_top, %esp call kernel_main cli diff --git a/kernel/arch/i386/interrupts.nim b/kernel/arch/i386/interrupts.nim index a6a1767..28688cd 100644 --- a/kernel/arch/i386/interrupts.nim +++ b/kernel/arch/i386/interrupts.nim @@ -84,11 +84,11 @@ macro generateISR(code: static[int], isError: static[bool]): typed = newIdentNode("writeLine") ), newLit(code) - ), - nnkAsmStmt.newTree( - newEmptyNode(), - newLit((if isError: "" else: "push 0\x0A") & "push " & $code & "\x0A") - ) + )#, + #nnkAsmStmt.newTree( + # newEmptyNode(), + # newLit((if isError: "" else: "push 0\x0A") & "push " & $code & "\x0A") + #) ) ) ) diff --git a/kernel/arch/i386/linker.ld b/kernel/arch/i386/linker.ld index 0509f7f..1206498 100644 --- a/kernel/arch/i386/linker.ld +++ b/kernel/arch/i386/linker.ld @@ -4,28 +4,29 @@ OUTPUT_FORMAT(elf32-i386) SECTIONS { - . = 0x00100000; - - .text BLOCK(4K) : ALIGN(4K) + . = 0xC0100000; + _kernel_start = .; + .text ALIGN(4K) : AT(ADDR(.text) - 0xC0000000) { *(.multiboot) *(.text) } - .rodata BLOCK(4K) : ALIGN(4K) + .rodata ALIGN(4K) : AT(ADDR(.rodata) - 0xC0000000) { *(.rodata) } - .data BLOCK(4K) : ALIGN(4K) + .data ALIGN(4K) : AT(ADDR(.data) - 0xC0000000) { *(.data) } - .bss BLOCK(4K) : ALIGN(4K) + .bss ALIGN(4K) : AT(ADDR(.bss) - 0xC0000000) { *(COMMON) *(.bss) + *(.bootstrap_stack) } - + _kernel_end = .; } diff --git a/kernel/arch/i386/paging.nim b/kernel/arch/i386/paging.nim index 6eb4089..b1f01f6 100644 --- a/kernel/arch/i386/paging.nim +++ b/kernel/arch/i386/paging.nim @@ -10,7 +10,7 @@ const blankPageDirectory: PageDirectoryEntry = 0x00000002 var - pageDirectory{.exportc, codegenDecl: "$# $# __attribute__((aligned(0x1000)))".}: PageDirectory + pageDirectory: ptr 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 = @@ -31,19 +31,32 @@ proc loadPageDirectory(address: uint32){.inline.} = serial.writeLine("Loading paging data") asm """ mov %%cr3, %%eax - mov %%eax, %%cr0 - or $0x80000001, %%eax - mov %%cr0, %%eax ::"a"(`address`) """ +# Converts a physical to a virtual address for the kernel +proc toVirtual(address: uint32): uint32 = + result = address + 0xC0000000'u32 + +# Converts a physical to a virtual address for the kernel +proc toPhysical(address: uint32): uint32 = + result = address - 0xC0000000'u32 + +# Each page starts from a multiple of 0x400000 769 proc init*() = serial.writeLine("Initialising paging tables and directories.") - for i in 0..1023: - pageDirectory[i] = blankPageDirectory + var pagingAddress: uint32 = 0 + # Find the bootstrapped page directory + asm """ + mov %%cr3, %%eax + :"=a"(`pagingAddress`) + """ + pageDirectory = cast[ptr PageDirectory](toVirtual(pagingAddress)) + for i in 0..767: + pageDirectory[][i] = blankPageDirectory for i in 0..1023: 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 + pageDirectory[][768] = createDirectory(address = toPhysical(cast[uint32](pageTable0.addr)), readWrite = true, present = true) + for i in 769..1023: + pageDirectory[][i] = blankPageDirectory + loadPageDirectory(pagingAddress) \ No newline at end of file diff --git a/kernel/arch/i386/tty.nim b/kernel/arch/i386/tty.nim index e500dee..cbf9a10 100644 --- a/kernel/arch/i386/tty.nim +++ b/kernel/arch/i386/tty.nim @@ -8,7 +8,7 @@ type VGAMemory = ptr array[0..(vgaWidth * vgaHeight - 1), VGADoubleByte] const - terminalBufferBaseAddress = 0xB8000 + terminalBufferBaseAddress = 0xC00B8000 vgaMem = cast[VGAMemory](terminalBufferBaseAddress) var diff --git a/kernel/kernel.nim b/kernel/kernel.nim index 1ba36fc..2dc79e2 100644 --- a/kernel/kernel.nim +++ b/kernel/kernel.nim @@ -25,16 +25,17 @@ proc getMemoryMap(mbd: multiboot_info) = #proc kernelMain(mbd: multiboot_info, magic: uint) {.exportc: "kernel_main"}= proc kernelMain() {.exportc: "kernel_main"}= + paging.init() serial.init() serial.writeLine("Version:" & (version)) serial.writeLine("Booting OS") #getMemoryMap(mbd) - #paging.init() gdt.gdtInstall() serial.writeLine("GDT installed") interrupts.idtInstall() serial.writeLine("IDT installed") tty.init() + serial.writeLine("TTY initialised") tty.writeLine("Version:" & version) tty.writeLine("Hello World!") tty.write("MAX_INT:")