How to map MSIs and IOAPIC ISRs to real int numbers
Posted: Tue Dec 06, 2011 4:20 pm
This seems to be a complicated issue. First, there are quite a few PCI devices that can request up to 16 (or is it 32?) continous interrupts. These are best allocated in some way. Currently, I have an allocator for MSI ints that can allocate a number of continous MSIs out of a pool of 64 possible MSIs. For the IO-APIC, I simply reserve 24 ints.
Problem: My 6-core AMD phenom computer has two IO-APICs (according to ACPI APIC table), and according to Windows, it uses the second IO-APIC since the Realtek network-card has ISR #40. That breaks my int allocation since I only have 24 ints available at this position.
OTOH, the IO-APIC can specify physical int-number per interrupt slot, so there is really no need for 24 continous ints per IO-APIC. It would be possible to allocate an int when an IO-APIC entry is created. That would mean that there should be a single pool of available ints that can be allocated 1,2,4,8,16 and 32 entries per call. The first ints are reserved by Intel/AMD, and then I reserve int 66, int 67, int 9A and possibly some more, but that still would mean it would possible to create a pool with at least 200 ints for allocation.
In order to convert global IRQ numbers (which ACPI uses) to physical int number, a table could be used.
There would also be a need to keep a vector of available IO-APICs. Maybe this could be combined with the global IRQ table since each IO-APIC has a base global IRQ-number.
Maybe something like this (in C syntax):
I have also discovered (on the same 6-core AMD), that using rdmsr with entry 0x1b to get the local APIC base is not reliable. The only reliable method seems to be to use the ACPI APIC table.
Problem: My 6-core AMD phenom computer has two IO-APICs (according to ACPI APIC table), and according to Windows, it uses the second IO-APIC since the Realtek network-card has ISR #40. That breaks my int allocation since I only have 24 ints available at this position.
OTOH, the IO-APIC can specify physical int-number per interrupt slot, so there is really no need for 24 continous ints per IO-APIC. It would be possible to allocate an int when an IO-APIC entry is created. That would mean that there should be a single pool of available ints that can be allocated 1,2,4,8,16 and 32 entries per call. The first ints are reserved by Intel/AMD, and then I reserve int 66, int 67, int 9A and possibly some more, but that still would mean it would possible to create a pool with at least 200 ints for allocation.
In order to convert global IRQ numbers (which ACPI uses) to physical int number, a table could be used.
There would also be a need to keep a vector of available IO-APICs. Maybe this could be combined with the global IRQ table since each IO-APIC has a base global IRQ-number.
Maybe something like this (in C syntax):
Code: Select all
struct TGlobalIntEntry
{
short int IoApicSel;
char PhysicalInt;
char TriggerMode;
};
#define MAX_GLOBAL_INTS 128
TGlobalIntEntry GlobalIntArr[MAX_GLOBAL_INTS];