I've been thinking about a new IRQ handling scheme. For clarity I'll describe the "standard" method, and then the new method...
Standard Method
This involves a seperate IDT descriptor and a seperate assembly handler for each IRQ. Assume the IRQ handlers all look like this (where NN is the IRQ number):
Code: Select all
IRQ_handler_NN:
push eax
mov eax, NN ;eax = IRQ number
jmp common_IRQ_handler
...
common_IRQ_handler:
GPF Method
For the alternative, the IDT limit is set short and the IDT itself only contains 36 descriptors. The IRQs are mapped to interrupt vectors that are above the IDT limit.
When an IRQ occurs, the CPU checks the IDT limit and it causes a GPF. The IRQ number is automatically stored on the stack by the CPU as part of the error code. The GPF handler begins with code like this:
Code: Select all
GPF_handler:
push eax
test byte [esp + 4], 1 ;Was it an IRQ?
je real_GPF_handler ; no, it's a real GPF
mov eax,[esp + 4]
shr eax,3 ;eax = IRQ number + 36
Because the GPF handler would be re-used for all IRQs, it's also more likely that it would already in the cache.
On modern CPUs a cache miss is costly, but I also expect that (if cache miss penalties are ignored or everything is already in the CPUs cache) a GPF will take longer.
Questions
So, which method would be faster on average?
How could the difference be measured with RDTSC (both with and without cache misses)?
Cheers,
Brendan