Page 1 of 1

IRET Not returning

Posted: Tue Oct 14, 2008 7:03 am
by System123
I recently figured out that if a non initialized interrupt is called for any reason then the kernel crashes. This makes perfect sense, so what I did was created a ignore_int procedure which fills my IDT before any IRQs and ISRs are added. This way it handles any strange interrupts. The problem is that the iretd at the end does not seem to return to the original code where the interrupt occurred. It has worked though because the screen is printed too and the keyboard is allowed to type. Thus interrupts have returned. However the normal pascal code under the int is never executed.

I was wondering is it possible for iret to return to the wrong code, or to return to a random section of memory, and what would cause this.

Code: Select all

[Global ignore_int]

ignore_int:
pushad
mov [ds:0xb8000 + 160], 'A'
mov [ds:0xb8000 + 161], 0x2
popad
iretd

Re: IRET Not returning

Posted: Tue Oct 14, 2008 7:37 am
by AJ
Hi,

Some exceptions will also push an error code on to the stack. This means that for interrupt numbers 0x08, 0x0A, 0x0B, 0x0C, 0x0D and 0x0E you will need to add 4 bytes to ESP before returning to avoid your stack becoming misaligned.

My suggestion would be to create a macro to create a handler with and without an error code. You can then quite simly create a separate ISR for each of the 32 exceptions and will be able to tell which exception just happened too.

Cheers,
Adam

Re: IRET Not returning

Posted: Tue Oct 14, 2008 10:42 am
by System123
My ISR and IRQs are perfectly fine. They work. this is for all other interrupts ie: int 55

Re: IRET Not returning

Posted: Tue Oct 14, 2008 12:31 pm
by AJ
Apologies - I still think stack corruption somewhere is the most likely explanation, though.

Cheers,
Adam

Re: IRET Not returning

Posted: Wed Oct 15, 2008 2:18 am
by mystran
Some exceptions push an error code, some don't. So if you are ignoring any exceptions, then you need a minimum of two versions, one that can remove the error code, and one that doesn't. What's worse, you also pretty much have to remap the PIC (assuming that's what you're using) because otherwise hardware IRQs can land on exceptions that would push error codes if they were exceptions, but now lack the code.

On the other hand, with exceptions you should probably panic with a helpful message if you are not handling it, because some exceptions can't even be resumed, and even when they can, it varies whether they resume at or after the instruction that caused the exceptions (faults resume at, traps after, and aborts can't be resumed reliably).

edit: was gonna say but forgot, that if you resume a fault without doing anything about the fault condition, you've essentially created a sophisticated version of an infinite loop, but I guess the CPU might handle hardware interrupts just before it faults again, so you might still see your keyboard working normal, even if the program doesn't seem to proceed anywhere

Anyway, if that is not the problem, then you have to clarify your original post. What exactly is it that happens, and what should happen? :)

Re: IRET Not returning

Posted: Wed Oct 15, 2008 3:07 am
by AJ
mystran wrote:Anyway, if that is not the problem, then you have to clarify your original post. What exactly is it that happens, and what should happen? :)
Agreed - I should have said in my last post, but is it possible to see a Bochs register dump of the system state when the system does not resume? I also wonder if it's possible that you don't have the correct PL for calling the int (can this happen? just brainstorming :? ). In that case, you would get a GPF immediately after the int and it would be the GPF that actually isn't returning correctly. I can see several ways this could happen with a PFE too...

The fact is that with a correct IDT and stack, the code you posted above should work - the problem therefore lies somewhere else.

Cheers,
Adam

Re: IRET Not returning

Posted: Wed Oct 15, 2008 4:51 am
by egos
Maybe so better:

Code: Select all

ignore_int:
pushad ;
push ds
push KERNEL_DATA_SELECTOR
pop ds
mov byte [ds:0xb8000 + 160], 'A'
mov byte [ds:0xb8000 + 161], 0x2
pop ds
popad ;
iretd

Re: IRET Not returning

Posted: Wed Oct 15, 2008 3:43 pm
by pcmattman
I can see the problem instantly ;)

Code: Select all

ignore_int:
pushad ;
push ds
push KERNEL_DATA_SELECTOR
pop ds
mov byte [ds:0xb8000 + 160], 'A'
mov byte [ds:0xb8000 + 161], 0x2
pop ds <------ Right HERE!
popad ;
iretd
The second pop ds means you're taking too much off the stack and jumping to the wrong address (most likely your code segment).

Re: IRET Not returning

Posted: Wed Oct 15, 2008 3:58 pm
by Combuster
The second pop ds means you're taking too much off the stack and jumping to the wrong address (most likely your code segment).
Euhm... everything matches up here :?

Code: Select all

ignore_int:
pushad ;
 | push ds <-- came from here!
 |  | push KERNEL_DATA_SELECTOR
 |  |  |
 |  | pop ds
 |  | mov byte [ds:0xb8000 + 160], 'A'
 |  | mov byte [ds:0xb8000 + 161], 0x2
 | pop ds 
popad ;
iretd

Re: IRET Not returning

Posted: Thu Oct 16, 2008 12:24 am
by pcmattman
Oops! Didn't see this:

Code: Select all

push KERNEL_DATA_SELECTOR
My mistake :(.

Re: IRET Not returning

Posted: Thu Oct 16, 2008 6:37 am
by System123
I can't supply a bochs reg dump as this problem only occurs when running on a real pc :? The problem has nothing to do with IRQs or exceptions I have checked and the idt works fine because without this code everything works.