Hi,
teodori wrote:My question: Is it possible to retrieve IRQ number in "DmyIsr" and to push it to the stack, so I can use a C function like this:
If you need each interrupt handler to be different, even if the only difference is pushing a different number on the stack, then you have to have different interrupt handlers.
To do this, one way is to use the assembler's preprocessor . For an example (NASM):
Code: Select all
%assign i 0
%rep 256
align 4,nop
IRQstub%[i]:
pusha
push dword %1
call dmy_isr
add esp,4
popa
iret
%assign i i+1
%endrep
This should generate 256 IRQ handlers with labels named "IRQstub0", "IRQstub1", "IRQstub2", ... "IRQstub255". You could generate the IDT in a similar way, so that the first IDT entry points to "IRQstub0", the second points to "IRQstub1", etc.
Unfortunately some assemblers don't have good preprocessors. In this case you can write code to generate code. For example, you could write a little C utility or a Python script or something that generates the assembly for the IRQ stubs and IDT.
However, the idea of having one common interrupt handler for all the extremely different types of interrupts is "less than intelligent".
For exceptions, software interrupts, IPIs and spurious IRQs the only thing a common interrupt handler is going to do is call the interrupt handler that's designed for that interrupt, and it makes more sense to setup the IDT so that the correct interrupt handler is called directly without wasting time getting an "interrupt number" and doing something like "if(number == 0x0E) { handler_that_should_have_been_called_to_begin_with(); return; }".
For IRQs you'd want to use trap gates, for some exceptions you'd want to use interrupt gates, and for some exceptions (NMI, machine check and double fault) you'd want to use task gates. For some of the exceptions the CPU pushes an extra error code and for some exceptions it doesn't. For the page fault handler the first thing you should do is save CR2 (so that it doesn't matter if CR2 gets trashed if a second page fault occurs). For things like spurious IRQ handlers you could just do "IRET" and nothing else.
Basically the idea only makes sense for normal IRQs; possibly excluding the IRQ the scheduler uses for figuring out when a task should be preempted, the IRQ the scheduler uses for figuring out when a sleeping task should wake up, any IRQ used for a watchdog, and any spurious IRQ.
What this means is that idea of generating the IDT and all the interrupt handling stubs using a simple loop is broken - it needs to be much more flexible. Instead, you might have different macros that generate different types of IDT entries and use them manually; and different pieces of code (some generated by macros) for different interrupt stubs.
Cheers,
Brendan