Page 1 of 2
Get vector number in IRQ handler
Posted: Tue Jan 24, 2012 6:24 pm
by Bietje
Hi,
I have a question about IRQ's. I wrote some functions which dynamicly allocate an IRQ and a vector and installs the IRQ with a handler given by (for example) some driver. When the hardware interrupts, the processors calls the handler ofcourse, but I only the only information that handler has are the registers pushed onto the stack.
So, my question is.. how can I get the vector number which was triggered? Is it stored somewhere in the registers? Or.. [fill in].
Thanks in advace,
Bietje
Re: Get vector number in IRQ handler
Posted: Tue Jan 24, 2012 6:42 pm
by Jezze
The easiest thing is for each assembler stub to push the vector number manually.
Re: Get vector number in IRQ handler
Posted: Tue Jan 24, 2012 11:54 pm
by Combuster
Bietje wrote:but I only the only information that handler has are the registers pushed onto the stack.
And it's own name. Pushing the interrupt number in the interrupt code is the typical way if you actually need that number in the handler itself.
The alternative is not implementing handlers and letting external interrupts route through #GP, which does tell you the interrupt number, which also means more overhead for the CPU for trying to dispatch two handlers.
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 12:49 am
by rdos
Usually, with IO-APIC interrupts, what you need is not the vector number (it is allocated because you want to use the interrupt priority feature), but the global interrupt number. So even if the CPU could push the interrupt vector number (which it doesn't unless you use #GPF), it would have limited use anyway since it would not be the global interrupt number.
Currently, I do this by dynamically allocating interrupt handler code segment stubs, and I put the global interrupt number just before the handler, along with information about which handler to call, and what parameters to supply (I use DS as parameter). What the stub does is it saves registers, calls the device-driver supplied entry-point (or the detection entry point), and when this returns, it would send EOI, restore registers and iretd.
Another way to do it with fixed interrupt stubs, is to define the handler stub as a macro, and use the global interrupt number as a parameter. This method was ok for legacy PIC which always has 16 inputs, but I don't find it sufficient for IO-APICs, which could have any number of inputs (one of my machines have one 24 input IO-APIC and one 32 input IO-APIC).
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 3:59 am
by Bietje
Hi,
Thanks for your replies!
rdos wrote:Currently, I do this by dynamically allocating interrupt handler code segment stubs, and I put the global interrupt number just before the handler
That sounds like what I need. I don't understand the dynamically allocate an interrupt handler part. I'm trying to google it, but I'm not getting much results (probably due to wrong keywords). So can you explain it a but further, please?
Thanks in advace,
Bietje
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 4:40 am
by rdos
I gave some examples in this thread:
http://forum.osdev.org/viewtopic.php?f=15&t=24690
What you do is to define a base version of the IRQ-stub, and just before the base you define some dynamic content (like global interrupt number, address of device-driver handler, parameters). When you install a IRQ-stub for an IRQ, you allocate a piece of memory, copy the base IRQ stub code, and setup the dynamic content. Then you link this stub in the IDT to the interrupt vector #.
How the stub looks like depends on the memory model used. For a segmented memory model, it is best to also create a code-selector for the IRQ-stub, so that the dynamic part can be directly accessed within the code selector without needing to know it's exact placement in linear address space. For a flat memory model, you might be able to use the value of EIP to find the dynamic data, or patch the base code in some way. You'll have to figure out the details yourself if you use a flat memory model.
Then you can support sharing interrupts by just adding a share part after the primary IRQ stub code, and just manipulating the dynamic data. Part of the dynamic data could be a link.
I don't think you will find this with Google, as it was something I designed a while ago, and nobody else might use this principle.
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 5:52 am
by Combuster
Bietje wrote:So can you explain it a but further, please?
The
hack technical term is called self-modifying code. Most people simply use macros to generate push index; jump interrupt_stub; pairs for each interrupt number they'll ever need. That should take about 256x10 bytes if you do that for all possible interrupt numbers.
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 6:02 am
by rdos
Combuster wrote:Bietje wrote:So can you explain it a but further, please?
The
hack technical term is called self-modifying code.
You've misunderstood the concept. The code is not modified in any way, only the dynamic content which resides in the dynamic header is modified, and this is not code.
Combuster wrote:Most people simply use macros to generate push index; jump interrupt_stub; pairs for each interrupt number they'll ever need. That should take about 256x10 bytes if you do that for all possible interrupt numbers.
Which wastes a near jmp, and since the vector number means nothing for dynamically allocated ints, you need to go through a table-lookup or something to get useful info.
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 7:05 am
by Solar
rdos wrote:The code is not modified in any way...
The way I understood it, you modify content in the code segment, no?
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 7:48 am
by Bietje
Hi,
Thanks for the example/explanation.
I wrote some simple stubs, not interrupt related to debug and test first. With these functions I get an Invalid Opcode, but I do not understand why, since I do not use any mem-location dependent code..
My code stubs..
assembly part:
Code: Select all
[GLOBAL gen_irq_stub]
gen_irq_stub:
pushad
mov ebp, esp
[EXTERN printNum]
push 0
push 0
push 16
push 0x10
call printNum
add esp, 16
popad
ret
[GLOBAL __end_of_irq_stub]
__end_of_irq_stub:
The C part ('install irq' part, later on):
Code: Select all
void* stub = kalloc(get_general_irqstub_size());
memcpy(stub, gen_irq_stub, get_general_irqstub_size());
exec_addr(stub);
As you can see, I allocate a piece of memory with the calculated size (size calculator is tested and working properly). Then I copy the content of the predefined stub (
gen_irq_stub) into the allocated memory (
stub). When that is done, I start execution at the address. After exec_addr() it panics and gives an invalid opcode..
I don't see why it fails, since my code is not location dependent (as far as I know?).
Thanks in advance,
Bietje
EDIT: The code fails at call printNum. But printNum is a function which is always at the same location in runtime (right?) so.. why does that fail?
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 7:55 am
by AJ
Hi,
This all seems a bit hackish - why not just use a macro to define your interrupt stubs (as suggested above?).
Do I understand that you are trying to test this concept without actually triggering an IRQ? If you are actually in an IRQ handler here, that ret should be an iret.
A couple of questions that need answering:
* Where is EIP when the exception occurs - is it where you would expect?
* What is ESP when the exception occurs - is it where you would expect?
This all seems a lot more complex than it actually needs to be.
Cheers,
Adam
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 7:59 am
by Combuster
Bietje wrote:my code is not location dependent (as far as I know?)
call printNum
Your position-independence just ate you because that term does not mean what you think.
For homework, assemble the following snippet and load it into an hex editor. Then explain why you don't see the same thing repeated (and why copying
parts of position-independent code breaks) - Intel 2A should help you explain why it works like that:
Code: Select all
call label
call label
call label
label:
After that you might understand why I called rdos' method a hack. I didn't even have my crystal ball at hand and I still knew this would happen.
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 9:12 am
by rdos
Solar wrote:rdos wrote:The code is not modified in any way...
The way I understood it, you modify content in the code segment, no?
Content yes, code no. Self-modifying code means you modify the code itself, I modify data that the code uses. I could have put the data in a data segment just as well, but that would require loading a segment register, which is why I use the cs: override to read it via code segment selector instead, which saves a segment register load.
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 9:14 am
by Combuster
Rdos just defined adding or removing code as being no change.
GTFO. identical copy or not, you are just arguing nonsense because you're so murderously afraid of being wrong.
Re: Get vector number in IRQ handler
Posted: Wed Jan 25, 2012 9:17 am
by rdos
Combuster wrote:Bietje wrote:my code is not location dependent (as far as I know?)
call printNum
Your position-independence just ate you because that term does not mean what you think.
I explicitly said the position independence only was valid when using a segmented memory model, and assuming the code selector start at 0. In a flat memory model, there is no position independence, rather this must be built some other way, like addressing through an index register.
Combuster wrote:After that you might understand why I called rdos' method a hack. I didn't even have my crystal ball at hand and I still knew this would happen.
It's not a hack, and it was designed for a segmented memory model only. If you violate these assumptions, the code cannot be used as is.