Hello everyone!
I'm having some trouble with ISRs in my OS written in Rust. The problem is that IRET instrction is restoring a wrong CS.
Let me show step by step what it happens.
First I generate a division error exception by dividing by zero. This is the situation before the exception:
https://i.ibb.co/k5L9qt3/Schermata-del- ... -37-36.png
Then I step to generate the exception:
https://i.ibb.co/W547mSV/Schermata-del- ... -38-10.png
CPU jumps to 0x1004d0, which is what I'm expecting since that is the address of my division error handler, which is made by the only IRET instruction.
Stack also seems fine, EIP, CS, and EFLAGS got pushed and they are correct (0x8 is my code segment).
So far, so good.
However see what happens when I step again to execute the IRET instruction:
https://i.ibb.co/b1d35sx/Schermata-del- ... -38-53.png
Instead of returning, a general protection fault exception is generated, and if I'm right the extra data pushed to stack is the error code.
In the case of a general protection fault the error code is the segment related to the excpetion, in my case is 0x10. WHY?
And indeed, Bochs is complaining check_cs(0x0010): not a valid code segment !, and Bochs is right since my code segment is 0x8 and not 0x10
My understanding of the problem is that IRET is popping wrong values from the stack, but how I can solve this?
Complete source code here: https://github.com/mrgian/felix
IRET instruction setting wrong code segment
Re: IRET instruction setting wrong code segment
You have a 16-bit IRET in 32-bit mode. And you need 32-bit one, AKA IRETD.
IOW, in 32-bit mode the instruction needs to be encoded as 0xCF and not as 0x66, 0xCF (your disassembly gives this away as the first digit 6 and length of 2 bytes).
Also, doing IRETD will go back to (I)DIV. If you intend to skip the offending instruction, the ISR needs to adjust the return address on the stack.
IOW, in 32-bit mode the instruction needs to be encoded as 0xCF and not as 0x66, 0xCF (your disassembly gives this away as the first digit 6 and length of 2 bytes).
Also, doing IRETD will go back to (I)DIV. If you intend to skip the offending instruction, the ISR needs to adjust the return address on the stack.
-
- Member
- Posts: 5562
- Joined: Mon Mar 25, 2013 7:01 pm
Re: IRET instruction setting wrong code segment
Looks like you already fixed the problem. I'm curious why your assembler decided you wanted IRETW instead of IRETD in 32-bit mode, that's a pretty unusual problem to have.
-
- Member
- Posts: 797
- Joined: Fri Aug 26, 2016 1:41 pm
- Libera.chat IRC: mpetch
Re: IRET instruction setting wrong code segment
Almost like the code had a `.code16gcc` directive or equivalent in it.
Re: IRET instruction setting wrong code segment
Yep. That was the problem. I still don't know why Rust inline asm assembler translated IRET to IRETW instead of IRETD, even if I'm in 32 bit mode.Octocontrabass wrote:Looks like you already fixed the problem. I'm curious why your assembler decided you wanted IRETW instead of IRETD in 32-bit mode, that's a pretty unusual problem to have.