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

@ -15,43 +15,18 @@
#include <acpi.h> #include <acpi.h>
#include <logmsg.h> #include <logmsg.h>
#define IOAPIC_INVALID_ID 0xFFU
#define NR_MAX_GSI (CONFIG_MAX_IOAPIC_NUM * CONFIG_MAX_IOAPIC_LINES) #define NR_MAX_GSI (CONFIG_MAX_IOAPIC_NUM * CONFIG_MAX_IOAPIC_LINES)
static struct gsi_table gsi_table_data[NR_MAX_GSI]; static struct gsi_table gsi_table_data[NR_MAX_GSI];
static uint32_t ioapic_nr_gsi; static uint32_t ioapic_max_nr_gsi;
static spinlock_t ioapic_lock; static spinlock_t ioapic_lock;
static union ioapic_rte saved_rte[CONFIG_MAX_IOAPIC_NUM][CONFIG_MAX_IOAPIC_LINES]; static union ioapic_rte saved_rte[CONFIG_MAX_IOAPIC_NUM][CONFIG_MAX_IOAPIC_LINES];
/* static const uint32_t legacy_irq_trigger_mode[NR_LEGACY_PIN] = {
* the irq to ioapic pin mapping should extract from ACPI MADT table
* hardcoded here
*/
static const uint32_t legacy_irq_to_pin[NR_LEGACY_IRQ] = {
2U, /* IRQ0*/
1U, /* IRQ1*/
0U, /* IRQ2 connected to Pin0 (ExtInt source of PIC) if existing */
3U, /* IRQ3*/
4U, /* IRQ4*/
5U, /* IRQ5*/
6U, /* IRQ6*/
7U, /* IRQ7*/
8U, /* IRQ8*/
9U, /* IRQ9*/
10U, /* IRQ10*/
11U, /* IRQ11*/
12U, /* IRQ12*/
13U, /* IRQ13*/
14U, /* IRQ14*/
15U, /* IRQ15*/
};
static const uint32_t legacy_irq_trigger_mode[NR_LEGACY_IRQ] = {
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ0*/
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ1*/
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ2*/ IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ2*/
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ1*/
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ0*/
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ3*/ IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ3*/
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ4*/ IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ4*/
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ5*/ IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ5*/
@ -87,7 +62,7 @@ static const uint32_t pic_ioapic_pin_map[NR_LEGACY_PIN] = {
}; };
static struct ioapic_info ioapic_array[CONFIG_MAX_IOAPIC_NUM]; static struct ioapic_info ioapic_array[CONFIG_MAX_IOAPIC_NUM];
static uint16_t ioapic_num; static uint8_t ioapic_num;
uint32_t get_pic_pin_from_ioapic_pin(uint32_t pin_index) uint32_t get_pic_pin_from_ioapic_pin(uint32_t pin_index)
{ {
@ -104,12 +79,12 @@ uint32_t get_pic_pin_from_ioapic_pin(uint32_t pin_index)
void *gsi_to_ioapic_base(uint32_t gsi) void *gsi_to_ioapic_base(uint32_t gsi)
{ {
return gsi_table_data[gsi].addr; return gsi_table_data[gsi].ioapic_info.base_addr;
} }
uint32_t ioapic_get_nr_gsi(void) uint32_t get_max_nr_gsi(void)
{ {
return ioapic_nr_gsi; return ioapic_max_nr_gsi;
} }
static void *map_ioapic(uint64_t ioapic_paddr) static void *map_ioapic(uint64_t ioapic_paddr)
@ -211,7 +186,7 @@ create_rte_for_gsi_irq(uint32_t irq, uint32_t vr)
rte.full = 0UL; rte.full = 0UL;
if (irq < NR_LEGACY_IRQ) { if (irq < NR_LEGACY_PIN) {
rte = create_rte_for_legacy_irq(irq, vr); rte = create_rte_for_legacy_irq(irq, vr);
} else { } else {
/* irq default masked, level trig */ /* irq default masked, level trig */
@ -238,7 +213,7 @@ static void ioapic_set_routing(uint32_t gsi, uint32_t vr)
ioapic_base = gsi_to_ioapic_base(gsi); ioapic_base = gsi_to_ioapic_base(gsi);
rte = create_rte_for_gsi_irq(gsi, vr); rte = create_rte_for_gsi_irq(gsi, vr);
ioapic_set_rte_entry(ioapic_base, gsi_table_data[gsi].pin, rte); ioapic_set_rte_entry(ioapic_base, gsi_table_data[gsi].ioapic_info.pin, rte);
if (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL) { if (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL) {
set_irq_trigger_mode(gsi, true); set_irq_trigger_mode(gsi, true);
@ -247,62 +222,71 @@ static void ioapic_set_routing(uint32_t gsi, uint32_t vr)
} }
dev_dbg(DBG_LEVEL_IRQ, "GSI: irq:%d pin:%hhu rte:%lx", dev_dbg(DBG_LEVEL_IRQ, "GSI: irq:%d pin:%hhu rte:%lx",
gsi, gsi_table_data[gsi].pin, gsi, gsi_table_data[gsi].ioapic_info.pin,
rte.full); rte.full);
} }
/** /*
* @pre rte != NULL * @pre rte != NULL
* @pre is_ioapic_irq(irq) == true
*/ */
void ioapic_get_rte(uint32_t irq, union ioapic_rte *rte) void ioapic_get_rte(uint32_t irq, union ioapic_rte *rte)
{ {
void *addr; void *addr;
if (ioapic_irq_is_gsi(irq)) {
addr = gsi_to_ioapic_base(irq); addr = gsi_to_ioapic_base(irq);
ioapic_get_rte_entry(addr, gsi_table_data[irq].pin, rte); ioapic_get_rte_entry(addr, gsi_table_data[irq].ioapic_info.pin, rte);
}
} }
/*
* @pre is_ioapic_irq(irq) == true
*/
void ioapic_set_rte(uint32_t irq, union ioapic_rte rte) void ioapic_set_rte(uint32_t irq, union ioapic_rte rte)
{ {
void *addr; void *addr;
if (ioapic_irq_is_gsi(irq)) {
addr = gsi_to_ioapic_base(irq); addr = gsi_to_ioapic_base(irq);
ioapic_set_rte_entry(addr, gsi_table_data[irq].pin, rte); ioapic_set_rte_entry(addr, gsi_table_data[irq].ioapic_info.pin, rte);
dev_dbg(DBG_LEVEL_IRQ, "GSI: irq:%d pin:%hhu rte:%lx", dev_dbg(DBG_LEVEL_IRQ, "GSI: irq:%d pin:%hhu rte:%lx",
irq, gsi_table_data[irq].pin, irq, gsi_table_data[irq].ioapic_info.pin,
rte.full); rte.full);
}
}
bool ioapic_irq_is_gsi(uint32_t irq)
{
return irq < ioapic_nr_gsi;
}
uint32_t ioapic_irq_to_pin(uint32_t irq)
{
uint32_t ret;
if (ioapic_irq_is_gsi(irq)) {
ret = gsi_table_data[irq].pin;
} else {
ret = INVALID_INTERRUPT_PIN;
}
return ret;
}
bool ioapic_is_pin_valid(uint32_t pin)
{
return (pin != INVALID_INTERRUPT_PIN);
} }
/* /*
*@pre ioapic_irq_is_gsi(gsi) == true * Checks if the gsi is valid
* 1) gsi < NR_MAX_GSI
* 2) gsi is valid on the platform according to ACPI MADT info
*/
bool is_gsi_valid(uint32_t gsi)
{
return (gsi < NR_MAX_GSI) && (gsi_table_data[gsi].is_valid);
}
/*
* IO-APIC gsi and irq are identity mapped in ioapic_setup_irqs
* So #gsi = #irq for ACRN
*/
bool is_ioapic_irq(uint32_t irq)
{
return is_gsi_valid(irq);
}
/*
*@pre gsi < NR_MAX_GSI
*@pre is_gsi_valid(gsi) == true
*/
uint32_t gsi_to_ioapic_pin(uint32_t gsi)
{
return gsi_table_data[gsi].ioapic_info.pin;
}
/*
*@pre is_gsi_valid(gsi) == true
*/ */
uint32_t ioapic_gsi_to_irq(uint32_t gsi) uint32_t ioapic_gsi_to_irq(uint32_t gsi)
{ {
@ -316,9 +300,8 @@ ioapic_irq_gsi_mask_unmask(uint32_t irq, bool mask)
uint32_t pin; uint32_t pin;
union ioapic_rte rte; union ioapic_rte rte;
if (ioapic_irq_is_gsi(irq)) {
addr = gsi_to_ioapic_base(irq); addr = gsi_to_ioapic_base(irq);
pin = gsi_table_data[irq].pin; pin = gsi_table_data[irq].ioapic_info.pin;
if (addr != NULL) { if (addr != NULL) {
ioapic_get_rte_entry(addr, pin, &rte); ioapic_get_rte_entry(addr, pin, &rte);
@ -333,7 +316,6 @@ ioapic_irq_gsi_mask_unmask(uint32_t irq, bool mask)
} else { } else {
dev_dbg(DBG_LEVEL_PTIRQ, "NULL Address returned from gsi_table_data"); dev_dbg(DBG_LEVEL_PTIRQ, "NULL Address returned from gsi_table_data");
} }
}
} }
void ioapic_gsi_mask_irq(uint32_t irq) void ioapic_gsi_mask_irq(uint32_t irq)
@ -364,17 +346,13 @@ ioapic_nr_pins(void *ioapic_base)
return nr_pins; return nr_pins;
} }
/*
* @pre is_ioapic_irq(irq) == true
*/
uint8_t ioapic_irq_to_ioapic_id(uint32_t irq) uint8_t ioapic_irq_to_ioapic_id(uint32_t irq)
{ {
uint8_t ret;
if (ioapic_irq_is_gsi(irq)) { return gsi_table_data[irq].ioapic_info.acpi_id;
ret = gsi_table_data[irq].ioapic_id;
} else {
ret = IOAPIC_INVALID_ID;
}
return ret;
} }
int32_t init_ioapic_id_info(void) int32_t init_ioapic_id_info(void)
@ -385,7 +363,7 @@ int32_t init_ioapic_id_info(void)
uint32_t nr_pins, gsi; uint32_t nr_pins, gsi;
ioapic_num = parse_madt_ioapic(&ioapic_array[0]); ioapic_num = parse_madt_ioapic(&ioapic_array[0]);
if (ioapic_num <= (uint16_t)CONFIG_MAX_IOAPIC_NUM) { if (ioapic_num <= (uint8_t)CONFIG_MAX_IOAPIC_NUM) {
/* /*
* Iterate thru all the IO-APICs on the platform * Iterate thru all the IO-APICs on the platform
* Check the number of pins available on each IOAPIC is less * Check the number of pins available on each IOAPIC is less
@ -415,7 +393,7 @@ int32_t init_ioapic_id_info(void)
*/ */
if (ret == 0) { if (ret == 0) {
if (gsi < (uint32_t) NR_LEGACY_IRQ) { if (gsi < (uint32_t) NR_LEGACY_PIN) {
pr_err ("Total pin count (%x) is less than NR_LEGACY_IRQ!", gsi); pr_err ("Total pin count (%x) is less than NR_LEGACY_IRQ!", gsi);
ret = -EINVAL; ret = -EINVAL;
} }
@ -446,16 +424,13 @@ void ioapic_setup_irqs(void)
addr = map_ioapic(ioapic_array[ioapic_id].addr); addr = map_ioapic(ioapic_array[ioapic_id].addr);
nr_pins = ioapic_array[ioapic_id].nr_pins; nr_pins = ioapic_array[ioapic_id].nr_pins;
gsi = ioapic_array[ioapic_id].gsi_base;
for (pin = 0U; pin < nr_pins; pin++) { for (pin = 0U; pin < nr_pins; pin++) {
gsi_table_data[gsi].ioapic_id = ioapic_array[ioapic_id].id; gsi_table_data[gsi].is_valid = true;
gsi_table_data[gsi].addr = addr; gsi_table_data[gsi].ioapic_info.acpi_id = ioapic_array[ioapic_id].id;
gsi_table_data[gsi].ioapic_info.base_addr = addr;
if (gsi < NR_LEGACY_IRQ) { gsi_table_data[gsi].ioapic_info.pin = pin;
gsi_table_data[gsi].pin = gsi_table_data[gsi].ioapic_info.index = ioapic_id;
legacy_irq_to_pin[gsi] & 0xffU;
} else {
gsi_table_data[gsi].pin = pin;
}
/* pinned irq before use it */ /* pinned irq before use it */
if (alloc_irq_num(gsi) == IRQ_INVALID) { if (alloc_irq_num(gsi) == IRQ_INVALID) {
@ -467,7 +442,7 @@ void ioapic_setup_irqs(void)
/* assign vector for this GSI /* assign vector for this GSI
* for legacy irq, reserved vector and never free * for legacy irq, reserved vector and never free
*/ */
if (gsi < NR_LEGACY_IRQ) { if (gsi < NR_LEGACY_PIN) {
vr = alloc_irq_vector(gsi); vr = alloc_irq_vector(gsi);
if (vr == VECTOR_INVALID) { if (vr == VECTOR_INVALID) {
pr_err("failed to alloc VR"); pr_err("failed to alloc VR");
@ -484,7 +459,7 @@ void ioapic_setup_irqs(void)
} }
/* system max gsi numbers */ /* system max gsi numbers */
ioapic_nr_gsi = gsi; ioapic_max_nr_gsi = gsi;
} }
void suspend_ioapic(void) void suspend_ioapic(void)

View File

@ -82,7 +82,7 @@ static void free_irq_num(uint32_t irq)
uint64_t rflags; uint64_t rflags;
if (irq < NR_IRQS) { if (irq < NR_IRQS) {
if (!ioapic_irq_is_gsi(irq)) { if (!is_ioapic_irq(irq)) {
spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags); spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags);
(void)bitmap_test_and_clear_nolock((uint16_t)(irq & 0x3FU), (void)bitmap_test_and_clear_nolock((uint16_t)(irq & 0x3FU),
irq_alloc_bitmap + (irq >> 6U)); irq_alloc_bitmap + (irq >> 6U));
@ -301,7 +301,7 @@ static inline bool irq_need_mask(const struct irq_desc *desc)
{ {
/* level triggered gsi should be masked */ /* level triggered gsi should be masked */
return (((desc->flags & IRQF_LEVEL) != 0U) return (((desc->flags & IRQF_LEVEL) != 0U)
&& ioapic_irq_is_gsi(desc->irq)); && is_ioapic_irq(desc->irq));
} }
static inline bool irq_need_unmask(const struct irq_desc *desc) static inline bool irq_need_unmask(const struct irq_desc *desc)
@ -309,7 +309,7 @@ static inline bool irq_need_unmask(const struct irq_desc *desc)
/* level triggered gsi for non-ptdev should be unmasked */ /* level triggered gsi for non-ptdev should be unmasked */
return (((desc->flags & IRQF_LEVEL) != 0U) return (((desc->flags & IRQF_LEVEL) != 0U)
&& ((desc->flags & IRQF_PT) == 0U) && ((desc->flags & IRQF_PT) == 0U)
&& ioapic_irq_is_gsi(desc->irq)); && is_ioapic_irq(desc->irq));
} }
static inline void handle_irq(const struct irq_desc *desc) static inline void handle_irq(const struct irq_desc *desc)

View File

@ -209,14 +209,14 @@ local_parse_madt(struct acpi_table_madt *madt, uint32_t lapic_id_array[MAX_PCPU_
return pcpu_num; return pcpu_num;
} }
static uint16_t static uint8_t
ioapic_parse_madt(void *madt, struct ioapic_info *ioapic_id_array) ioapic_parse_madt(void *madt, struct ioapic_info *ioapic_id_array)
{ {
struct acpi_madt_ioapic *ioapic; struct acpi_madt_ioapic *ioapic;
struct acpi_table_madt *madt_ptr; struct acpi_table_madt *madt_ptr;
void *first, *end, *iterator; void *first, *end, *iterator;
struct acpi_subtable_header *entry; struct acpi_subtable_header *entry;
uint16_t ioapic_idx = 0U; uint8_t ioapic_idx = 0U;
madt_ptr = (struct acpi_table_madt *)madt; madt_ptr = (struct acpi_table_madt *)madt;
@ -261,9 +261,9 @@ uint16_t parse_madt(uint32_t lapic_id_array[MAX_PCPU_NUM])
return ret; return ret;
} }
uint16_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array) uint8_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array)
{ {
uint16_t ret = 0U; uint8_t ret = 0U;
struct acpi_table_rsdp *rsdp = NULL; struct acpi_table_rsdp *rsdp = NULL;
rsdp = get_rsdp(); rsdp = get_rsdp();

View File

@ -203,7 +203,7 @@ void *get_acpi_tbl(const char *signature);
struct ioapic_info; struct ioapic_info;
uint16_t parse_madt(uint32_t lapic_id_array[MAX_PCPU_NUM]); uint16_t parse_madt(uint32_t lapic_id_array[MAX_PCPU_NUM]);
uint16_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array); uint8_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array);
#ifdef CONFIG_ACPI_PARSE_ENABLED #ifdef CONFIG_ACPI_PARSE_ENABLED
int32_t acpi_fixup(void); int32_t acpi_fixup(void);

View File

@ -908,7 +908,7 @@ int32_t hcall_set_ptdev_intr_info(struct acrn_vm *vm, uint16_t vmid, uint64_t pa
if ((vdev != NULL) && (vdev->pdev->bdf.value == irq.phys_bdf)) { if ((vdev != NULL) && (vdev->pdev->bdf.value == irq.phys_bdf)) {
if ((((!irq.intx.pic_pin) && (irq.intx.virt_pin < vioapic_pincount(target_vm))) || if ((((!irq.intx.pic_pin) && (irq.intx.virt_pin < vioapic_pincount(target_vm))) ||
((irq.intx.pic_pin) && (irq.intx.virt_pin < vpic_pincount()))) && ((irq.intx.pic_pin) && (irq.intx.virt_pin < vpic_pincount()))) &&
ioapic_irq_is_gsi(irq.intx.phys_pin)) { is_gsi_valid(irq.intx.phys_pin)) {
ret = ptirq_add_intx_remapping(target_vm, irq.intx.virt_pin, ret = ptirq_add_intx_remapping(target_vm, irq.intx.virt_pin,
irq.intx.phys_pin, irq.intx.pic_pin); irq.intx.phys_pin, irq.intx.pic_pin);
} else { } else {

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) static int32_t get_ioapic_info(char *str_arg, size_t str_max_len)
{ {
char *str = str_arg; char *str = str_arg;
uint32_t irq; uint32_t gsi;
size_t len, size = str_max_len; size_t len, size = str_max_len;
uint32_t ioapic_nr_gsi = 0U; 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; size -= len;
str += len; str += len;
ioapic_nr_gsi = ioapic_get_nr_gsi (); ioapic_nr_gsi = get_max_nr_gsi ();
for (irq = 0U; irq < ioapic_nr_gsi; irq++) { for (gsi = 0U; gsi < ioapic_nr_gsi; gsi++) {
void *addr = gsi_to_ioapic_base(irq); void *addr;
uint32_t pin = ioapic_irq_to_pin(irq); uint32_t pin;
union ioapic_rte rte; union ioapic_rte rte;
/* Add NULL check for addr, INVALID_PIN check for pin */ if (!is_gsi_valid(gsi)) {
if ((addr == NULL) || (!ioapic_is_pin_valid(pin))) { continue;
goto overflow;
} }
addr = gsi_to_ioapic_base(gsi);
pin = gsi_to_ioapic_pin(gsi);
ioapic_get_rte_entry(addr, pin, &rte); 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) { if (len >= size) {
goto overflow; goto overflow;
} }
@ -1285,8 +1286,10 @@ static int32_t get_ioapic_info(char *str_arg, size_t str_max_len)
str += len; str += len;
len = snprintf(str, size, "0x%02X\t0x%02X\t%s\t%s\t%u\t%d\t%d", 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.vector, rte.bits.dest_field,
rte.bits.trigger_mode ? "level" : "edge", rte.bits.delivery_mode, rte.bits.remote_irr, (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); rte.bits.intr_mask);
if (len >= size) { if (len >= size) {
goto overflow; goto overflow;

View File

@ -21,8 +21,8 @@ struct ioapic_info {
void ioapic_setup_irqs(void); void ioapic_setup_irqs(void);
bool ioapic_irq_is_gsi(uint32_t irq); bool is_ioapic_irq(uint32_t irq);
uint32_t ioapic_irq_to_pin(uint32_t irq); uint32_t gsi_to_ioapic_pin(uint32_t gsi);
int32_t init_ioapic_id_info(void); int32_t init_ioapic_id_info(void);
uint8_t ioapic_irq_to_ioapic_id(uint32_t irq); uint8_t ioapic_irq_to_ioapic_id(uint32_t irq);
@ -88,15 +88,26 @@ void ioapic_gsi_unmask_irq(uint32_t irq);
void ioapic_get_rte_entry(void *ioapic_base, uint32_t pin, union ioapic_rte *rte); void ioapic_get_rte_entry(void *ioapic_base, uint32_t pin, union ioapic_rte *rte);
/*
* is_valid is by default false when all the
* static variables, part of .bss, are initialized to 0s
* It is set to true, if the corresponding
* gsi falls in ranges identified by IOAPIC data
* in ACPI MADT in ioapic_setup_irqs.
*/
struct gsi_table { struct gsi_table {
uint8_t ioapic_id; bool is_valid;
struct {
uint8_t acpi_id;
uint8_t index;
uint32_t pin; uint32_t pin;
void *addr; void *base_addr;
} ioapic_info;
}; };
void *gsi_to_ioapic_base(uint32_t gsi); void *gsi_to_ioapic_base(uint32_t gsi);
uint32_t ioapic_get_nr_gsi(void); uint32_t get_max_nr_gsi(void);
uint32_t get_pic_pin_from_ioapic_pin(uint32_t pin_index); uint32_t get_pic_pin_from_ioapic_pin(uint32_t pin_index);
bool ioapic_is_pin_valid(uint32_t pin); bool is_gsi_valid(uint32_t gsi);
#endif /* IOAPIC_H */ #endif /* IOAPIC_H */