Page 1 of 2

Enabling interrupts causes int 8 and then int 13 repeatedly?

Posted: Wed Nov 12, 2014 4:10 pm
by jrhetf4xb
I've just set up my interrupt/exception handling and as soon as I call sti my interrupt handler gets called by catching int no.8 at first and then int no.13 gets caught repeatedly. Bochs is displaying this in the log, which leaves me wondering if the GDT or the IDT is the problem:

Code: Select all

check_cs(0x0246): conforming code seg descriptor dpl > cpl, dpl=3, cpl=2
Any ideas what is going on?

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Wed Nov 12, 2014 5:28 pm
by Octocontrabass
Are you expecting interrupt 8? If not, you should read the FAQ.

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Wed Nov 12, 2014 10:04 pm
by Brendan
Hi,
jrhetf4xb wrote:I've just set up my interrupt/exception handling and as soon as I call sti my interrupt handler gets called by catching int no.8 at first and then int no.13 gets caught repeatedly. Bochs is displaying this in the log, which leaves me wondering if the GDT or the IDT is the problem:

Code: Select all

check_cs(0x0246): conforming code seg descriptor dpl > cpl, dpl=3, cpl=2
Any ideas what is going on?
First, I'd assume your GDT limit is wrong (allowing uninitialised GDT entries to be used).

Second, 0x0246 is a likely value for EFLAGS; so the problem may be that your interrupt handler has messed up the stack causing the interrupted code's EFLAGS to get loaded into CS when the interrupt handler does IRET.


Cheers,

Brendan

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Thu Nov 13, 2014 8:14 am
by jrhetf4xb
Are you expecting interrupt 8? If not, you should read the FAQ.
You're right, I forgot about the remapping. I did it now by following Bran's kernel dev tutorial.

However, I noticed my handler's parameter was wrong as it did not take a pointer, so I fixed it to this:

Code: Select all

void isr_handler(struct regs32 *regs)
But now I get this odd interrupt no.778855790, which makes no sense to me...
so the problem may be that your interrupt handler has messed up the stack
But my handler just calls my kprintf function to display what interrupt was handled, literally a one-liner.
The handler is as follows:

Code: Select all

/* asm part: */
isr_common_stub:
    pushal
    call isr_handler
    popal
    addl $8, %esp
    sti
    iret  

/* C part: */
void
isr_handler(struct regs32 *regs)
{
	kprintf("Received interrupt: %d\n", regs->intn);
}
With my two types of ISRs:

Code: Select all

/* with 2 pushes: */
isr0:
    cli
    pushl $0
    pushl $0
    jmp isr_common_stub

/* ... */
/*with 1 push */
isr8: 
    cli
    pushl $8
    jmp isr_common_stub
/* ... etc */
And my regs32 structure:

Code: Select all

struct regs32
{
    uint32_t edi, esi, ebp, esp, 
                ebx, edx, ecx, eax; 
    uint32_t intn, errc;
    uint32_t eip, cs, eflags, usresp, ss; 
};
As for my GDT, I've included 3 entries only, so I've set the limit to 23. I get no problems with my code prior to enabling interrupts...


EDIT:
My bad, I see what you meant... I forgot this bit:

Code: Select all

pushl %esp 
    call irq_handler 
    popl %eax
    movl %eax, %esp
Now that I fixed that, I get the same sequence of int 8 and int 13

EDIT2: I actually get int 6 (Invalid Opcode)... What did I do...

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Tue Nov 18, 2014 6:02 am
by jrhetf4xb
Alright, it seems it has been working all along, my sti instruction was misplaced #-o
However, when I force an interrupt, say divide by 0, I get repeatedly interrupt no.778855790, which I assume means my handler is broken... Judging by my previous post do you see any obvious errors in my handler asm and C parts? I really can't see why it's operating so weirdly..

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Tue Nov 18, 2014 6:52 am
by Octocontrabass
jrhetf4xb wrote:778855790
It looks like you're interpreting text as an integer. Here's what it says:

Code: Select all

nel.
Perhaps you're clobbering the stack somehow.

Code: Select all

    pushl %esp
    call irq_handler
    popl %eax
    movl %eax, %esp
What is this supposed to do? (For bonus points, also explain why it's wrong.)

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Tue Nov 18, 2014 8:50 am
by jrhetf4xb
Sorry, I shouldn't have left that edit as I'm using the code above it (with just push, call, pop). I get the error with that code.
But to answer your question it pushes the current stack pointer onto the stack, so my struct in the end would read garbage...
As for "nel." I checked my code and this it the part of code that supposedly contains it:

Code: Select all

if (bootinfo->flags & MBTINFO_CMDLINE) {
    kprintf("Command line: %s\n", (char *) bootinfo->cmdline);
}
This is my multiboot.c file that deals with the boot info from GRUB.
So in my kernel the output appears as:

Code: Select all

Command line: /boot/kernel.bin cmdline=any kernel parameters
So it's reading over this string...

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Tue Nov 18, 2014 8:52 am
by SpyderTL
A lot of exception interrupts will immediately be re-thrown after you iret from the interrupt handler. This is because the "return" address on the stack is the address of the instruction that failed. So unless you either change the return address, or find some other way to leave your interrupt handler, you will get the same interrupt over and over again.

Not sure if this is your problem, but I thought that I'd mention it.

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Tue Nov 18, 2014 9:48 am
by Octocontrabass
jrhetf4xb wrote:Sorry, I shouldn't have left that edit as I'm using the code above it (with just push, call, pop).
Your isr_handler function takes whatever was pushed on to the stack immediately before it was called as a pointer to a regs32 struct. The last thing pushed to the stack is EDI. What do you think will happen if EDI is a pointer to (a copy of) the kernel command line?
jrhetf4xb wrote:But to answer your question it pushes the current stack pointer onto the stack, so my struct in the end would read garbage...
Zero points. Pushing esp is correct. The problem there is the fourth line: taking that value off the stack (which is not guaranteed to be the same value you pushed!) and then putting it back into the stack pointer. Either it's the same value as before and nothing at all happens, or the value is different and your stack is now corrupt.

By the way, if you're not going to use a value popped from the stack, you shouldn't pop it at all. Instead, add 4 to esp.

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Wed Nov 19, 2014 5:17 am
by jrhetf4xb
What do you think will happen if EDI is a pointer to (a copy of) the kernel command line?
Since it's a pointer, it's going to point to the address of the start of the string, which I assume shouldn't interfere with anything... My regs32.edi would contain this address. But it seems to me that the whole string is pushed onto the stack and not the address itself so when I read regs32.intn I'm just getting a portion of the string?

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Wed Nov 19, 2014 6:30 am
by Octocontrabass
Here are two function prototypes.

Code: Select all

void example_a(struct regs32 regs)
void example_b(struct regs32 *regs)
What's the difference between these two function prototypes?

What does each function expect to find on the stack when it is called?

Once you can correctly answer both of these questions, you should understand why your code doesn't work.

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Wed Nov 19, 2014 10:58 am
by jrhetf4xb
What's the difference between these two function prototypes?
However, I noticed my handler's parameter was wrong as it did not take a pointer, so I fixed it to this:
Lol I can't believe what I did :D I followed Bran's Kernel Development tutorial and this bit was totally misleading as his regs structure is a pointer in the handler.

In the pointer prototype the structure of regs32 begins with the address of edi as this is the first address on the stack, thus accesses further down (or up... dat stack structure) regs32 point after edi's value, so that's why I'm reading string data.
As for the normal declaration of regs32 prototype, I think regs32 is created and populated with data from the stack.

In any case I managed to get interrupts working and I'm successfully forcing a divide by 0.
A lot of exception interrupts will immediately be re-thrown after you iret from the interrupt handler.
Thanks for the tip, for now I do a simple regs.eip += 4; and I get away with repetitive interrupt calling.
But are all instructions 4 bytes long? :?:

Thanks for keeping up with my lame mistakes. Last question, how can I force any of the other interrupts except divide by 0? Or should I assume everything is fine for now?

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Wed Nov 19, 2014 11:18 am
by Kazinsal
jrhetf4xb wrote:Thanks for the tip, for now I do a simple egs.eip += 4; and I get away with repetitive interrupt calling.
But are all instructions 4 bytes long? :?:
This is bad. Instructions on x86 are variable length, and are between 1 and 15 bytes (except for very strange and odd circumstances). Chances are you're now getting a totally different exception because you've iret-ed into the middle of an instruction!
jrhetf4xb wrote:Thanks for keeping up with my lame mistakes. Last question, how can I force any of the other interrupts except divide by 0? Or should I assume everything is fine for now?
You can force a general protection fault by a myriad of different ways (such as triggering an interrupt outside the IDT limit or referencing a null descriptor). You can trigger a segment not present fault by loading a selector with its present bit set to 0 into a segment (or a stack segment fault if you load it into SS). There's an instruction called UD2 that is reserved by Intel to be an invalid opcode.

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Wed Nov 19, 2014 11:34 am
by jrhetf4xb
Kazinsal wrote:This is bad. Instructions on x86 are variable length, and are between 1 and 15 bytes (except for very strange and odd circumstances).
I'm pushing this too much but is there a straightforward way to know how to jump to the next instruction then (if they are all of variable length)?

Re: Enabling interrupts causes int 8 and then int 13 repeate

Posted: Wed Nov 19, 2014 11:56 am
by Icee
@jrhetf4xb
Not without a full-featured instruction decoder.