From f290314f286b70a8f59becedd5f789c21f675b5d Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 20 Jun 2024 20:35:38 -0400 Subject: kernel/amd64: intr: Add splraise/splx support Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/intr.c | 63 ++++++++++++++++++++++++++++++++++++++++--- sys/arch/amd64/amd64/lapic.c | 2 +- sys/include/arch/amd64/asm.h | 14 ++++++++++ sys/include/arch/amd64/cpu.h | 1 + sys/include/arch/amd64/intr.h | 19 ++++++++++++- 5 files changed, 93 insertions(+), 6 deletions(-) (limited to 'sys') diff --git a/sys/arch/amd64/amd64/intr.c b/sys/arch/amd64/amd64/intr.c index b841da7..3e3f309 100644 --- a/sys/arch/amd64/amd64/intr.c +++ b/sys/arch/amd64/amd64/intr.c @@ -28,16 +28,71 @@ */ #include +#include +#include +#include #include +#include +#include +#include + +static struct intr_entry *intrs[256] = {0}; + +void +splraise(uint8_t s) +{ + struct cpu_info *ci = this_cpu(); + + if (s < ci->ipl) { + panic("splraise IPL less than current IPL\n"); + } + + amd64_write_cr8(s); + ci->ipl = s; +} + +void +splx(uint8_t s) +{ + struct cpu_info *ci = this_cpu(); + + if (s > ci->ipl) { + panic("splx IPL greater than current IPL\n"); + } + + amd64_write_cr8(s); + ci->ipl = s; +} int -intr_alloc_vector(void) +intr_alloc_vector(const char *name, uint8_t priority) { - static size_t vec = 0x21; + size_t vec = MAX(priority << IPL_SHIFT, 0x20); + struct intr_entry *intr; - if (vec >= 0xFF) { + /* Sanity check */ + if (vec > NELEM(intrs)) { return -1; } - return vec++; + /* + * Try to allocate an interrupt vector. An IPL is made up + * of 4 bits so there can be 16 vectors per IPL. + */ + for (int i = vec; i < vec + 16; ++i) { + if (intrs[i] != NULL) { + continue; + } + + intr = dynalloc(sizeof(*intr)); + if (intr == NULL) { + return -ENOMEM; + } + + intr->priority = priority; + intrs[i] = intr; + return i; + } + + return -1; } diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c index b7cefd4..896c2bd 100644 --- a/sys/arch/amd64/amd64/lapic.c +++ b/sys/arch/amd64/amd64/lapic.c @@ -317,7 +317,7 @@ lapic_init(void) /* Allocate a vector if needed */ if (lapic_timer_vec == 0) { - lapic_timer_vec = intr_alloc_vector(); + lapic_timer_vec = intr_alloc_vector("lapictmr", IPL_CLOCK); idt_set_desc(lapic_timer_vec, IDT_INT_GATE, ISR(lapic_tmr_isr), IST_SCHED); } diff --git a/sys/include/arch/amd64/asm.h b/sys/include/arch/amd64/asm.h index d7334fe..e85dd87 100644 --- a/sys/include/arch/amd64/asm.h +++ b/sys/include/arch/amd64/asm.h @@ -84,6 +84,20 @@ amd64_write_cr0(uint64_t val) __ASMV("mov %0, %%cr0" :: "r" (val) : "memory"); } +static inline uint64_t +amd64_read_cr8(void) +{ + uint64_t cr8; + __ASMV("mov %%cr8, %0" : "=r" (cr8) :: "memory"); + return cr8; +} + +static inline void +amd64_write_cr8(uint64_t val) +{ + __ASMV("mov %0, %%cr8" :: "r" (val) : "memory"); +} + static inline uint64_t amd64_read_cr4(void) { diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h index b5420a6..16936e9 100644 --- a/sys/include/arch/amd64/cpu.h +++ b/sys/include/arch/amd64/cpu.h @@ -38,6 +38,7 @@ struct cpu_info { uint32_t apicid; uint8_t has_x2apic : 1; + uint8_t ipl; size_t lapic_tmr_freq; struct tss_entry *tss; struct proc *curtd; diff --git a/sys/include/arch/amd64/intr.h b/sys/include/arch/amd64/intr.h index 3f0da77..af5edf2 100644 --- a/sys/include/arch/amd64/intr.h +++ b/sys/include/arch/amd64/intr.h @@ -36,6 +36,23 @@ #define IST_HW_IRQ 2U #define IST_SW_INT 3U -int intr_alloc_vector(void); +/* Upper 4 bits of interrupt vector */ +#define IPL_SHIFT 4 + +/* + * Interrupt priority levels + */ +#define IPL_NONE 0 /* Don't defer anything */ +#define IPL_BIO 1 /* Block I/O */ +#define IPL_CLOCK 2 /* Clock */ +#define IPL_HIGH 3 /* Defer everything */ + +struct intr_entry { + int priority; +}; + +int intr_alloc_vector(const char *name, uint8_t priority); +void splraise(uint8_t s); +void splx(uint8_t s); #endif -- cgit v1.2.3