Hi,
Ok - first I should say it's 5:30 in the morning here (I'm tired) and the following is from memory - it'd be a good idea to double check anything I've said before you rely on it, just in case...
thomasnilsen wrote:Well i have setup the destination mode to 0b001 (lowest priority mode) so with broadcast i guess it that only lowest priority one will handle or am i wrong?
The lowest priority delivery mode is a little tricky. The processor's priority is determined by the highest value in the TPR register, the IRR register and the ISR register (where the lowest 4 bits of the IRR and ISR are ignored); and any interrupt that is lower priority than the processor's priority won't be accepted (e.g. if all CPUs have their TPR set to 0xFF then no interrupts will be accepted by any CPU). If you don't change the TPR then all IRQs will go to the same CPU every time, unless that CPU happens to be servicing a different IRQ. How this is done is up to you.
Because interrupts range from 0x20 to 0xFF (where 0x20 is the lowest priority interrupt), any TPR value below 0x20 will allow all interrupts but still effect the "lowest priority delivery". Because of this, I'd only use TPR values below 0x20. For example:
- 0x18 to 0x1F = used when the CPU is in different sleep states, where the value depends on the latency of leaving the sleep state
0x10 to 0x17 = used when the CPU has acquired different kernel locks, where the value depends on which kernel lock
0x00 to 0x0F = used in all other cases, where the value depends on the current thread's priority
You'd also want to arrange the interrupt vectors in a prioritised way. For example, vectors 0xF0 to 0xFF (the highest priority interrupt vectors) might be reserved for IPIs and 0x20 to 0x23 might be used for the spurious interrupts. That leaves you with 13 priority levels for IRQs (e.g. 0x24 to 0x2F, 0x30 to 0x3F, 0x40 to 0x4F, etc).
Also note that you can combine this with "logical destination mode", to send the IRQ to the lowest priority CPU within a specific group of CPUs. For example, you might have an IRQ that occurs very often and you might want that IRQ to be handled by CPUs that happen to share the same L2/L3 cache (to avoid cache-line bouncing); or you might have a NUMA system and want all IRQs that originate from an I/O hub to be handled by CPUs that are "close" to that I/O hub (to avoid extra latency/hops when the IRQ handler/device driver accesses the devices). The main trick here is how you setup the "logical destination register" (e.g. you could set bit 7 in the logical destination register for all CPUs that are "close" to an I/O hub, then use logical destination mode to send an IRQ to the lowest priority CPU that has bit 7 set in it's logical destination register; and set bit 6 in the logical destination register for some CPUs that share L2/L3 caches).
For x2APIC most of this is mostly the same, except you have no control over the contents of the logical destination register - the highest 16-bits are used to select the NUMA domain and the lowest 16 bits are used to select between 1 and 16 CPUs within that NUMA domain, and therefore you can only send an interrupt to CPUs within one specific NUMA domain using logical delivery mode.
Cheers,
Brendan