This commit is contained in:
2026-09-28 17:46:45 +02:00
committed by Marvin Friedrich
parent 09926f45ee
commit 4a20a5b0af
62 changed files with 1266 additions and 554 deletions
+53 -11
View File
@@ -5,6 +5,9 @@
#include <zinnia/percpu.h>
#include <zinnia/print.h>
#include <zinnia/sched.h>
#include <zinnia/usercopy.h>
#include <zinnia/utils.h>
#include <zinnia/vma.h>
#include <arch/sched.h>
#include <bits/sched.h>
#include <stddef.h>
@@ -36,29 +39,68 @@ static_assert(sizeof(struct idtr) == 10);
void interrupt_handler(struct arch_context* ctx) {
struct percpu* cpu = percpu_get();
struct arch_percpu* arch_cpu = percpu_ref(arch_data);
bool old = irq_set_interrupted(true);
uint64_t isr = ctx->isr;
switch (isr) {
case IDT_PF:
uint64_t cr2;
asm volatile("mov %0, cr2" : "=r"(cr2));
panic("Page fault at %#lx, accessed: %#lx\n", ctx->rip, cr2);
case IDT_IPI_RESCHED:
arch_sched_preempt_disable();
if (arch_sched_preempt_enable()) {
lapic_eoi(&arch_cpu->lapic);
sched_reschedule(&cpu->sched);
const struct vma_fault_info info = {
.ip = ctx->rip,
.addr = cr2,
.caused_by_user = (ctx->cs & CPL_USER) == CPL_USER,
.caused_by_write = ctx->error & (1 << 1),
.caused_by_fetch = ctx->error & (1 << 4),
.page_was_present = ctx->error & (1 << 0),
};
struct task* current = cpu->sched.current;
const bool irqs_were_on = ctx->rflags & RFLAGS_IF;
if (irqs_were_on)
irq_set_state(true);
const bool handled = current && current->space && vma_page_fault(current->space, &info);
if (irqs_were_on)
irq_set_state(false);
if (handled)
break;
if (current && current->usercopy_region) {
struct usercopy_region* region = current->usercopy_region;
if (ctx->rip >= (uintptr_t)region->start_ip && ctx->rip < (uintptr_t)region->end_ip) {
ctx->rip = (uintptr_t)region->fault_ip;
break;
}
}
panic(
"Unrecoverable page fault. Attempted to %s a %s page at %#lx (IP: %#lx)\n",
info.caused_by_write ? "write to"
: info.caused_by_fetch ? "execute on"
: "read from",
info.page_was_present ? "present" : "non-present",
info.addr,
info.ip
);
case IDT_SPURIOUS:
break;
case IDT_IPI_RESCHED:
lapic_eoi(&arch_cpu->lapic);
arch_sched_preempt_disable();
if (arch_sched_preempt_enable())
sched_reschedule(&cpu->sched);
break;
default:
if (isr < 0x20)
panic("Unhandled exception %lu at %#lx, error: %#lx\n", isr, ctx->rip, ctx->error);
assert(isr - 0x20 < ARRAY_SIZE(arch_cpu->irq_lines), "Unhandled interrupt on ISR %lu\n", isr);
struct irq_line* line = arch_cpu->irq_lines[isr - 0x20];
assert(line, "Unhandled interrupt on ISR %lu\n", isr);
// TODO: irq_raise(line);
irq_line_raise(line);
}
irq_set_interrupted(old);
}
#define CS_OFFSET (sizeof(struct arch_context) - sizeof(uint64_t) - offsetof(struct arch_context, cs))