From a9f490b4313c629af74838cda065e67ef58dbd16 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sat, 8 Apr 2023 20:13:51 -0300 Subject: [PATCH] kernel: initial interrupt abstraction implementation --- kernel-src/include/kernel/interrupt.h | 26 +++++++++++++++ kernel-src/include/x86-64/arch/cpu.h | 4 ++- kernel-src/sys/interrupt.c | 47 +++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 kernel-src/include/kernel/interrupt.h create mode 100644 kernel-src/sys/interrupt.c diff --git a/kernel-src/include/kernel/interrupt.h b/kernel-src/include/kernel/interrupt.h new file mode 100644 index 00000000..9db5eff4 --- /dev/null +++ b/kernel-src/include/kernel/interrupt.h @@ -0,0 +1,26 @@ +#ifndef _INTERRUPT_H +#define _INTERRUPT_H + +#include + +#ifdef __x86_64__ + #define MAX_ISR_COUNT 256 +#else + #error Unsupported architecture! +#endif + +struct _isr_t; +typedef struct _isr_t { + void (*func)(struct _isr_t *self); // TODO pass register context as argument as well. + void (*eoi)(struct _isr_t *self); + long id; + long priority; + bool pending; +} isr_t; + +void interrupt_register(int vector, void (*func)(isr_t *self), void (*eoi)(isr_t *self), long priority); // TODO pass register context as well. +isr_t *interrupt_allocate(void (*func)(isr_t *self), void (*eoi)(isr_t *self), long priority); // TODO pass register context as well. +void interrupt_raiseipl(long newipl); +void interrupt_loweripl(long newipl); + +#endif diff --git a/kernel-src/include/x86-64/arch/cpu.h b/kernel-src/include/x86-64/arch/cpu.h index 470ca745..1c3bdae8 100644 --- a/kernel-src/include/x86-64/arch/cpu.h +++ b/kernel-src/include/x86-64/arch/cpu.h @@ -6,11 +6,13 @@ #include #include +#include typedef struct { uint64_t gdt[7]; ist_t ist; - int lapicid; + long id; + isr_t isr[MAX_ISR_COUNT]; } cpu_t; static inline cpu_t *_cpu() { diff --git a/kernel-src/sys/interrupt.c b/kernel-src/sys/interrupt.c new file mode 100644 index 00000000..a9dc3add --- /dev/null +++ b/kernel-src/sys/interrupt.c @@ -0,0 +1,47 @@ +#include +#include +#include + +// TODO pass register context as well +void interrupt_isr(int vec) { + isr_t *isr = &_cpu()->isr[vec]; + // TODO ipl check + isr->func(isr); // TODO pass context + + if (isr->eoi) + isr->eoi(isr); +} + +// TODO pass register context as well. +void interrupt_register(int vector, void (*func)(isr_t *self), void (*eoi)(isr_t *self), long priority) { + isr_t *isr = &_cpu()->isr[vector]; + isr->func = func; + isr->eoi = eoi; + isr->id = _cpu()->id << 32 | vector; + isr->priority = priority; +} + +// TODO pass register context as well. +isr_t *interrupt_allocate(void (*func)(isr_t *self), void (*eoi)(isr_t *self), long priority) { + isr_t *isr = NULL; + + for (int i = 0; i < MAX_ISR_COUNT; ++i) { + if (_cpu()->isr[i].func == NULL) { + isr = &_cpu()->isr[i]; + interrupt_register(i, func, eoi, priority); + break; + } + } + + return isr; +} + +// TODO ipl is thread level, write these when the scheduler is written + +void interrupt_raiseipl(long newipl) { + __assert(!"Unimplemented"); +} + +void interrupt_loweripl(long newipl) { + __assert(!"Unimplemented"); +}