From e05574a9511e724651361905620f96666c7acb04 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Fri, 11 Jun 2021 23:01:32 +0300 Subject: [PATCH] selectors, descriptors, more interrupt init --- sys1/kern/src/desc.c | 15 +++++++++++ sys1/kern/src/desc.h | 2 ++ sys1/kern/src/intr.asm | 52 +++++++++++++++++++++++++++++++++++- sys1/kern/src/intr.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++- sys1/kern/src/intr.h | 43 ++++++++++++++++++++++++++++++ sys1/kern/src/main.c | 1 + sys1/kern/src/mem.asm | 20 +++++++++++++- sys1/kern/src/mem.c | 18 +++++++------ sys1/kern/src/mem.h | 12 +++++++++ 9 files changed, 221 insertions(+), 11 deletions(-) diff --git a/sys1/kern/src/desc.c b/sys1/kern/src/desc.c index d02c5fc..9af939e 100644 --- a/sys1/kern/src/desc.c +++ b/sys1/kern/src/desc.c @@ -22,6 +22,11 @@ #define SEG_DEF 0x00400000 +#define GATE_TYPE_INTR 0x0e00 +#define GATE_TYPE_TRAP 0x0f00 +#define GATE_PRESENT 0x8000 + + void desc_seg(struct desc *desc, int type, uint32_t base, uint32_t limit, int dpl) { if(type == SEG_NULL) { @@ -43,3 +48,13 @@ void desc_seg(struct desc *desc, int type, uint32_t base, uint32_t limit, int dp break; } } + + + +void desc_intr(struct desc *desc, int type, uint16_t sel, uint32_t offs, int dpl) +{ + uint32_t gate_type[] = { GATE_TYPE_INTR, GATE_TYPE_TRAP }; + + desc->d[0] = (offs & 0xffff) | ((uint32_t)sel << 16); + desc->d[1] = (offs & 0xffff0000) | GATE_PRESENT | (dpl << 13) | gate_type[type]; +} diff --git a/sys1/kern/src/desc.h b/sys1/kern/src/desc.h index 9d9f700..e5e723b 100644 --- a/sys1/kern/src/desc.h +++ b/sys1/kern/src/desc.h @@ -8,7 +8,9 @@ struct desc { }; enum { SEG_NULL, SEG_CODE, SEG_DATA, SEG_TSS }; +enum { GATE_INTR, GATE_TRAP }; void desc_seg(struct desc *desc, int type, uint32_t base, uint32_t limit, int dpl); +void desc_intr(struct desc *desc, int type, uint16_t sel, uint32_t offs, int dpl); #endif /* DESC_H_ */ diff --git a/sys1/kern/src/intr.asm b/sys1/kern/src/intr.asm index dd35095..0d73c71 100644 --- a/sys1/kern/src/intr.asm +++ b/sys1/kern/src/intr.asm @@ -4,7 +4,14 @@ extern intr_handler PIC1_CMD_PORT equ 0x20 +PIC1_DATA_PORT equ 0x21 PIC2_CMD_PORT equ 0xa0 +PIC2_DATA_PORT equ 0xa1 + +ICW1_ICW4_NEEDED equ 0x01 +ICW1_INIT equ 0x10 +ICW4_8086 equ 0x01 + OCW2_EOI equ 0x20 OCW3_ISR equ 0x0b @@ -23,6 +30,48 @@ idtlim dw 0 idtbase dd 0 + global prog_pic +prog_pic: + ; send ICW1 saying we'll follow with ICW4 later + mov al, ICW1_INIT | ICW1_ICW4_NEEDED + out PIC1_CMD_PORT, al + ; send ICW2 with IRQ remapping + mov al, [esp + 4] + out PIC1_DATA_PORT, al + add al, 8 + out PIC2_DATA_PORT, al + ; send ICW3 to setup the master/slave relationship + ; ... set bit3 = 3rd interrupt input has a slave + mov al, 4 + out PIC1_DATA_PORT, al + ; ... set slave id to 2 + mov al, 2 + OUT PIC2_DATA_PORT, al + ; send ICW4 to set 8086 mode (no calls generated) + mov al, ICW4_8086 + out PIC1_DATA_PORT, al + out PIC2_DATA_PORT, al + ; done, reset the data port to 0 + xor al, al + out PIC1_DATA_PORT, al + out PIC2_DATA_PORT, al + ret + + + global end_of_irq +end_of_irq: + mov eax, [esp + 4] + cmp eax, 8 + jb .eoi_master + ; cascaded IRQ, send EOI to slave PIC first + mov al, OCW2_EOI + out PIC2_CMD_PORT, al +.eoi_master: ; send EOI to master PIC + mov al, OCW2_EOI + out PIC1_CMD_PORT, al + ret + + ; special entry point for IRQ7 to catch and disregard spurious interrupts global intr_entry_irq7_verify intr_entry_irq7_verify: @@ -54,12 +103,14 @@ intr_entry_irq15_verify: %macro intr_entry_err 2 + global intr_entry_%2 intr_entry_%2: push dword %1 ; push interrupt number jmp intr_entry_common %endmacro %macro intr_entry_noerr 2 + global intr_entry_%2 intr_entry_%2: push dword 0 ; push dummy error code push dword %1 ; push interrupt number @@ -89,7 +140,6 @@ intr_entry_common: intr_entry_err 12, stack intr_entry_err 13, prot intr_entry_err 14, page - intr_entry_noerr 15, rsvd intr_entry_noerr 16, fpu intr_entry_err 17, align intr_entry_noerr 18, mce diff --git a/sys1/kern/src/intr.c b/sys1/kern/src/intr.c index 5ce0009..dbd8faa 100644 --- a/sys1/kern/src/intr.c +++ b/sys1/kern/src/intr.c @@ -1,17 +1,84 @@ +#include #include "intr.h" #include "desc.h" +#include "mem.h" void set_idt(void *ptr, uint16_t lim); #define NUM_INTR 256 static struct desc idt[NUM_INTR] __attribute__((aligned(8))); +static void (*intr_func[NUM_INTR])(); + +static struct { + char *name; + int num; + void (*entry)(); +} intrtab[] = { + {"divide error", 0, intr_entry_div}, + {"debug exception", 1, intr_entry_debug}, + {"non-maskable interrupt", 2, intr_entry_nmi}, + {"breakpoint", 3, intr_entry_bpt}, + {"overflow", 4, intr_entry_ovf}, + {"bounds check", 5, intr_entry_bound}, + {"invalid opcode", 6, intr_entry_ill}, + {"missing coprocessor", 7, intr_entry_nodev}, + {"double fault", 8, intr_entry_dbl}, + {"coprocessor segment overrun", 9, intr_entry_copseg}, + {"invalid TSS", 10, intr_entry_tss}, + {"segment not present", 11, intr_entry_segpres}, + {"stack exception", 12, intr_entry_stack}, + {"general protection", 13, intr_entry_prot}, + {"page fault", 14, intr_entry_page}, + {"floating point error", 16, intr_entry_fpu}, + {"alignment check", 17, intr_entry_align}, + {"machine check", 18, intr_entry_mce}, + {"SIMD floating point error", 19, intr_entry_sse}, + {"IRQ 0 (timer)", 32, intr_entry_irq0}, + {"IRQ 1 (keyboard)", 33, intr_entry_irq1}, + {"IRQ 2 (cascade)", 34, intr_entry_irq2}, + {"IRQ 3 (UART 1)", 35, intr_entry_irq3}, + {"IRQ 4 (UART 0)", 36, intr_entry_irq4}, + {"IRQ 5", 37, intr_entry_irq5}, + {"IRQ 6 (floppy)", 38, intr_entry_irq6}, + {"IRQ 7 (parallel)", 39, intr_entry_irq7_verify}, + {"IRQ 8 (RTC)", 40, intr_entry_irq8}, + {"IRQ 9", 41, intr_entry_irq9}, + {"IRQ 10", 42, intr_entry_irq10}, + {"IRQ 11", 43, intr_entry_irq11}, + {"IRQ 12 (PS/2 mouse)", 44, intr_entry_irq12}, + {"IRQ 13 (coproc)", 45, intr_entry_irq13}, + {"IRQ 14 (ATA 0)", 46, intr_entry_irq14}, + {"IRQ 15 (ATA 1)", 47, intr_entry_irq15_verify} +}; void intr_init(void) { + int i, inum, type; + uint16_t sel_kcode = selector(SEL_KCODE, 0); + + prog_pic(IRQ_OFFS); + + for(i=0; i<256; i++) { + type = i < 32 ? GATE_TRAP : GATE_INTR; + desc_intr(idt + i, type, sel_kcode, (uint32_t)intr_entry_default, 0); + } + for(i=0; i= IRQ_OFFS) { + end_of_irq(num - IRQ_OFFS); + } +} diff --git a/sys1/kern/src/intr.h b/sys1/kern/src/intr.h index 10e3fe9..a4e1fde 100644 --- a/sys1/kern/src/intr.h +++ b/sys1/kern/src/intr.h @@ -3,6 +3,49 @@ #include "desc.h" +#define IRQ_OFFS 32 +#define IRQ_INTR(x) ((x) + IRQ_OFFS) + void intr_init(void); +void prog_pic(int offs); +void end_of_irq(int irq); + +void intr_entry_div(); +void intr_entry_debug(); +void intr_entry_nmi(); +void intr_entry_bpt(); +void intr_entry_ovf(); +void intr_entry_bound(); +void intr_entry_ill(); +void intr_entry_nodev(); +void intr_entry_dbl(); +void intr_entry_copseg(); +void intr_entry_tss(); +void intr_entry_segpres(); +void intr_entry_stack(); +void intr_entry_prot(); +void intr_entry_page(); +void intr_entry_fpu(); +void intr_entry_align(); +void intr_entry_mce(); +void intr_entry_sse(); +void intr_entry_irq0(); +void intr_entry_irq1(); +void intr_entry_irq2(); +void intr_entry_irq3(); +void intr_entry_irq4(); +void intr_entry_irq5(); +void intr_entry_irq6(); +void intr_entry_irq7_verify(); +void intr_entry_irq8(); +void intr_entry_irq9(); +void intr_entry_irq10(); +void intr_entry_irq11(); +void intr_entry_irq12(); +void intr_entry_irq13(); +void intr_entry_irq14(); +void intr_entry_irq15_verify(); +void intr_entry_default(); + #endif /* INTR_H_ */ diff --git a/sys1/kern/src/main.c b/sys1/kern/src/main.c index 8426a66..1a84caf 100644 --- a/sys1/kern/src/main.c +++ b/sys1/kern/src/main.c @@ -3,6 +3,7 @@ #include #include "vga.h" #include "mem.h" +#include "intr.h" void drawtext(int x, int y, const char *s) { diff --git a/sys1/kern/src/mem.asm b/sys1/kern/src/mem.asm index 3a4bf85..54c04f3 100644 --- a/sys1/kern/src/mem.asm +++ b/sys1/kern/src/mem.asm @@ -10,8 +10,26 @@ set_gdt: lgdt [gdtlim] ret + global setup_selectors +setup_selectors: + ; set data selectors directly + mov ax, [esp + 8] + mov ss, ax + mov es, ax + mov ds, ax + mov gs, ax + mov fs, ax + ; set cs with a long jump + mov ax, [esp + 4] + mov [jseg], ax + mov dword [joffs], .setcs + jmp far [joffs] +.setcs: ret + + align 4 - dw 0 +joffs dd 0 +jseg dw 0 gdtlim dw 0 gdtbase dd 0 diff --git a/sys1/kern/src/mem.c b/sys1/kern/src/mem.c index 92d6de9..b801a7d 100644 --- a/sys1/kern/src/mem.c +++ b/sys1/kern/src/mem.c @@ -3,19 +3,21 @@ void set_gdt(void *addr, uint16_t limit); -enum { - SEG_KCODE = 1, - SEG_KDATA = 2 -}; - -#define NUM_SEG 3 +#define NUM_SEG 3 static struct desc gdt[NUM_SEG] __attribute__((aligned(8))); void mem_init(void) { desc_seg(gdt, SEG_NULL, 0, 0, 0); - desc_seg(gdt + SEG_KCODE, SEG_CODE, 0, 0xffffffff, 0); - desc_seg(gdt + SEG_KDATA, SEG_DATA, 0, 0xffffffff, 0); + desc_seg(gdt + SEL_KCODE, SEG_CODE, 0, 0xffffffff, 0); + desc_seg(gdt + SEL_KDATA, SEG_DATA, 0, 0xffffffff, 0); set_gdt(gdt, sizeof gdt - 1); + + setup_selectors(selector(SEL_KCODE, 0), selector(SEL_KDATA, 0)); +} + +uint16_t selector(int idx, int rpl) +{ + return (idx << 3) | (rpl & 3); } diff --git a/sys1/kern/src/mem.h b/sys1/kern/src/mem.h index 1517e3e..5e76a6c 100644 --- a/sys1/kern/src/mem.h +++ b/sys1/kern/src/mem.h @@ -1,6 +1,18 @@ #ifndef MEM_H_ #define MEM_H_ +#include + +enum { + SEL_KCODE = 1, + SEL_KDATA = 2 +}; + void mem_init(void); +uint16_t selector(int idx, int rpl); + +/* defined in mem.asm */ +void setup_selectors(uint16_t code, uint16_t data); + #endif /* MEM_H_ */ -- 1.7.10.4