Enabling interrupts causes int 8 and then int 13 repeatedly?

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.
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

Enabling interrupts causes int 8 and then int 13 repeatedly?

Post 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?
Practice makes perfect.
Octocontrabass
Member
Member
Posts: 5590
Joined: Mon Mar 25, 2013 7:01 pm

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

Post by Octocontrabass »

Are you expecting interrupt 8? If not, you should read the FAQ.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

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

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

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

Post 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...
Practice makes perfect.
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

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

Post 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..
Practice makes perfect.
Octocontrabass
Member
Member
Posts: 5590
Joined: Mon Mar 25, 2013 7:01 pm

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

Post 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.)
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

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

Post 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...
Practice makes perfect.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

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

Post 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.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Octocontrabass
Member
Member
Posts: 5590
Joined: Mon Mar 25, 2013 7:01 pm

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

Post 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.
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

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

Post 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?
Practice makes perfect.
Octocontrabass
Member
Member
Posts: 5590
Joined: Mon Mar 25, 2013 7:01 pm

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

Post 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.
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

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

Post 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?
Practice makes perfect.
User avatar
Kazinsal
Member
Member
Posts: 559
Joined: Wed Jul 13, 2011 7:38 pm
Libera.chat IRC: Kazinsal
Location: Vancouver
Contact:

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

Post 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.
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

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

Post 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)?
Practice makes perfect.
Icee
Member
Member
Posts: 100
Joined: Wed Jan 08, 2014 8:41 am
Location: Moscow, Russia

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

Post by Icee »

@jrhetf4xb
Not without a full-featured instruction decoder.
Post Reply