First post, by superfury
When executing a jmp, call or interrupt/iret, the processor docs say that it checks the limit and type against the jump and the destination (E)IP, faulting if it does.
But what happens with the paging part of the transfer? The PIQ is obviously flushed, so needs to fetch new data. Are paging structures only referenced and faulted on once the new instruction is started(in other words, the jmp/call/int/iret has already finished executing)? So for instruction fetching-type page faults (compared to data-type page faults for referencing a non-canonical address as a parameter) the page fault and TLB/pagetable walk only happens when the next instruction starts, which starts to fetch new instructions from memory after said walk is complete(if not in the TLB already for the CPL and page rights)?
So instructions act like this:
1. JMP/CALL/INT/IRET loads EIP and finds it's limit&type valid. Doesn't fault, thus commits modified registers(instead of faulting rollback). Instruction is finished after this.
2. Processor checks for trap flag to be taken or not. If taken, step 1 happens after firing said interrupt. It then proceeds to step 3 if not trapped(non-taken) or taken and step 1 finishes without fault.
3. Instruction fetching for the new instruction starts(return CS:EIP for faults is the jumped location). This is doing two things: the BIU prefetches instructions until segment limit is reached(then idles if reached) or TLB mismatch occurs.
The EU on the other hand, fetches instructions from the PIQ. When the paging TLB has a mismatch for the current parameter(1/2/4-byte block) or opcode byte, the pagetable walk is executed(segmentation address limit faults take priority for this). If page faulted, the interrupt handling starts at step 1 again. Otherwise, the TLB is loaded and it waits for the PIQ to fetch enough data to get the next parameter.
Then, once the entire instruction is fetched into the EU, it starts to execute.
Would that be how an actual CPU performs paging on a x86 non-superscalar CPU?
Above is the way the current commit of UniPCemu handles page faults. Older versions do the same, except page faulting and loading the TLB on the interrupt/jump/call instruction itself(what the fault EIP points to).
I've been looking all over the internet, but can't found out ANYTHING about if the page fault for an not-present page happens on the jumped instruction(when fetching it) or on the jumping instruction(the call/jmp/int/iret to it). What does EIP point to for such a faulting instruction?
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io