#include #include // Page fault handler entrypoint - // this is where we ask the kernel // (by calling sys_set_pgfault_handler in pgfault.c) // to redirect us to whenever we cause a page fault in user space. // // When a page fault actually occurs, // the kernel switches our ESP to point to the user exception stack // if we're not already on the user exception stack, // and then it pushes the following minimal trap frame // onto our user exception stack: // // [ 5 spare words ] // trap-time eip // trap-time eflags // trap-time esp // trap-time errcode // trap-time va <-- %esp // // We then have to save additional callee-saved registers // and call up to the appropriate page fault handler in C code, // pointed to by the global variable '_pgfault_handler' declared above. .text .globl _pgfault_entry _pgfault_entry: // Save the caller-save registers // (your code here) movl %ecx, 20(%esp) movl %edx, 24(%esp) movl %eax, 28(%esp) // Call the C page fault handler movl _pgfault_handler, %eax call *%eax // Push trap-time eip and eflags onto trap-time stack. // In the case of a recursive fault on the exception stack, // note that the two words we're pushing now // overlap with the exception frame we're currently using! // Push eax too, so we can restore it. Not the most efficient // use of stack space, but it works. movl 8(%esp), %eax movl 12(%esp), %ecx movl %ecx, -4(%eax) movl %cs, -8(%eax) movl 16(%esp), %ecx movl %ecx, -12(%eax) movl 28(%esp), %ecx movl %ecx, -16(%eax) subl $16, %eax // Restore the caller-save registers. movl 20(%esp), %ecx movl 24(%esp), %edx // Switch back to the trap-time stack. movl %eax, %esp popl %eax // Restore eflags and eip from the stack. iret