[SOLVED] QEMU GPF on 64-bit ring0 IRETQ to ring3
Posted: Sat Jan 28, 2023 4:19 pm
tl;dr The AMD System Programming manual (Vol 2) can be misleading. DPL=3 code and stack
descriptors must both have bit 12 set (code or data desciptor) and the stack
descriptor must have the writable bit 9 set.
After setting up the TSS with RSP0 and correctly setting the STAR and LSTAR
MSRs sysret to ring 3 and syscall back to ring 0 was working fine. Until
turning on ring 0 timer interrupts.
On interrupt of the ring3 process the timer handler would GPF on the iretq every time.
And the error code had the ring 3 code selector in it.
Stared at that desciptor so long though marriage might be the answer. But,
thanks to the this forum the veracity of the manuals was not 100%. I noticed
that some of the ignored bits (grey) in Figure 4-20 had a 1 in it instead of a
label.
I remembered reading about the LAR instruction so I put it to work. After OS
init I had it display all the segment and TSS desciptors. It didn't like the
DPL=3 descriptors. I added bit 12 to the DPL=3 descriptors. That got the GPF to
stop complaining about the code descriptor. Instead it complained about stack
desciptor. Eureka! Progress! Added bit 9 (writable) to the stack descriptor and
the GPF from iretq stopped. LAR is my new best friend.
It is interesting that calls in ring3 didn't complain about the stack desciptor. But
there is something about using the TSS stack switching from ring-3 to ring-0
interrupt that causes a problem.
Don't know if it is qemu only. I'm not ready/able to test on real hardware yet.
In the manuals defense it does say:
It just doesn't say what the implications of (not) loading those fields means.
Cheers to all osdevers.
descriptors must both have bit 12 set (code or data desciptor) and the stack
descriptor must have the writable bit 9 set.
After setting up the TSS with RSP0 and correctly setting the STAR and LSTAR
MSRs sysret to ring 3 and syscall back to ring 0 was working fine. Until
turning on ring 0 timer interrupts.
On interrupt of the ring3 process the timer handler would GPF on the iretq every time.
And the error code had the ring 3 code selector in it.
Stared at that desciptor so long though marriage might be the answer. But,
thanks to the this forum the veracity of the manuals was not 100%. I noticed
that some of the ignored bits (grey) in Figure 4-20 had a 1 in it instead of a
label.
I remembered reading about the LAR instruction so I put it to work. After OS
init I had it display all the segment and TSS desciptors. It didn't like the
DPL=3 descriptors. I added bit 12 to the DPL=3 descriptors. That got the GPF to
stop complaining about the code descriptor. Instead it complained about stack
desciptor. Eureka! Progress! Added bit 9 (writable) to the stack descriptor and
the GPF from iretq stopped. LAR is my new best friend.
It is interesting that calls in ring3 didn't complain about the stack desciptor. But
there is something about using the TSS stack switching from ring-3 to ring-0
interrupt that causes a problem.
Don't know if it is qemu only. I'm not ready/able to test on real hardware yet.
In the manuals defense it does say:
[emphasis mine]In Figure 4-20, gray shading indicates the code-segment descriptor fields that are ignored in 64-bit
mode when the descriptor is used during a memory reference. However, the fields are loaded whenever
the segment register is loaded in 64-bit mode.
It just doesn't say what the implications of (not) loading those fields means.
Cheers to all osdevers.