VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

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

Reply 2 of 3, by superfury

User metadata
Rank l33t++
Rank
l33t++
peterferrie wrote on 2020-12-07, 17:03:

If the access and limit checks pass then registers are committed and the transfer is made. At that point of fetching the new instruction, the page fault is raised.

So it's the execution unit on the destination EIP that's raising the fault, after the EIP of the jump destination is already committed. OK. So the jump itself doesn't raise any page fault(as UniPCemu did previously until now). So the case I presented is actually how the processor actually does it?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io