mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user