Getting interrupt's number within it's handler

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.
Tyler Durden

Getting interrupt's number within it's handler

Post by Tyler Durden »

Hi all ! Can I get a current interrupt's number within it's handler ? E.g. I've got the same handler for exceptions (this is just a test version but...) the only difference are the exceptions's numbers printed with this handler. So I wrote about 20 pretty the same handlers for this :( Is it possible to get this number somehow (e.g. from APIC or what else ?) and write the universal handler for all ints ? Thanks
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:Getting interrupt's number within it's handler

Post by Pype.Clicker »

no. We've been looking for something alike, but apparently there isn't such solution. What most of us do is to push the INT number on stack and then branch to a generic handler

(did i already mentionned your avatar is kewl ?)
Curufir

Re:Getting interrupt's number within it's handler

Post by Curufir »

The last time this came up I suggest that it was possible to read the return value from the stack and interpret the interrupt value from the calling instruction. I still think that's a perfectly valid way of doing it.
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:Getting interrupt's number within it's handler

Post by Pype.Clicker »

Curufir wrote: The last time this came up I suggest that it was possible to read the return value from the stack and interpret the interrupt value from the calling instruction. I still think that's a perfectly valid way of doing it.
Well, it will certainly be valid for guessing whether the user used "INT 0x30" or "INT 0x31", though i doubt it will actually be efficient. But it certainly won't work for hardware interrupts (which can occur with any instruction) nor for exceptions (the same mov eax,[eax] could raise a page fault or a segmentation fault)
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Getting interrupt's number within it's handler

Post by Brendan »

Hi,

It'd make much more sense to do something like:

Code: Select all

int0x00:
    push dword 0      ;Fake error code
    push eax
    mov eax,0x00
    jmp default_exception_handler

int0x01:
    push dword 0      ;Fake error code
    push eax
    mov eax,0x01
    jmp default_exception_handler

<-Ints 0x02 to 0x0C skipped->

int0x0D:
    <-handle_the_GPF->
    iretd

int0x0E:
    <-handle_the_PGF->
    iretd

<-Ints 0x0F to 0x1F skipped->

int0x20:
    <-handle_IRQ0->
    iretd

int0x21:
    push eax
    mov eax,0x01
    jmp IRQ_handler

int0x22:
    push eax
    mov eax,0x02
    jmp IRQ_handler

<-Ints 0x23 to 0x27 skipped->

int0x28:
    <-handle_IRQ8->
    iretd

int0x29:
    push eax
    mov eax,0x09
    jmp IRQ_handler

<-Ints 0x2A to 0x2F skipped->

default_exception_handler:
    call critical_error_handler
    pop eax
    add esp,4
    iretd

IRQ_handler:
    <-handle the IRQ in EAX->
    <-send EOI to master PIC->
    cmp eax,0x07
    jb .l1
    <-send EOI to slave PIC->
.l1:
    pop eax
    iretd
This lets you specify which interrupts get controlled by which default handlers, and they can be handled by special code instead if necessary. The EOI stuff for IRQs is only an example (it'd choke on PCI level triggered interrupts), and the whole idea of using 16 pre-defined IRQs only works with the PIC chips (IO APICs can be used for up to 224 IRQs where the interrupt number determines it's priority - they should be spread throughout the whole IDT).


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.
mystran

Re:Getting interrupt's number within it's handler

Post by mystran »

Urgh.. I'd still go with the:

Code: Select all

irq<n>_handler:
     pushl $<n>
     jmp generic_irq_handler
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:Getting interrupt's number within it's handler

Post by Pype.Clicker »

Code: Select all

%macro exc_noerrcode 1
handler_exc_%1:
     push 0  ;; fake errcode
     push %1
     jmp generic_exc_handler
%endmacro

%macro exc_errcode 1
handler_exc_%1:
     push %1
     jmp generic_exc_handler
%endmacro

%macro irq 1
handler_irq_%1
     push %1
     jmp generic_irq_handler
%endmacro
[quote][/quote]

for me ... 
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Getting interrupt's number within it's handler

Post by Candy »

You CAN do so for software interrupts.

Code: Select all

interrupt_asm:
    ; push the registers that will be used as arguments for this call
    push eax
    push ebx
    push ecx
    push edx
    mov eax, [esp+4]
    xor ebx, ebx
    mov bl, byte [eax-1]
    push ebx
call interrupt_c
    pop eax
    pop edx
    pop ecx
    pop ebx
    pop eax
    iret
And then make a C function:

Code: Select all

void interrupt_c(int called_interrupt_num, int edx, int ecx, int ebx, int eax) {

}
that pretty much does whatever you like it to do.

Note, all untested as usual. If it makes your computer dance around the room, don't blame me.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Getting interrupt's number within it's handler

Post by Brendan »

Hi,
Candy wrote:You CAN do so for software interrupts.
Looks good. The next logical step would be:

Code: Select all

void interrupt_c(int called_interrupt_num, int edx, int ecx, int ebx, int eax) {
    switch(called_interrupt_num) {
        case 0x80:
             call interrupt_0x80(edx, ecx, ebx, eax);
             break;
        case 0x81:
             call interrupt_0x81(edx, ecx, ebx, eax);
             break;
    }
}
That's be great for performance ;D.


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
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Getting interrupt's number within it's handler

Post by Candy »

Brendan wrote: Hi,
Looks good. The next logical step would be:

Code: Select all

void interrupt_c(int called_interrupt_num, int edx, int ecx, int ebx, int eax) {
    switch(called_interrupt_num) {
        case 0x80:
             call interrupt_0x80(edx, ecx, ebx, eax);
             break;
        case 0x81:
             call interrupt_0x81(edx, ecx, ebx, eax);
             break;
    }
}
That's be great for performance ;D.
Well... that idea has been abandoned by most years ago already. Try this one:

Code: Select all

typedef void (*syscall_function)(int, int, int, int);
syscall_function[256] = { NULL, NULL, NULL ... NULL, func_30, func_31, func_32...func_fe, func_ff };

void interrupt(int syscall_id, int eax, int ebx, int ecx, int edx) {
    call syscall_function[syscall_id](eax, ebx, ecx, edx);
}
Or do the same in ASM. My interrupt handler does that for all of them, whereas I only use hardware ones and exceptions so this technique has no use for me.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Getting interrupt's number within it's handler

Post by Brendan »

Hi,
Candy wrote:Well... that idea has been abandoned by most years ago already. Try this one:
The point I was trying to make (albeit far too subtly) is that software interrupts end up being used for one or more specific functions, and that it would be silly to use any form of generic software interrupt handler.

The code you posted is a good example - it ends up calling func_30, func_31, etc depending on the software interrupt used, so for performance reasons why not call them directly without the extra overhead?

The only reason I can think of is C's inability to generate interrupt handlers combined with lazy programming (not feeling like writing multiple assembly stubs).


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.
Curufir

Re:Getting interrupt's number within it's handler

Post by Curufir »

I agree. I've never really understood why most OS try to multiplex a single interrupt for all the system calls (Eg Linux int 80h).

On x86 you have over 150 interrupts at your disposal. Since the number of system calls is usually pretty limited why not use the encoding of the interrupt instruction to contain useful data. In other words use a different software interrupt for each system call.

The other methods seem pretty wasteful, and inefficient (Losing a register, looking up address in memory, storing function table in memory etc) compared to using the system call directly.

I guess at some point it made total sense to someone, but I can't see a good reason for it.
AR

Re:Getting interrupt's number within it's handler

Post by AR »

I would imagine the best explanation as being longevity, sure you have 150 spare interrupts, but what happens if a new PC model comes out that requires additional IRQ interrupts or if you reach 151 system calls? "Professional" OS' (term used loosely) tend to leave wide spaces open for extending in future. On Windows for example, quite a few structs start with a size field which assumeably allows version control based on the amount of data in the struct.

You could also say it's simple and allows easy behind the scenes replacement with SYSENTER/SYSCALL.
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Getting interrupt's number within it's handler

Post by Colonel Kernel »

I think it may have something to do with porting to other architectures, where there may only be one "syscall" instruction. In such a case you have to dispatch through a table lookup anyway...
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
B.E

Re:Getting interrupt's number within it's handler

Post by B.E »

I'm guessing the you would be able to get the interrupt's number from the PIC or the APIC.
Post Reply