Hi,
gaf wrote:Detecting the interrupt number by reading out the ISR is however prohibitively expensive as the binary logorithm of the 256bit register would have to be calculated. I would thus recommend you to rather use a more elabarated GDT design that assigns an exclusive stub to each interrupt. Using this technique it's trivial to get the interrupt number, as it just has to be stored somewhere in the stub-code..
You are of course correct (GDT stub-code would be faster), but it doesn't sound prohibitively expensive:
Code: Select all
mov ebx,0xFEE00170
.nextDword:
bsr ecx,[ebx]
jne .found
sub ebx,16
cmp ebx,0xFEE00100
jae .nextDword
jmp .errorNoneSet
.foundDword:
add bl,bl
or cl,bl ;ecx = interrupt number
Because the local APIC is built into the CPU there won't be any cache miss penalties or anything. Of course in C there's no way to generate a "bsr" instruction (and I'd be very surprised if any optimizer can convert any manual loop into a bsr or bsf instruction).
Doing the same thing for the PIC chips (if your OS supports either) would be much slower (delays caused by I/O port accesses to the "PCI to IPC bridge").
durand wrote:By the way, do you know the effect of setting the initial count of the APIC Timer to zero while it's already busy counting down a one-shot interval set earlier?
The Intel manual says "after the timer reaches zero, an timer interrupt is generated". The word "after" could mean that the interrupt is generated when the counter tries to go from zero to "-1". In this case setting the initial count to zero would generate an IRQ after N bus cycles (where N depends on the divide configuration register).
The AMD manual says "when the count reaches 0, a timer interrupt is generated". This would imply that the interrupt is generated when the count goes from 1 to zero. In this case setting the initial count to zero would mean you either won't get any IRQ or you'd get an IRQ immediately.
I really do wish the manuals were more descriptive. For e.g. would an initial count of 1 mean 2*N bus cycles (interrupt on overflow) or would an initial count of 1 mean 1*N bus cycles (interrupt as soon as zero is reached)?
I'd also like to know how long it takes before the count is first decreased. For e.g. when the divide configuration register is set to "divide by 128" and you set the initial count register, is the count first decreased 128 bus clocks after the count is set, or could it be anywhere from 1 to 128 bus clocks before the count is first decreased? If the latter case is true then reducing the "divide by" value and increasing the count would improve timing accuracy.
I would assume that setting a count of zero would mean you won't get any IRQ, and that the delay you get for a non-zero count is between "(count - 1) * divider + 1" and "count * divider" bus cycles. For e.g. with "divide by 128", for a count of 1 the delay would be between 1 and 128 bus cycles, and for a count of 2 the delay would be between 129 and 256 bus cycles.
Assumptions suck though...
Cheers,
Brendan