#include #include // Page fault upcall entrypoint. // This is where we ask the kernel to redirect us to whenever we cause // a page fault in user space (see the call to sys_set_pgfault_handler // in pgfault.c). // // 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 a UTrapframe onto our user // exception stack: // // trap-time esp // trap-time eflags // trap-time eip // utf_regs.reg_eax // ... // utf_regs.reg_esi // utf_regs.reg_edi // utf_err (error code) // utf_fault_va <-- %esp // // If this is a recursive fault, the kernel will reserve for us a // blank word above the trap-time esp for scratch work when we unwind // the recursive call. // // We then have call up to the appropriate page fault handler in C // code, pointed to by the global variable '_pgfault_handler'. .text .globl _pgfault_upcall _pgfault_upcall: // Call the C page fault handler. pushl %esp // function argument: pointer to UTF movl _pgfault_handler, %eax call *%eax addl $4, %esp // pop function argument // Now the C page fault handler has returned and you must return // to the trap time state. // Push trap-time %eip onto the trap-time stack. // // Explanation: // We must prepare the trap-time stack for our eventual return to // re-execute the instruction that faulted. // Unfortunately, we can't return directly from the exception stack: // We can't call 'jmp', since that requires that we load the address // into a register, and all registers must have their trap-time // values after the return. // We can't call 'ret' from the exception stack either, since if we // did, %esp would have the wrong value. // So instead, we push the trap-time %eip onto the *trap-time* stack! // Below we'll switch to that stack and call 'ret', which will // restore %eip to its pre-fault value. // // In the case of a recursive fault on the exception stack, // note that the word we're pushing now will fit in the // blank word that the kernel reserved for us. // // Hints: // What registers are available for intermediate calculations? // // LAB 4: Your code here. //R: increase esp first -- to simulate a push movl 48(%esp), %eax subl $4, %eax movl %eax, 48(%esp) //eax has trap time esp //R: put eip in the trap time frame movl 40(%esp), %ebx //ebx has trap-time eip movl %ebx, (%eax) addl $8, %esp popal; addl $4, %esp popfl; // Restore the trap-time registers. // LAB 4: Your code here. //movl 8(%esp), %edi //movl 12(%esp), %esi //movl 16(%esp), %ebp // 20(%esp) here should be esp but we do not move it yet //movl 24(%esp), %ebx //movl 28(%esp), %edx //movl 32(%esp), %ecx //movl 36(%esp), %eax // Restore eflags from the stack. // LAB 4: Your code here. //this is really bad hacking code cause I do not know how eflags is called! //addl $44, %esp # --> should say movl 44(%esp), %eflags //popfl //subl $48, %esp // Switch back to the adjusted trap-time stack. // LAB 4: Your code here. popl %esp // Return to re-execute the instruction that faulted. // LAB 4: Your code here. ret