2018-05-02 23:03:01 +01:00
|
|
|
import serial
|
|
|
|
|
|
|
|
type
|
|
|
|
PageDirectoryEntry = uint32
|
|
|
|
PageTableEntry = uint32
|
|
|
|
PageDirectory = array[1024, PageDirectoryEntry]
|
|
|
|
PageTable = array[1024, PageTableEntry]
|
|
|
|
|
|
|
|
const
|
|
|
|
blankPageDirectory: PageDirectoryEntry = 0x00000002
|
|
|
|
|
|
|
|
var
|
2018-05-11 22:41:52 +01:00
|
|
|
pageDirectory: ptr PageDirectory
|
2018-05-11 02:07:40 +01:00
|
|
|
pageTable0{.exportc, codegenDecl: "$# $# __attribute__((aligned(0x1000)))".}: PageTable
|
2018-05-02 23:03:01 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
if present: result = result or 0b1
|
|
|
|
if readWrite: result = result or 0b10
|
|
|
|
if userAccessible: result = result or 0b100
|
|
|
|
if writeThrough: result = result or 0b1000
|
|
|
|
if disableCache: result = result or 0b10000
|
|
|
|
|
2018-05-11 02:07:40 +01:00
|
|
|
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")
|
2018-05-02 23:03:01 +01:00
|
|
|
asm """
|
2018-05-11 02:07:40 +01:00
|
|
|
mov %%cr3, %%eax
|
|
|
|
::"a"(`address`)
|
2018-05-02 23:03:01 +01:00
|
|
|
"""
|
|
|
|
|
2018-05-11 22:41:52 +01:00
|
|
|
# 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
|
2018-05-02 23:03:01 +01:00
|
|
|
proc init*() =
|
|
|
|
serial.writeLine("Initialising paging tables and directories.")
|
2018-05-11 22:41:52 +01:00
|
|
|
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
|
2018-05-02 23:03:01 +01:00
|
|
|
for i in 0..1023:
|
2018-05-11 02:07:40 +01:00
|
|
|
pageTable0[i] = createEntry(address = uint32(i) * 0x1000, readWrite = true, present = true)
|
2018-05-11 22:41:52 +01:00
|
|
|
pageDirectory[][768] = createDirectory(address = toPhysical(cast[uint32](pageTable0.addr)), readWrite = true, present = true)
|
|
|
|
for i in 769..1023:
|
|
|
|
pageDirectory[][i] = blankPageDirectory
|
|
|
|
loadPageDirectory(pagingAddress)
|