diff --git a/arch/x86_64/irq.c b/arch/x86_64/irq.c index 320bd8e..d613aef 100644 --- a/arch/x86_64/irq.c +++ b/arch/x86_64/irq.c @@ -9,7 +9,13 @@ #include #include -#define MAX_ISR_HANDLERS 16 +#define MAX_ISR_HANDLERS 16 + +#define PF_PRESENT 0x01u +#define PF_WRITE 0x02u +#define PF_USER 0x04u +#define PF_RESERVED_WRITE 0x08u +#define PF_IFETCH 0x10u extern void syscall_gate(void); extern uintptr_t pf_faultptr(void); @@ -79,10 +85,31 @@ static void gpf_handler(struct ml_cpu_context *regs) static void pf_handler(struct ml_cpu_context *regs) { + enum pmap_fault_flags fault_flags = 0; + + (regs->err_no & PF_PRESENT) && (fault_flags |= PMAP_FAULT_PRESENT); + (regs->err_no & PF_USER) && (fault_flags |= PMAP_FAULT_USER); + (regs->err_no & PF_WRITE) && (fault_flags |= PMAP_FAULT_WRITE); + (regs->err_no & PF_IFETCH) && (fault_flags |= PMAP_FAULT_IFETCH); + (regs->err_no & PF_RESERVED_WRITE) + && (fault_flags |= PMAP_FAULT_BADCFG); + + virt_addr_t fault_ptr = pf_faultptr(); + + kern_status_t status = KERN_FATAL_ERROR; + + if (regs->err_no & PF_USER) { + status = pmap_handle_fault(fault_ptr, fault_flags); + } + + if (status == KERN_OK) { + return; + } + panic_irq( regs, "page fault (%016llx %016llx %016llx)", - pf_faultptr(), + fault_ptr, regs->rip, regs->err_no); }