hv: Handle holes in GSI i.e. Global System Interrupt for multiple IO-APICs

MADT is used to specify the GSI base for each IO-APIC and the number of
interrupt pins per IO-APIC is programmed into Max. Redir. Entry register of
that IO-APIC.

On platforms with multiple IO-APICs, there can be holes in the GSI space.
For example, on a platform with 2 IO-APICs, the following configuration has
a hole (from 24 to 31) in the GSI space.

IO-APIC 1: GSI base - 0, number of pins - 24
IO-APIC 2: GSI base - 32, number of pins - 8

This patch also adjusts the size for variables used to represent the total
number of IO-APICs on the system from uint16_t to uint8_t as the ACPI MADT
uses only 8-bits to indicate the unique IO-APIC IDs.

Tracked-On: #4151
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
Acked-by: Eddie Dong <eddie.dong@Intel.com>
This commit is contained in:
Sainath Grandhi
2020-02-24 17:02:41 -08:00
committed by wenlingz
parent 85217e362f
commit f67ac09141
7 changed files with 124 additions and 135 deletions

View File

@@ -1253,7 +1253,7 @@ static int32_t shell_show_vioapic_info(int32_t argc, char **argv)
static int32_t get_ioapic_info(char *str_arg, size_t str_max_len)
{
char *str = str_arg;
uint32_t irq;
uint32_t gsi;
size_t len, size = str_max_len;
uint32_t ioapic_nr_gsi = 0U;
@@ -1264,20 +1264,21 @@ static int32_t get_ioapic_info(char *str_arg, size_t str_max_len)
size -= len;
str += len;
ioapic_nr_gsi = ioapic_get_nr_gsi ();
for (irq = 0U; irq < ioapic_nr_gsi; irq++) {
void *addr = gsi_to_ioapic_base(irq);
uint32_t pin = ioapic_irq_to_pin(irq);
ioapic_nr_gsi = get_max_nr_gsi ();
for (gsi = 0U; gsi < ioapic_nr_gsi; gsi++) {
void *addr;
uint32_t pin;
union ioapic_rte rte;
/* Add NULL check for addr, INVALID_PIN check for pin */
if ((addr == NULL) || (!ioapic_is_pin_valid(pin))) {
goto overflow;
if (!is_gsi_valid(gsi)) {
continue;
}
addr = gsi_to_ioapic_base(gsi);
pin = gsi_to_ioapic_pin(gsi);
ioapic_get_rte_entry(addr, pin, &rte);
len = snprintf(str, size, "\r\n%03d\t%03hhu\t0x%08X\t0x%08X\t", irq, pin, rte.u.hi_32, rte.u.lo_32);
len = snprintf(str, size, "\r\n%03d\t%03hhu\t0x%08X\t0x%08X\t", gsi, pin, rte.u.hi_32, rte.u.lo_32);
if (len >= size) {
goto overflow;
}
@@ -1285,8 +1286,10 @@ static int32_t get_ioapic_info(char *str_arg, size_t str_max_len)
str += len;
len = snprintf(str, size, "0x%02X\t0x%02X\t%s\t%s\t%u\t%d\t%d",
rte.bits.vector, rte.bits.dest_field, rte.bits.dest_mode ? "logic" : "phys",
rte.bits.trigger_mode ? "level" : "edge", rte.bits.delivery_mode, rte.bits.remote_irr,
rte.bits.vector, rte.bits.dest_field,
(rte.bits.dest_mode == IOAPIC_RTE_DESTMODE_LOGICAL)? "logic" : "phys",
(rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL)? "level" : "edge",
rte.bits.delivery_mode, rte.bits.remote_irr,
rte.bits.intr_mask);
if (len >= size) {
goto overflow;