duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit fc760b94218ec72d9981a8cbaef193595545dd54
parent 89ba11ccf55bacbdb043171f8e526a5cb3c2de2d
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Sun, 30 Oct 2022 10:50:47 -0400

i386/pc: add exception handling and PIC remapping

Doing a division by zero now gives us a nice message+abort.

Diffstat:
MMakefile | 2+-
Afs/drv/pc/idt.fs | 40++++++++++++++++++++++++++++++++++++++++
Afs/drv/pc/pic.fs | 24++++++++++++++++++++++++
Mfs/xcomp/i386/kernel.fs | 8++++++--
Mfs/xcomp/i386/pc/init.fs | 20+++++++++++++-------
Mfs/xcomp/i386/pc/inittest.fs | 1+
Mfs/xcomp/i386/pc/kernel.fs | 21++++++++++++---------
7 files changed, 97 insertions(+), 19 deletions(-)

diff --git a/Makefile b/Makefile @@ -2,7 +2,7 @@ TARGETS = dusk dis BOOTFS_SRC = fs/xcomp/bootlo.fs posix/glue.fs fs/xcomp/boothi.fs ALLSRCS = $(shell find fs) QEMU_FLAGS = -accel kvm -accel tcg -QEMU_DRVOPTS = format=raw,index=0,if=floppy +QEMU_DRVOPTS = format=raw,index=0,if=ide all: $(TARGETS) fs/init.fs: posix/init.fs fs/xcomp/init.fs diff --git a/fs/drv/pc/idt.fs b/fs/drv/pc/idt.fs @@ -0,0 +1,40 @@ +\ Interrupt Descriptor Table + +: setISR ( w idx -- ) \ set interrupt "idx" to word w + over 16 rshift rot> 8 * IDT + tuck w! 6 + w! ; + +: _isr00 abort" Divide by zero" ; +: _isr05 abort" Bound range exceeded" ; +: _isr06 abort" Invalid opcode" ; +: _isr07 abort" Device not available" ; +\ To avoid triple faults, we don't do anything on double fault and go straight +\ to (abort) on ISR08 +: _isr0a r> .x spc> abort" Invalid TSS" ; +: _isr0b r> .x spc> abort" Segment not present" ; +: _isr0c r> .x spc> abort" Stack segment fault" ; +: _isr0d r> .x spc> abort" General protection fault" ; +: _isr0e r> .x spc> abort" Page fault" ; +: _isr10 abort" x87 floating-point exception" ; +: _isr11 r> .x spc> abort" Alignment check" ; +: _isr12 abort" Machine check" ; +: _isr13 abort" SIMD floating-point exception" ; +: _isr14 abort" Virtualization exception" ; +: _isr15 r> .x spc> abort" Control protection exception" ; + +\ Only call this after you've moved PIC base vectors around! +: idt$ ['] _isr00 $00 setISR + ['] _isr05 $05 setISR + ['] _isr06 $06 setISR + ['] _isr07 $07 setISR + ['] (abort) $08 setISR + ['] _isr0a $0a setISR + ['] _isr0b $0b setISR + ['] _isr0c $0c setISR + ['] _isr0d $0d setISR + ['] _isr0e $0e setISR + ['] _isr10 $10 setISR + ['] _isr11 $11 setISR + ['] _isr12 $12 setISR + ['] _isr13 $13 setISR + ['] _isr14 $14 setISR + ['] _isr15 $15 setISR ; diff --git a/fs/drv/pc/pic.fs b/fs/drv/pc/pic.fs @@ -0,0 +1,24 @@ +\ Programmable Interrupt Controller 8259 driver +?f<< /drv/pc/idt.fs + +$20 const PIC1CMD +$21 const PIC1DATA +$a0 const PIC2CMD +$a1 const PIC2DATA + +\ piceoi and piceoi2 are already defined in the kernel + +: pic$ + \ Set $20-$2f ISRs to IRQ handlers that send back EOI to PICs + 8 >r begin ['] piceoi $20 r@ 1- + setISR next + 8 >r begin ['] piceoi2 $28 r@ 1- + setISR next + \ Re-initialize master and slave PIC chips + \ We send bytes to both PIC in parallel to have an "io_wait" effect + $11 PIC1CMD pc! \ INIT + ICW4 + $11 PIC2CMD pc! + $20 PIC1DATA pc! \ $20 offset for master + $28 PIC2DATA pc! \ $28 offset for master + $04 PIC1DATA pc! \ PIC1 in master mode + $02 PIC2DATA pc! \ PIC2 in slave mode + $01 PIC1DATA pc! \ 8086/8088 mode + $01 PIC2DATA pc! ; diff --git a/fs/xcomp/i386/kernel.fs b/fs/xcomp/i386/kernel.fs @@ -41,13 +41,17 @@ PSTOP STACKSZ - const HEREMAX forward16 jmp, to L1 pc to lblintnoop iret, \ Interrupt Descriptor Table -0 align4 pc $100 idtgen +0 align4 pc to L2 $100 idtgen pc to lblidt -$100 8 * 1- w, ( pc ) , +$100 8 * 1- w, L2 , L1 forward! lblidt m) lidt, sti, forward16 jmp, to L1 +xcode IDT + L2 pspushN, + ret, + xcode noop pc to lblret ret, xcode (cell) diff --git a/fs/xcomp/i386/pc/init.fs b/fs/xcomp/i386/pc/init.fs @@ -8,26 +8,32 @@ \ BIOS 64k limit and all hell breaks loose. ?f<< /asm/i386.fs f<< /drv/pc/acpi.fs -f<< /drv/pc/com.fs +\ Serial communication +\ f<< /drv/pc/com.fs f<< /drv/pc/vga.fs f<< /sys/grid.fs ' (emit) to emit -f<< /drv/pc/pci.fs \ Floppy boot drive -f<< /drv/pc/fdc.fs -floppy :init -floppy :self bootfs to Filesystem drv +\ f<< /drv/pc/fdc.fs +\ floppy :init +\ floppy :self bootfs to Filesystem drv +f<< /drv/pc/pci.fs \ IDE boot drive -\ f<< /drv/pc/ata.fs -\ ATADrive :reset drop ATA0:0 bootfs to Filesystem drv +f<< /drv/pc/ata.fs +ATADrive :reset drop ATA0:0 bootfs to Filesystem drv \ AHCI boot drive \ f<< /drv/pc/ahci.fs \ 0 AHCIDrive :new dup bootfs to Filesystem drv ( drv ) \ AHCIDrive :enable +\ Now that we don't ever go back to real mode anymore, we can remap the PIC +\ and setup exception handlers +f<< /drv/pc/pic.fs +pic$ idt$ + f<< /fs/fat.fs f<< /drv/pc/ps28042.fs diff --git a/fs/xcomp/i386/pc/inittest.fs b/fs/xcomp/i386/pc/inittest.fs @@ -1,3 +1,4 @@ +f<< /drv/pc/com.fs com$ ' >com to emit f<< sys/scratch.fs f<< lib/nfmt.fs diff --git a/fs/xcomp/i386/pc/kernel.fs b/fs/xcomp/i386/pc/kernel.fs @@ -22,7 +22,7 @@ pc to L1 \ segment with ffff limits 0 L2 jmpfar, 0 to realmode -xcode int13h ( drv head cyl sec dst -- ) pc w>e lblsysdict pc>addr ! +xcode int13h ( drv head cyl sec dst -- ) BX pspop, AX pspop, cl al mov, \ sec AX pspop, ch al mov, \ cyl @@ -30,13 +30,16 @@ xcode int13h ( drv head cyl sec dst -- ) pc w>e lblsysdict pc>addr ! AX pspop, dl al mov, \ drive cli, $18 L1 jmpfar, -\ When booting from floppy under QEMU, I get IRQs 0 and 6 from the PIC (mapped -\ to vector 8 and 14) and if I don't handle it with an ACK to the PIC, the -\ system freezes. (often, but not always). With these handlers below, we always -\ boot. -\ TODO: have proper and complete IRQ handling -pc lblidt pc>addr 1+ 1+ @ pc>addr 8 8 * + 16b ! -pc lblidt pc>addr 1+ 1+ @ pc>addr 14 8 * + 16b ! -ax push, al $20 i) mov, $20 i) al out, ax pop, iret, +\ IRQ 0 and 6 have to be mapped to End Of Interrupt handlers early because when +\ booting from floppy, the system hangs early from those IRQs not being handled. +\ The rest of PIC initialization is done in /drv/pc/pic.fs +xcode piceoi pc + ax push, al $20 i) mov, $20 i) al out, ax pop, iret, + +( pc ) lblidt pc>addr 1+ 1+ @ pc>addr 8 8 * + 2dup w! 6 8 * + w! + +xcode piceoi2 \ slave IRQs have to EOI both master and slave. + pc w>e lblsysdict pc>addr ! \ last word of the kernel dict + ax push, al $20 i) mov, $a0 i) al out, $20 i) al out, ax pop, iret, pc lblbootptr pc>addr !