50 lines
1.3 KiB
C++
50 lines
1.3 KiB
C++
|
|
#include "memory/pagefault.h"
|
|
|
|
#include "arch/core.h"
|
|
#include "arch/core_interrupt.h"
|
|
#include "arch/idt.h"
|
|
#include "debug/output.h"
|
|
#include "memory/config.h"
|
|
|
|
namespace PageFault {
|
|
|
|
union ErrorCode {
|
|
uint32_t value;
|
|
struct {
|
|
uint32_t present : 1; ///< was the page present?
|
|
uint32_t write : 1; ///< was the access a write?
|
|
uint32_t usermode : 1; ///< was it in user mode?
|
|
uint32_t reserved : 1; ///< reserved bit violation
|
|
uint32_t instruction : 1; ///< was it caused by instruction fetch?
|
|
uint32_t : 0;
|
|
} __attribute__((packed));
|
|
|
|
explicit ErrorCode(uint32_t value) : value(value) {}
|
|
};
|
|
|
|
assert_size(ErrorCode, 4);
|
|
|
|
[[gnu::interrupt]] static void pagefault_handler(InterruptContext *context,
|
|
uint64_t err) {
|
|
PageFault::ErrorCode error(err);
|
|
// Get the faulting address
|
|
uintptr_t virt;
|
|
asm volatile("mov %%cr2, %0" : "=r"(virt));
|
|
DBG << "Page fault at " << hex << virt << dec << endl;
|
|
|
|
// show page fault message
|
|
DBG << "PAGEFAULT: " << hex << virt << ":" << dec << error.present
|
|
<< error.write << error.usermode << error.reserved << error.instruction
|
|
<< " @ " << hex << context->ip << endl;
|
|
|
|
Core::die();
|
|
}
|
|
|
|
void init() {
|
|
IDT::set(Core::Interrupt::Vector::PAGE_FAULT,
|
|
IDT::InterruptDescriptor::ReturningWithError(pagefault_handler));
|
|
}
|
|
|
|
} // namespace PageFault
|