My paging implementation is largely from JamesM's series. Currently, when we encounter a page fault, we print out some debug info and halt execution, however this clearly isn't optimal. I'm trying to recover from a page fault and continue execution as if nothing happened. My current page fault handler is below. As you can see, if the page exists, then we allocate the page and simply return. When I run this (specifically, the iret), I get a general protection fault, indicating that my attempt at recovery doesn't work.
Code: Select all
void alloc_frame(page_t* page, int is_kernel, int is_writeable);
page_t* get_page(uint32_t address, int make, page_directory_t* dir);
void page_fault(registers_t* regs) {
switch_to_text();
//page fault has occured
//faulting address is stored in CR2 register
uint32_t faulting_address;
asm volatile("mov %%cr2, %0" : "=r" (faulting_address));
//error code tells us what happened
int present = !(regs->err_code & 0x1); //page not present
int rw = regs->err_code & 0x2; //write operation?
int us = regs->err_code & 0x4; //were we in user mode?
int reserved = regs->err_code & 0x8; //overwritten CPU-reserved bits of page entry?
int id = regs->err_code & 0x10; //caused by instruction fetch?
printf_err("Encountered page fault at %x. Info follows", faulting_address);
if (present) printf_err("Page was present");
else printf_err("Page was not present");
if (rw) printf_err("Operation was a write");
else printf_err("Operation was a read");
if (us) printf_err("User mode");
else printf_err("Supervisor mode");
if (reserved) printf_err("Overwrote CPU-resereved bits of page entry");
if (id) printf_err("Faulted during instruction fetch");
if (regs->eip != faulting_address) {
printf_err("Page fault caused by executing unpaged memory");
}
else {
printf_err("Page fault caused by reading unpaged memory");
}
//if this page was present, attempt to recover by allocating the page
if (present) {
alloc_frame(get_page(faulting_address, !present, current_directory), !us, rw);
asm volatile("iret");
return;
}
common_halt(®s);
}
Thanks!