OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 1:02 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: IRET instruction setting wrong code segment
PostPosted: Wed Mar 29, 2023 4:09 am 
Offline

Joined: Wed Mar 29, 2023 2:41 am
Posts: 2
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-2023-03-29-11-37-36.png

Then I step to generate the exception:
https://i.ibb.co/W547mSV/Schermata-del-2023-03-29-11-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-2023-03-29-11-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


Top
 Profile  
 
 Post subject: Re: IRET instruction setting wrong code segment
PostPosted: Mon Apr 03, 2023 6:37 pm 
Offline
Member
Member

Joined: Tue Mar 04, 2014 5:27 am
Posts: 1108
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.


Top
 Profile  
 
 Post subject: Re: IRET instruction setting wrong code segment
PostPosted: Mon Apr 03, 2023 7:17 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
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.


Top
 Profile  
 
 Post subject: Re: IRET instruction setting wrong code segment
PostPosted: Mon Apr 03, 2023 9:33 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
Almost like the code had a `.code16gcc` directive or equivalent in it.


Top
 Profile  
 
 Post subject: Re: IRET instruction setting wrong code segment
PostPosted: Sat Apr 08, 2023 1:57 am 
Offline

Joined: Wed Mar 29, 2023 2:41 am
Posts: 2
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.


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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 62 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group