cpu: add irq depth counting

Add a way of checking if a cpu is in the middle of handling an irq and
how deep it is into it. This will allow for future code to conditionally
run only in/outside interrupts.
This commit is contained in:
Matheus
2026-10-06 10:58:37 -03:00
parent 6c65a90a5f
commit 011309d43d
3 changed files with 18 additions and 1 deletions
+4
View File
@@ -147,6 +147,8 @@ void arch_nmi_isr(context_t *ctx) {
uint64_t old_gsbase = rdmsr(MSR_GSBASE); uint64_t old_gsbase = rdmsr(MSR_GSBASE);
wrmsr(MSR_GSBASE, *(uint64_t *)(ctx + 1)); wrmsr(MSR_GSBASE, *(uint64_t *)(ctx + 1));
__atomic_fetch_add(&current_cpu()->irq_depth, 1, __ATOMIC_RELAXED);
bool handled = false; bool handled = false;
#ifdef ENABLE_PROFILING #ifdef ENABLE_PROFILING
@@ -157,6 +159,8 @@ void arch_nmi_isr(context_t *ctx) {
if (!handled) if (!handled)
_panic("Unhandled NMI", ctx); _panic("Unhandled NMI", ctx);
__atomic_fetch_sub(&current_cpu()->irq_depth, 1, __ATOMIC_RELAXED);
// restore the old gsbase // restore the old gsbase
wrmsr(MSR_GSBASE, old_gsbase); wrmsr(MSR_GSBASE, old_gsbase);
} }
+2
View File
@@ -30,6 +30,8 @@ typedef struct cpu_t {
uint64_t scratch; // expected to be here by other code 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_t *timekeeper_source;
timekeeper_source_info_t *timekeeper_source_info; timekeeper_source_info_t *timekeeper_source_info;
time_t timekeeper_source_base_ticks; time_t timekeeper_source_base_ticks;
+12 -1
View File
@@ -45,6 +45,7 @@ static void dopending(context_t *ctx, void *) {
arch_interrupt_disable(); arch_interrupt_disable();
bool entrystatus = current_cpu()->intstatus; bool entrystatus = current_cpu()->intstatus;
current_cpu()->intstatus = false; current_cpu()->intstatus = false;
__atomic_fetch_add(&current_cpu()->irq_depth, 1, __ATOMIC_RELAXED);
isr_t *list = NULL; isr_t *list = NULL;
isr_t *iterator = current_cpu()->isrqueue; isr_t *iterator = current_cpu()->isrqueue;
@@ -87,18 +88,25 @@ static void dopending(context_t *ctx, void *) {
} }
cleanup: cleanup:
__atomic_fetch_sub(&current_cpu()->irq_depth, 1, __ATOMIC_RELAXED);
if (entrystatus) { if (entrystatus) {
current_cpu()->intstatus = true; current_cpu()->intstatus = true;
arch_interrupt_enable(); 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) { void interrupt_isr(int vec, context_t *ctx) {
isr_t *isr = &current_cpu()->isr[vec]; isr_t *isr = &current_cpu()->isr[vec];
current_cpu()->intstatus = false; current_cpu()->intstatus = false;
if (isr->priority != IPL_IGNORE)
__atomic_fetch_add(&current_cpu()->irq_depth, 1, __ATOMIC_RELAXED);
if (isr->func == NULL) { if (isr->func == NULL) {
char oops[64]; char oops[64];
snprintf(oops, 64, "Unregistered interrupt %d\n", vec); snprintf(oops, 64, "Unregistered interrupt %d\n", vec);
@@ -116,6 +124,9 @@ void interrupt_isr(int vec, context_t *ctx) {
if (isr->eoi) if (isr->eoi)
isr->eoi(isr); isr->eoi(isr);
if (isr->priority != IPL_IGNORE)
__atomic_fetch_sub(&current_cpu()->irq_depth, 1, __ATOMIC_RELAXED);
if (ARCH_CONTEXT_ISUSER(ctx)) if (ARCH_CONTEXT_ISUSER(ctx))
sched_userspacecheck(ctx, false, 0, 0); sched_userspacecheck(ctx, false, 0, 0);