Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
I've been attempting to reload the GDT while already in 64 bit mode and for some reason it works fine but completely smashes my stack.
I've confirmed that before entering this function and exiting that the stack pointer is in fact at the same position but again for some reason my kernel crashes very shortly after for what appears to be a poisoned stack.
Code below simply pushes SS:RSP flags CS and RIP and then iretq to force a reload of CS is my understanding of the only correct way of doing this in 64 bit mode since far jmps aren't allowed.
Ok I experimented with setting SS=0 during IRETQ from 64-bit ring0 to 64-bit ring0 and it work, so it might actually legal to do so (I'm not sure if that's just luck).
So, the inline block seems correctly to me, although it is ugly to reuses the same stack but I'm also doing that.
perhaps we can look into the whole C function to see if there is anything wrong.
By the way, this is my code for your reference (however, in plain assembly)
Ok I experimented with setting SS=0 during IRETQ from 64-bit ring0 to 64-bit ring0 and it work, so it might actually legal to do so (I'm not sure if that's just luck).
Oh, I thought we were trying to get to ring 3. To iret to ring 3 you need a valid SS.
If a trainstation is where trains stop, what is a workstation ?
gerryg400 wrote:Oh, I thought we were trying to get to ring 3. To iret to ring 3 you need a valid SS.
Not necessairly. In long mode it's allowed to use SS=0 on iretq, for nested ISRs. But we agreed that you should not rely on that because when the first time you switch to userspace from kernel (in other words, when you set up segment registers for the first and only time), there's no nesting, therefore SS should contain a valid selector. Normally only the cpu will push ss=0 on stack, and pop it back, and software has nothing to do with it (unless you want to count reentrant calls and your kernel checks the stack for ss=0 to accomplish that task).
If SS=0 when going to user mode, #GP as according to the manual for IRETQ:
64-Bit Mode Exceptions
#GP(0) If EFLAGS.NT[bit 14] = 1.
If the return code segment selector is NULL.
If the stack segment selector is NULL going back to compatibility mode. If the stack segment selector is NULL going back to CPL3 64-bit mode.
If a NULL stack segment selector RPL is not equal to CPL going back to non-CPL3 64-bit mode.
If the return instruction pointer is not within the return code segment limit.
If the return instruction pointer is non-canonical.
SS=0 only possible in ring0, and as mentioned above, is usually set by CPU in some circumstances.