2018-10-06 06:52:47 -07:00
|
|
|
// User-level page fault handler support.
|
|
|
|
// Rather than register the C page fault handler directly with the
|
|
|
|
// kernel as the page fault handler, we register the assembly language
|
|
|
|
// wrapper in pfentry.S, which in turns calls the registered C
|
|
|
|
// function.
|
|
|
|
|
|
|
|
#include <inc/lib.h>
|
|
|
|
|
|
|
|
|
|
|
|
// Assembly language pgfault entrypoint defined in lib/pfentry.S.
|
|
|
|
extern void _pgfault_upcall(void);
|
|
|
|
|
|
|
|
// Pointer to currently installed C-language pgfault handler.
|
|
|
|
void (*_pgfault_handler)(struct UTrapframe *utf);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set the page fault handler function.
|
|
|
|
// If there isn't one yet, _pgfault_handler will be 0.
|
|
|
|
// The first time we register a handler, we need to
|
|
|
|
// allocate an exception stack (one page of memory with its top
|
|
|
|
// at UXSTACKTOP), and tell the kernel to call the assembly-language
|
|
|
|
// _pgfault_upcall routine when a page fault occurs.
|
|
|
|
//
|
|
|
|
void
|
|
|
|
set_pgfault_handler(void (*handler)(struct UTrapframe *utf))
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (_pgfault_handler == 0) {
|
2019-05-05 19:42:15 -07:00
|
|
|
if(sys_page_alloc(0, (void*) UXSTACKTOP - PGSIZE, PTE_U | PTE_P | PTE_W) < 0)
|
|
|
|
panic("set_pgfault_handler");
|
|
|
|
sys_env_set_pgfault_upcall(0, _pgfault_upcall);
|
2018-10-06 06:52:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Save handler pointer for assembly to call.
|
|
|
|
_pgfault_handler = handler;
|
|
|
|
}
|