From 5f84cdec3cb4b33bccb57794089762f23ca27285 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 23 Apr 2023 15:42:08 -0300 Subject: [PATCH] interrupt: basic ipl handling --- kernel-src/arch/x86-64/idt.c | 2 +- kernel-src/include/kernel/interrupt.h | 8 ++++++-- kernel-src/include/x86-64/arch/cpu.h | 1 + kernel-src/sys/interrupt.c | 28 +++++++++++++++++++-------- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/kernel-src/arch/x86-64/idt.c b/kernel-src/arch/x86-64/idt.c index 3d48ac88..d343d6bc 100644 --- a/kernel-src/arch/x86-64/idt.c +++ b/kernel-src/arch/x86-64/idt.c @@ -78,7 +78,7 @@ void arch_idt_reload() { // make sure to reserve the first 32 isrs for exceptions with a dummy panic isr for (int i = 0; i < 32; ++i) - interrupt_register(i, exceptisr, NULL, 0); // TODO assign priority + interrupt_register(i, exceptisr, NULL, IPL_MAX); } void arch_interrupt_disable() { diff --git a/kernel-src/include/kernel/interrupt.h b/kernel-src/include/kernel/interrupt.h index b0481e85..7eac1dbb 100644 --- a/kernel-src/include/kernel/interrupt.h +++ b/kernel-src/include/kernel/interrupt.h @@ -11,6 +11,11 @@ #error Unsupported architecture! #endif +#define IPL_MAX -1 +#define IPL_NONE 0 +#define IPL_TIMER 1 +#define IPL_BASE 1000 + struct _isr_t; typedef struct _isr_t { void (*func)(struct _isr_t *self, context_t *ctx); @@ -22,8 +27,7 @@ typedef struct _isr_t { void interrupt_register(int vector, void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority); isr_t *interrupt_allocate(void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority); -void interrupt_raiseipl(long newipl); -void interrupt_loweripl(long newipl); +long interrupt_setipl(long newipl); bool interrupt_set(bool status); #endif diff --git a/kernel-src/include/x86-64/arch/cpu.h b/kernel-src/include/x86-64/arch/cpu.h index 20931605..3890a86b 100644 --- a/kernel-src/include/x86-64/arch/cpu.h +++ b/kernel-src/include/x86-64/arch/cpu.h @@ -20,6 +20,7 @@ typedef struct { int acpiid; timer_t *timer; bool intstatus; + long ipl; } cpu_t; static inline cpu_t *_cpu() { diff --git a/kernel-src/sys/interrupt.c b/kernel-src/sys/interrupt.c index 07b47ef4..fbe57dc2 100644 --- a/kernel-src/sys/interrupt.c +++ b/kernel-src/sys/interrupt.c @@ -9,8 +9,18 @@ void interrupt_isr(int vec, context_t *ctx) { if (isr->func == NULL) _panic("Unregistered interrupt", ctx); - // TODO ipl check - isr->func(isr, ctx); + if (_cpu()->ipl < isr->priority) { + long oldipl = interrupt_setipl(isr->priority); + + bool oldint = interrupt_set(true); + isr->func(isr, ctx); + interrupt_set(false); + + _cpu()->intstatus = oldint; + interrupt_setipl(oldipl); + } else { + isr->pending = true; + } if (isr->eoi) isr->eoi(isr); @@ -22,6 +32,7 @@ void interrupt_register(int vector, void (*func)(isr_t *self, context_t *ctx), v isr->eoi = eoi; isr->id = (uint64_t)_cpu()->id << 32 | vector; isr->priority = priority; + isr->pending = false; } isr_t *interrupt_allocate(void (*func)(isr_t *self, context_t *ctx), void (*eoi)(isr_t *self), long priority) { @@ -38,14 +49,15 @@ isr_t *interrupt_allocate(void (*func)(isr_t *self, context_t *ctx), void (*eoi) return isr; } -// TODO ipl is thread level, write these when the scheduler is written +long interrupt_setipl(long ipl) { + bool oldintstatus = interrupt_set(false); + long oldipl = _cpu()->ipl; + _cpu()->ipl = ipl; + interrupt_set(oldintstatus); -void interrupt_raiseipl(long newipl) { - __assert(!"Unimplemented"); -} + // TODO do pending interrupts -void interrupt_loweripl(long newipl) { - __assert(!"Unimplemented"); + return oldipl; } void arch_interrupt_disable();