2 #include <inc/memlayout.h>
5 // Page fault upcall entrypoint.
7 // This is where we ask the kernel to redirect us to whenever we cause
8 // a page fault in user space (see the call to sys_set_pgfault_handler
11 // When a page fault actually occurs, the kernel switches our ESP to
12 // point to the user exception stack if we're not already on the user
13 // exception stack, and then it pushes a UTrapframe onto our user
23 // utf_err (error code)
24 // utf_fault_va <-- %esp
26 // If this is a recursive fault, the kernel will reserve for us a
27 // blank word above the trap-time esp for scratch work when we unwind
28 // the recursive call.
30 // We then have call up to the appropriate page fault handler in C
31 // code, pointed to by the global variable '_pgfault_handler'.
34 .globl _pgfault_upcall
36 // Call the C page fault handler.
37 pushl %esp // function argument: pointer to UTF
38 movl _pgfault_handler, %eax
40 addl $4, %esp // pop function argument
42 // Now the C page fault handler has returned and you must return
43 // to the trap time state.
44 // Push trap-time %eip onto the trap-time stack.
47 // We must prepare the trap-time stack for our eventual return to
48 // re-execute the instruction that faulted.
49 // Unfortunately, we can't return directly from the exception stack:
50 // We can't call 'jmp', since that requires that we load the address
51 // into a register, and all registers must have their trap-time
52 // values after the return.
53 // We can't call 'ret' from the exception stack either, since if we
54 // did, %esp would have the wrong value.
55 // So instead, we push the trap-time %eip onto the *trap-time* stack!
56 // Below we'll switch to that stack and call 'ret', which will
57 // restore %eip to its pre-fault value.
59 // In the case of a recursive fault on the exception stack,
60 // note that the word we're pushing now will fit in the
61 // blank word that the kernel reserved for us.
64 // What registers are available for intermediate calculations?
66 // ignore 'fault_va' and 'tf_err'
68 // store the current esp
70 // store trap-time esp
72 // store trap-time eip
74 // change to trap-time esp
76 // push trap-time eip to the trap-time stack
78 // back to the user exception stack
80 // the trap-time esp should be decremented by 4
82 // change trap-time esp
84 // restore all the general registers
86 // ignore trap-time eip
90 // into the trap-time stack