Started implementing IDT. Currently crashes on interrupt.
This commit is contained in:
parent
05f6ce2544
commit
6ead11b75a
171
kernel/arch/i386/interrupts.nim
Normal file
171
kernel/arch/i386/interrupts.nim
Normal file
@ -0,0 +1,171 @@
|
||||
import macros, serial
|
||||
type
|
||||
IDTEntry{.packed.} = object
|
||||
base_low: uint16
|
||||
kernel_selector: uint16
|
||||
zero: uint8
|
||||
flags: uint8
|
||||
base_high: uint16
|
||||
IDTPointer{.packed.} = object
|
||||
limit: uint16
|
||||
base: uint32
|
||||
IDT{.packed.} = object
|
||||
descriptor: IDTPointer
|
||||
entries: array[0..255, IDTEntry]
|
||||
Registers{.packed.} = object
|
||||
ds: uint32 # Data segment selector
|
||||
edi, esi, ebp, esp, ebx, edx, ecx, eax: uint32 # Pushed by pusha.
|
||||
int_no, err_code: uint32 # Interrupt number and error code (if applicable)
|
||||
eip, cs, eflags, useresp, ss: uint32 # Pushed by the processor automatically.
|
||||
|
||||
var
|
||||
idt: IDT
|
||||
idtAddr: uint32 = cast[uint32](idt.addr)
|
||||
|
||||
{.push stackTrace:off.}
|
||||
proc idtFlush(){.inline,asmNoStackFrame.} =
|
||||
asm """
|
||||
lidt [`idtAddr`]
|
||||
ret
|
||||
"""
|
||||
{.pop.}
|
||||
|
||||
proc isrHandler(registers: Registers){.exportc.} =
|
||||
serial.write("Recieved interrupt:")
|
||||
serial.write(registers.int_no)
|
||||
serial.write("\L")
|
||||
|
||||
proc isrCommon() =
|
||||
asm """
|
||||
pusha
|
||||
movw %ax, %ds
|
||||
push %eax
|
||||
movw $0x10, %ax
|
||||
movw %ds, %ax
|
||||
movw %es, %ax
|
||||
movw %fs, %ax
|
||||
movw %gs, %ax
|
||||
call `isrHandler`
|
||||
pop %eax
|
||||
movw %ds, %ax
|
||||
movw %es, %ax
|
||||
movw %fs, %ax
|
||||
movw %gs, %ax
|
||||
popa
|
||||
add $8, %esp
|
||||
sti
|
||||
iret
|
||||
"""
|
||||
|
||||
macro generateISR(code: static[uint8], isError: static[bool]): typed =
|
||||
result = nnkStmtList.newTree(
|
||||
nnkProcDef.newTree(
|
||||
newIdentNode("isr" & $code),
|
||||
newEmptyNode(),
|
||||
newEmptyNode(),
|
||||
nnkFormalParams.newTree(
|
||||
newEmptyNode()
|
||||
),
|
||||
newEmptyNode(),
|
||||
newEmptyNode(),
|
||||
nnkStmtList.newTree(
|
||||
nnkAsmStmt.newTree(
|
||||
newEmptyNode(),
|
||||
newLit("cli\x0A" & (if isError: "" else: "push 0\x0A") & "push " & $code & "\x0A")
|
||||
),
|
||||
nnkCall.newTree(
|
||||
newIdentNode("isrCommon")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
proc idtSetGate(num: uint8, base: uint32, sel: uint16, flags: uint8) =
|
||||
idt.entries[num].base_low = uint16(base and 0xFFFF)
|
||||
idt.entries[num].base_high = uint16((base shr 16) and 0xFFFF)
|
||||
idt.entries[num].zero = 0
|
||||
idt.entries[num].flags = flags
|
||||
idt.entries[num].kernel_selector = sel
|
||||
|
||||
# Would like to generate these in a loop, but apparently
|
||||
# Error: type mismatch: got <uint8, bool>
|
||||
# but expected one of:
|
||||
# macro generateISR(code: static[uint8]; isError: static[bool]): typed
|
||||
# first type mismatch at position: 1
|
||||
# required type: static[uint8]
|
||||
# but expression 'uint8(i)' is of type: uint8
|
||||
|
||||
static:
|
||||
generateISR(0, false)
|
||||
generateISR(1, false)
|
||||
generateISR(2, false)
|
||||
generateISR(3, false)
|
||||
generateISR(4, false)
|
||||
generateISR(5, false)
|
||||
generateISR(6, false)
|
||||
generateISR(7, false)
|
||||
generateISR(8, true)
|
||||
generateISR(9, false)
|
||||
generateISR(10, true)
|
||||
generateISR(11, true)
|
||||
generateISR(12, true)
|
||||
generateISR(13, true)
|
||||
generateISR(14, true)
|
||||
generateISR(15, false)
|
||||
generateISR(16, false)
|
||||
generateISR(17, false)
|
||||
generateISR(18, false)
|
||||
generateISR(19, false)
|
||||
generateISR(20, false)
|
||||
generateISR(21, false)
|
||||
generateISR(22, false)
|
||||
generateISR(23, false)
|
||||
generateISR(24, false)
|
||||
generateISR(25, false)
|
||||
generateISR(26, false)
|
||||
generateISR(27, false)
|
||||
generateISR(28, false)
|
||||
generateISR(29, false)
|
||||
generateISR(30, false)
|
||||
generateISR(31, false)
|
||||
|
||||
let
|
||||
selector: uint16 = 0x08
|
||||
flags: uint8 = 0x8E
|
||||
|
||||
proc idtInstall*() =
|
||||
idt.descriptor.limit = uint16(sizeof(IDTEntry) * idt.entries.len) - 1
|
||||
idt.descriptor.base = cast[uint32](idt.entries.addr)
|
||||
idtSetGate(0, cast[uint32](isr0) ,selector, flags)
|
||||
idtSetGate(1, cast[uint32](isr1) ,selector, flags)
|
||||
idtSetGate(2, cast[uint32](isr2) ,selector, flags)
|
||||
idtSetGate(3, cast[uint32](isr3) ,selector, flags)
|
||||
idtSetGate(4, cast[uint32](isr4) ,selector, flags)
|
||||
idtSetGate(5, cast[uint32](isr5) ,selector, flags)
|
||||
idtSetGate(6, cast[uint32](isr6) ,selector, flags)
|
||||
idtSetGate(7, cast[uint32](isr7) ,selector, flags)
|
||||
idtSetGate(8, cast[uint32](isr8) ,selector, flags)
|
||||
idtSetGate(9, cast[uint32](isr9) ,selector, flags)
|
||||
idtSetGate(10, cast[uint32](isr10) ,selector, flags)
|
||||
idtSetGate(11, cast[uint32](isr11) ,selector, flags)
|
||||
idtSetGate(12, cast[uint32](isr12) ,selector, flags)
|
||||
idtSetGate(13, cast[uint32](isr13) ,selector, flags)
|
||||
idtSetGate(14, cast[uint32](isr14) ,selector, flags)
|
||||
idtSetGate(15, cast[uint32](isr15) ,selector, flags)
|
||||
idtSetGate(16, cast[uint32](isr16) ,selector, flags)
|
||||
idtSetGate(17, cast[uint32](isr17) ,selector, flags)
|
||||
idtSetGate(18, cast[uint32](isr18) ,selector, flags)
|
||||
idtSetGate(19, cast[uint32](isr19) ,selector, flags)
|
||||
idtSetGate(20, cast[uint32](isr20) ,selector, flags)
|
||||
idtSetGate(21, cast[uint32](isr21) ,selector, flags)
|
||||
idtSetGate(22, cast[uint32](isr22) ,selector, flags)
|
||||
idtSetGate(23, cast[uint32](isr23) ,selector, flags)
|
||||
idtSetGate(24, cast[uint32](isr24) ,selector, flags)
|
||||
idtSetGate(25, cast[uint32](isr25) ,selector, flags)
|
||||
idtSetGate(26, cast[uint32](isr26) ,selector, flags)
|
||||
idtSetGate(27, cast[uint32](isr27) ,selector, flags)
|
||||
idtSetGate(28, cast[uint32](isr28) ,selector, flags)
|
||||
idtSetGate(29, cast[uint32](isr29) ,selector, flags)
|
||||
idtSetGate(30, cast[uint32](isr30) ,selector, flags)
|
||||
idtSetGate(31, cast[uint32](isr31) ,selector, flags)
|
||||
idtFlush()
|
@ -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, serial
|
||||
import tty, gdt, interrupts, serial
|
||||
|
||||
type
|
||||
MemoryPointer{.unchecked.} = ptr array[0, char]
|
||||
@ -23,6 +23,8 @@ proc kernelMain() {.exportc: "kernel_main"}=
|
||||
serial.write("Booting OS\L")
|
||||
gdt.gdtInstall()
|
||||
serial.write("GDT installed\L")
|
||||
interrupts.idtInstall()
|
||||
serial.write("IDT installed\L")
|
||||
terminalInitialize()
|
||||
terminalWrite("Hello World!\L")
|
||||
terminalWrite("MAX_INT:")
|
||||
@ -32,3 +34,6 @@ proc kernelMain() {.exportc: "kernel_main"}=
|
||||
for i in 0..22:
|
||||
terminalWrite(i)
|
||||
terminalWrite('\L')
|
||||
asm """
|
||||
int $0x3
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user