iret: Return CS Selector NULL

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.
Post Reply
NOTNULL

iret: Return CS Selector NULL

Post by NOTNULL »

Hi all,
I completed installing IDT for my OS by declaring all the exception function pointers in an array (in C file, since all the exception handlers are C routines) and assigning it to all the interrupt descriptors (in assembly file). The "iret" is given as inline assembly instruction in the exception handler. While debugging the code, I found that when the processor excecutes the "iret" instruction, bochs panics with the message iret: return CS selector null. But, all the interrupt descriptors point to the correct CS descriptor.

Here's my C exception handler,

Code: Select all

void do_irq00(void)
{
    PUSH_REGISTERS
    print("Exception 0");
    POP_REGISTERS
    __asm__("iret");
}
The PUSH_REGISTERS and POP_REGISTERS are macros defined as below:

Code: Select all

#define PUSH_REGISTERS   {                      \
                            __asm__ ("pusha");       \
                            __asm__ ("push %ds");  \
                            __asm__ ("push %es");  \
                            __asm__ ("push %fs");   \
                            __asm__ ("push %gs");  \
                         }

#define POP_REGISTERS    {                        \
                            __asm__ ("pop %gs");    \
                            __asm__ ("pop %fs");     \
                            __asm__ ("pop %es");    \
                            __asm__ ("pop %ds");    \
                            __asm__ ("popa");         \
                         }
What could be problem?
Any help greatly appreciated.
Kim

Re:iret: Return CS Selector NULL

Post by Kim »

Well your compiler add's a stack frame I think...
You should use:

Code: Select all

__declspec(naked) void do_irq00(void)
{
    PUSH_REGISTERS
    print("Exception 0");
    POP_REGISTERS
    __asm__("iret");
}
NOTNULL

Re:iret: Return CS Selector NULL

Post by NOTNULL »

Does gcc v4.0.0 support "__declspec(naked)". I am afraid that my compiler doesn't support it? It gives parse error.
Kim

Re:iret: Return CS Selector NULL

Post by Kim »

Oh sorry thats for Visual C++...

void do_irq00(void) __attribute__((naked))

I hope this is correct (almost never use c/c++)...

Edit: I found this on google
http://www.ohse.de/uwe/articles/gcc-attributes.html#func-naked.
AR

Re:iret: Return CS Selector NULL

Post by AR »

__declspec is a Microsoft C++ Compiler extension, similar to GCC's __attribute__, as far as I am aware you cannot remove the stackframe in GCC that is why ISRs are always in Assembly language.

The reason for the crash is probably stuffing up the stack, by calling print the parameter and return address are pushed and ESP is modified but your "artificial" push/pops are pulling modified data from the stack. Example:

Code: Select all

/* Your function in Assembly */
.global do_irq00
do_irq00:
push %ebp
mov %esp, %ebp
sub $4, %esp
pusha
/* Pushes */
mov $PointerToString, %ss:(%esp)
call print
/* Pops */
popa
iret
add $4, %esp
pop %ebp
ret
This is a theory of how the code looks, use objdump/NASM disassembler to see what exactly it's done. The solution is to do it in assembly though so that you control exactly what it does.

@Kim: I tested __attribute__((naked)) and it doesn't work [GCC 4.0.0] ("directive ignored"), the reference you provided also states specific architectures, x86 isn't listed.
NOTNULL

Re:iret: Return CS Selector NULL

Post by NOTNULL »

I managed to fix this problem by adding 0x0C to the esp register. Because, the disassembled code shows that ebp (4 bytes) is pushed in the stack and 8 bytes is subtracted from the esp register, which is the normal code when a C function is assembled. Now, my exception handler looks like this,

Code: Select all

void do_irq00(void)
{
    PUSH_REGISTERS
    print("Exception 0");
    POP_REGISTERS
    __asm__("add $0x0c, %esp");
    __asm__("iret");
}
Thanks for the help AR.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:iret: Return CS Selector NULL

Post by Pype.Clicker »

You may want to check the FAQ for it:
http://www.osdev.org/osfaq2/index.php/I ... ceRoutines

Honnestly, i think that approach of tweaking stack within a C procedure should be avoided. You'll have debug-sessions-darker-than-the-night if someone someday (e.g. the optimizer ?) decide that the stack frame shouldn't look the same ...

at least try to do it clean with "mov esp,ebp"-based thing (otherwise, adding e.g. local variables could trash the whole thing ...)
NOTNULL

Re:iret: Return CS Selector NULL

Post by NOTNULL »

Thank you pype. I can now figure out how worse the problem may occur using this fix. I believe writing an ASM wrapper for interrupt handlers would be the best option.
Post Reply