Like almost all of my questions, I feel like I'm missing something / I understood something the wrong way so help me figure out where I'm wrong with this.
When a Page Fault occurs and nt!KiTrap0E comes to save the day the CPU saves the current state, then it pushes the EIP of the faulting instruction and an error code on the stack (32 bits on x86, 64 bits on x64, but only bits 0, 1 and 2 are relevant here) and loads CR2 with the referenced virtual address? So, when we are in KiTrap06 the stack looks like this:
EIP of faulting instruction
Is this right?
So if I have the following code in user mode:
LPVOID address = VirtualAlloc(NULL, 1024, MEM_COMMIT, PAGE_READONLY); *(PDWORD)address = 12;
When the EIP will reach *(PDWORD)address = 12 (well, actually it will probably be mov address, 0x0B, but let's simplify things) a Page Fault will occur, the CPU will save the current state, will push the EIP of that assignment, then an error code will be pushed on the stack (bits 2, 1 and 0: 1 (user process) 1 (tried to write a page) 1 (and caused a protection fault) ), and load CR2 with the address allocated with VirtualAlloc? The handler will check the error code and the Read\Write byte from PDE (upper 10 bits of CR2) and/or (??) PTE (middle 10 bits of CR2), see that an attempt to write to a read only page was made and will terminate the faulting process?
If the page was writable but not loaded (last 3 bits of error code: 110) the handler will use the value from CR2 to bring the page into memory and the faulting instruction will be re-executed?