diff --git a/kernel-src/arch/x86-64/cpu.c b/kernel-src/arch/x86-64/cpu.c index d8f84f07..33d8e05c 100644 --- a/kernel-src/arch/x86-64/cpu.c +++ b/kernel-src/arch/x86-64/cpu.c @@ -147,6 +147,8 @@ void arch_nmi_isr(context_t *ctx) { uint64_t old_gsbase = rdmsr(MSR_GSBASE); wrmsr(MSR_GSBASE, *(uint64_t *)(ctx + 1)); + __atomic_fetch_add(¤t_cpu()->irq_depth, 1, __ATOMIC_RELAXED); + bool handled = false; #ifdef ENABLE_PROFILING @@ -157,6 +159,8 @@ void arch_nmi_isr(context_t *ctx) { if (!handled) _panic("Unhandled NMI", ctx); + __atomic_fetch_sub(¤t_cpu()->irq_depth, 1, __ATOMIC_RELAXED); + // restore the old gsbase wrmsr(MSR_GSBASE, old_gsbase); } diff --git a/kernel-src/include/x86-64/arch/cpu.h b/kernel-src/include/x86-64/arch/cpu.h index 2de21908..3dd5dda4 100644 --- a/kernel-src/include/x86-64/arch/cpu.h +++ b/kernel-src/include/x86-64/arch/cpu.h @@ -30,6 +30,8 @@ typedef struct cpu_t { uint64_t scratch; // expected to be here by other code + unsigned long irq_depth; // expected to be here by other code + timekeeper_source_t *timekeeper_source; timekeeper_source_info_t *timekeeper_source_info; time_t timekeeper_source_base_ticks; diff --git a/kernel-src/sys/interrupt.c b/kernel-src/sys/interrupt.c index 9367d367..d64887c9 100644 --- a/kernel-src/sys/interrupt.c +++ b/kernel-src/sys/interrupt.c @@ -45,6 +45,7 @@ static void dopending(context_t *ctx, void *) { arch_interrupt_disable(); bool entrystatus = current_cpu()->intstatus; current_cpu()->intstatus = false; + __atomic_fetch_add(¤t_cpu()->irq_depth, 1, __ATOMIC_RELAXED); isr_t *list = NULL; isr_t *iterator = current_cpu()->isrqueue; @@ -87,18 +88,25 @@ static void dopending(context_t *ctx, void *) { } cleanup: + __atomic_fetch_sub(¤t_cpu()->irq_depth, 1, __ATOMIC_RELAXED); if (entrystatus) { current_cpu()->intstatus = true; arch_interrupt_enable(); } } -__attribute__((no_caller_saved_registers)) void sched_userspacecheck(context_t *context, bool syscall, uint64_t syscallret, uint64_t syscallerrno); +__attribute__((no_caller_saved_registers)) void sched_userspacecheck(context_t *context, + bool syscall, + uint64_t syscallret, + uint64_t syscallerrno); void interrupt_isr(int vec, context_t *ctx) { isr_t *isr = ¤t_cpu()->isr[vec]; current_cpu()->intstatus = false; + if (isr->priority != IPL_IGNORE) + __atomic_fetch_add(¤t_cpu()->irq_depth, 1, __ATOMIC_RELAXED); + if (isr->func == NULL) { char oops[64]; snprintf(oops, 64, "Unregistered interrupt %d\n", vec); @@ -116,6 +124,9 @@ void interrupt_isr(int vec, context_t *ctx) { if (isr->eoi) isr->eoi(isr); + if (isr->priority != IPL_IGNORE) + __atomic_fetch_sub(¤t_cpu()->irq_depth, 1, __ATOMIC_RELAXED); + if (ARCH_CONTEXT_ISUSER(ctx)) sched_userspacecheck(ctx, false, 0, 0);