diff --git a/kernel/dev/ps2kbdev.c b/kernel/dev/ps2kbdev.c index e34b447..ae2a227 100644 --- a/kernel/dev/ps2kbdev.c +++ b/kernel/dev/ps2kbdev.c @@ -8,6 +8,7 @@ #include "proc/proc.h" #include "io/io.h" #include "ipc/mbus/mbus.h" +#include "intr/intr.h" #include "errors.h" #include "hshtb.h" #include "kprintf.h" @@ -155,12 +156,16 @@ int32_t ps2kb_intr(void) { IpcMBus *PS2KB_MBUS; -void ps2kbdev_intr(void) { +int ps2kbdev_intr(IntrStackFrame *frame) { + (void)frame; + int32_t c = ps2kb_intr(); if (c >= 0) { uint8_t b = c; ipc_mbuspublish("ps2kb", &b); } + + return INTR_OK; } void ps2kbdev_init(void) { diff --git a/kernel/intr/intr.c b/kernel/intr/intr.c index cde9b7a..e60bca3 100644 --- a/kernel/intr/intr.c +++ b/kernel/intr/intr.c @@ -19,17 +19,39 @@ typedef struct IntrHandler { struct IntrHandler *next; - void (*fn)(void); + int (*fn)(IntrStackFrame *frame); int irq; } IntrHandler; IntrHandler *INTR_HANDLERS = NULL; +SpinLock INTR_HANDLERS_SPINLOCK; -void intr_attchhandler(void (*fn)(void), int irq) { +void intr_attchhandler(int (*fn)(IntrStackFrame *frame), int irq) { IntrHandler *ih = dlmalloc(sizeof(*ih)); ih->fn = fn; ih->irq = irq; + spinlock_acquire(&INTR_HANDLERS_SPINLOCK); LL_APPEND(INTR_HANDLERS, ih); + spinlock_release(&INTR_HANDLERS_SPINLOCK); +} + +int32_t intr_dttchhandler(int irq) { + IntrHandler *ih = NULL; + + spinlock_acquire(&INTR_HANDLERS_SPINLOCK); + + LL_FINDPROP(INTR_HANDLERS, ih, irq, irq); + + if (ih == NULL) { + spinlock_release(&INTR_HANDLERS_SPINLOCK); + return E_NOENTRY; + } + + LL_REMOVE(INTR_HANDLERS, ih); + spinlock_release(&INTR_HANDLERS_SPINLOCK); + + dlfree(ih); + return E_OK; } typedef struct BackTraceFrame { @@ -104,6 +126,8 @@ static const char *exceptions[] = { }; void intr_init(void) { + spinlock_init(&INTR_HANDLERS_SPINLOCK); + #define MKINTR(N) \ extern void intr_vec##N(void); \ idt_setentry(N, (uint64_t)&intr_vec##N, 0x8E); @@ -222,22 +246,16 @@ void intr_handleintr(IntrStackFrame *frame) { cpu_hang(); } } else if (frame->trapnum >= 32 && frame->trapnum <= 47) { - switch (frame->trapnum) { - case INTR_IRQBASE+0: - PIT_TICKS++; - intr_pic_eoi(); - proc_sched((void *)frame); - break; - default: - IntrHandler *ih, *ihtmp; - LL_FOREACH_SAFE(INTR_HANDLERS, ih, ihtmp) { - if ((uint64_t)ih->irq == frame->trapnum) { - ih->fn(); - } + bool send = true; + IntrHandler *ih, *ihtmp; + LL_FOREACH_SAFE(INTR_HANDLERS, ih, ihtmp) { + if ((uint64_t)ih->irq == frame->trapnum) { + if (ih->fn(frame) == INTR_NOEOI) { + send = false; } - intr_pic_eoi(); - break; + } } + if (send) intr_pic_eoi(); } else if (frame->trapnum == 0x80) { intr_syscalldispatch(frame); } diff --git a/kernel/intr/intr.h b/kernel/intr/intr.h index 5445d6c..53d5212 100644 --- a/kernel/intr/intr.h +++ b/kernel/intr/intr.h @@ -2,10 +2,14 @@ #define INTR_INTR_H_ #include +#include #include "compiler/attr.h" #define INTR_IRQBASE 0x20 +#define INTR_OK 1 +#define INTR_NOEOI 2 + typedef struct { uint64_t r15; uint64_t r14; @@ -34,7 +38,8 @@ typedef struct { uint64_t ss; } PACKED IntrStackFrame; -void intr_attchhandler(void (*fn)(void), int irq); +void intr_attchhandler(int (*fn)(IntrStackFrame *frame), int irq); +int32_t intr_dttchhandler(int irq); void intr_disable(void); void intr_enable(void); void intr_init(void); diff --git a/kernel/intr/pit.c b/kernel/intr/pit.c index 9046365..5602a51 100644 --- a/kernel/intr/pit.c +++ b/kernel/intr/pit.c @@ -1,6 +1,7 @@ #include #include "intr/pit.h" #include "io/io.h" +#include "intr/intr.h" #define PIT_COUNTER0 0x40 #define PIT_CMD 0x43 @@ -25,15 +26,22 @@ volatile uint32_t PIT_TICKS; +void intr_pit_wait(uint32_t ms) { + uint32_t now = PIT_TICKS; + while (PIT_TICKS - now < ms); +} + +int intr_pit_intr(IntrStackFrame *frame) { + PIT_TICKS++; + return INTR_OK; +} + void intr_pit_init(void) { + intr_attchhandler(&intr_pit_intr, INTR_IRQBASE+0); + uint32_t hz = 1000; uint32_t div = PIT_FREQ / hz; io_out8(PIT_CMD, PIT_CMD_BINARY | PIT_CMD_MODE3 | PIT_CMD_RW_BOTH | PIT_CMD_COUNTER0); io_out8(PIT_COUNTER0, div & 0xFF); io_out8(PIT_COUNTER0, div >> 8); } - -void intr_pit_wait(uint32_t ms) { - uint32_t now = PIT_TICKS; - while (PIT_TICKS - now < ms); -} diff --git a/kernel/kmain.c b/kernel/kmain.c index 3d8201e..d150194 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -45,9 +45,9 @@ void kmain(void) { log_bootinfo(); log_time(); gdt_init(); - intr_init(); pmm_init(); vmm_init(); + intr_init(); randcrypto_init(); ipc_mbusinit(); dev_init(); diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 22d18ec..1d47a3e 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -16,8 +16,9 @@ #include "std/string.h" #include "cpu/gdt.h" #include "intr/intr.h" -#include "switch.h" +#include "intr/pic.h" #include "vmm/vmm.h" +#include "proc/switch.h" #include "elf.h" #include "errors.h" #include "kprintf.h" @@ -252,10 +253,18 @@ void proc_killself(void) { proc_kill(proc); } +int proc_intr(IntrStackFrame *frame) { + intr_pic_eoi(); + proc_sched(frame); + return INTR_NOEOI; +} + void proc_init(void) { spinlock_init(&PROCS.spinlock); PROCS.procs = NULL; + intr_attchhandler(&proc_intr, INTR_IRQBASE+0); + Proc *init = proc_spawnuser("base", "/bin/init"); PROCS.current = init; proc_register(init);