mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-26 15:31:35 +00:00
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:
parent
85217e362f
commit
f67ac09141
@ -15,43 +15,18 @@
|
||||
#include <acpi.h>
|
||||
#include <logmsg.h>
|
||||
|
||||
#define IOAPIC_INVALID_ID 0xFFU
|
||||
|
||||
#define NR_MAX_GSI (CONFIG_MAX_IOAPIC_NUM * CONFIG_MAX_IOAPIC_LINES)
|
||||
|
||||
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 union ioapic_rte saved_rte[CONFIG_MAX_IOAPIC_NUM][CONFIG_MAX_IOAPIC_LINES];
|
||||
|
||||
/*
|
||||
* 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*/
|
||||
static const uint32_t legacy_irq_trigger_mode[NR_LEGACY_PIN] = {
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ2*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ1*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ0*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ3*/
|
||||
IOAPIC_RTE_TRGRMODE_EDGE, /* IRQ4*/
|
||||
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 uint16_t ioapic_num;
|
||||
static uint8_t ioapic_num;
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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)
|
||||
@ -211,7 +186,7 @@ create_rte_for_gsi_irq(uint32_t irq, uint32_t vr)
|
||||
|
||||
rte.full = 0UL;
|
||||
|
||||
if (irq < NR_LEGACY_IRQ) {
|
||||
if (irq < NR_LEGACY_PIN) {
|
||||
rte = create_rte_for_legacy_irq(irq, vr);
|
||||
} else {
|
||||
/* 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);
|
||||
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) {
|
||||
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",
|
||||
gsi, gsi_table_data[gsi].pin,
|
||||
gsi, gsi_table_data[gsi].ioapic_info.pin,
|
||||
rte.full);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @pre rte != NULL
|
||||
* @pre is_ioapic_irq(irq) == true
|
||||
*/
|
||||
void ioapic_get_rte(uint32_t irq, union ioapic_rte *rte)
|
||||
{
|
||||
void *addr;
|
||||
|
||||
if (ioapic_irq_is_gsi(irq)) {
|
||||
addr = gsi_to_ioapic_base(irq);
|
||||
ioapic_get_rte_entry(addr, gsi_table_data[irq].pin, rte);
|
||||
}
|
||||
addr = gsi_to_ioapic_base(irq);
|
||||
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 *addr;
|
||||
|
||||
if (ioapic_irq_is_gsi(irq)) {
|
||||
addr = gsi_to_ioapic_base(irq);
|
||||
ioapic_set_rte_entry(addr, gsi_table_data[irq].pin, rte);
|
||||
addr = gsi_to_ioapic_base(irq);
|
||||
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",
|
||||
irq, gsi_table_data[irq].pin,
|
||||
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);
|
||||
dev_dbg(DBG_LEVEL_IRQ, "GSI: irq:%d pin:%hhu rte:%lx",
|
||||
irq, gsi_table_data[irq].ioapic_info.pin,
|
||||
rte.full);
|
||||
}
|
||||
|
||||
/*
|
||||
*@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)
|
||||
{
|
||||
@ -316,23 +300,21 @@ ioapic_irq_gsi_mask_unmask(uint32_t irq, bool mask)
|
||||
uint32_t pin;
|
||||
union ioapic_rte rte;
|
||||
|
||||
if (ioapic_irq_is_gsi(irq)) {
|
||||
addr = gsi_to_ioapic_base(irq);
|
||||
pin = gsi_table_data[irq].pin;
|
||||
addr = gsi_to_ioapic_base(irq);
|
||||
pin = gsi_table_data[irq].ioapic_info.pin;
|
||||
|
||||
if (addr != NULL) {
|
||||
ioapic_get_rte_entry(addr, pin, &rte);
|
||||
if (mask) {
|
||||
rte.bits.intr_mask = IOAPIC_RTE_MASK_SET;
|
||||
} else {
|
||||
rte.bits.intr_mask = IOAPIC_RTE_MASK_CLR;
|
||||
}
|
||||
ioapic_set_rte_entry(addr, pin, rte);
|
||||
dev_dbg(DBG_LEVEL_PTIRQ, "update: irq:%d pin:%hhu rte:%lx",
|
||||
irq, pin, rte.full);
|
||||
if (addr != NULL) {
|
||||
ioapic_get_rte_entry(addr, pin, &rte);
|
||||
if (mask) {
|
||||
rte.bits.intr_mask = IOAPIC_RTE_MASK_SET;
|
||||
} else {
|
||||
dev_dbg(DBG_LEVEL_PTIRQ, "NULL Address returned from gsi_table_data");
|
||||
rte.bits.intr_mask = IOAPIC_RTE_MASK_CLR;
|
||||
}
|
||||
ioapic_set_rte_entry(addr, pin, rte);
|
||||
dev_dbg(DBG_LEVEL_PTIRQ, "update: irq:%d pin:%hhu rte:%lx",
|
||||
irq, pin, rte.full);
|
||||
} else {
|
||||
dev_dbg(DBG_LEVEL_PTIRQ, "NULL Address returned from gsi_table_data");
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,17 +346,13 @@ ioapic_nr_pins(void *ioapic_base)
|
||||
return nr_pins;
|
||||
}
|
||||
|
||||
/*
|
||||
* @pre is_ioapic_irq(irq) == true
|
||||
*/
|
||||
uint8_t ioapic_irq_to_ioapic_id(uint32_t irq)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
if (ioapic_irq_is_gsi(irq)) {
|
||||
ret = gsi_table_data[irq].ioapic_id;
|
||||
} else {
|
||||
ret = IOAPIC_INVALID_ID;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return gsi_table_data[irq].ioapic_info.acpi_id;
|
||||
}
|
||||
|
||||
int32_t init_ioapic_id_info(void)
|
||||
@ -385,7 +363,7 @@ int32_t init_ioapic_id_info(void)
|
||||
uint32_t nr_pins, gsi;
|
||||
|
||||
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
|
||||
* 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 (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);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
@ -446,16 +424,13 @@ void ioapic_setup_irqs(void)
|
||||
addr = map_ioapic(ioapic_array[ioapic_id].addr);
|
||||
|
||||
nr_pins = ioapic_array[ioapic_id].nr_pins;
|
||||
gsi = ioapic_array[ioapic_id].gsi_base;
|
||||
for (pin = 0U; pin < nr_pins; pin++) {
|
||||
gsi_table_data[gsi].ioapic_id = ioapic_array[ioapic_id].id;
|
||||
gsi_table_data[gsi].addr = addr;
|
||||
|
||||
if (gsi < NR_LEGACY_IRQ) {
|
||||
gsi_table_data[gsi].pin =
|
||||
legacy_irq_to_pin[gsi] & 0xffU;
|
||||
} else {
|
||||
gsi_table_data[gsi].pin = pin;
|
||||
}
|
||||
gsi_table_data[gsi].is_valid = true;
|
||||
gsi_table_data[gsi].ioapic_info.acpi_id = ioapic_array[ioapic_id].id;
|
||||
gsi_table_data[gsi].ioapic_info.base_addr = addr;
|
||||
gsi_table_data[gsi].ioapic_info.pin = pin;
|
||||
gsi_table_data[gsi].ioapic_info.index = ioapic_id;
|
||||
|
||||
/* pinned irq before use it */
|
||||
if (alloc_irq_num(gsi) == IRQ_INVALID) {
|
||||
@ -467,7 +442,7 @@ void ioapic_setup_irqs(void)
|
||||
/* assign vector for this GSI
|
||||
* for legacy irq, reserved vector and never free
|
||||
*/
|
||||
if (gsi < NR_LEGACY_IRQ) {
|
||||
if (gsi < NR_LEGACY_PIN) {
|
||||
vr = alloc_irq_vector(gsi);
|
||||
if (vr == VECTOR_INVALID) {
|
||||
pr_err("failed to alloc VR");
|
||||
@ -484,7 +459,7 @@ void ioapic_setup_irqs(void)
|
||||
}
|
||||
|
||||
/* system max gsi numbers */
|
||||
ioapic_nr_gsi = gsi;
|
||||
ioapic_max_nr_gsi = gsi;
|
||||
}
|
||||
|
||||
void suspend_ioapic(void)
|
||||
|
@ -82,7 +82,7 @@ static void free_irq_num(uint32_t irq)
|
||||
uint64_t rflags;
|
||||
|
||||
if (irq < NR_IRQS) {
|
||||
if (!ioapic_irq_is_gsi(irq)) {
|
||||
if (!is_ioapic_irq(irq)) {
|
||||
spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags);
|
||||
(void)bitmap_test_and_clear_nolock((uint16_t)(irq & 0x3FU),
|
||||
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 */
|
||||
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)
|
||||
@ -309,7 +309,7 @@ static inline bool irq_need_unmask(const struct irq_desc *desc)
|
||||
/* level triggered gsi for non-ptdev should be unmasked */
|
||||
return (((desc->flags & IRQF_LEVEL) != 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)
|
||||
|
@ -209,14 +209,14 @@ local_parse_madt(struct acpi_table_madt *madt, uint32_t lapic_id_array[MAX_PCPU_
|
||||
return pcpu_num;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
static uint8_t
|
||||
ioapic_parse_madt(void *madt, struct ioapic_info *ioapic_id_array)
|
||||
{
|
||||
struct acpi_madt_ioapic *ioapic;
|
||||
struct acpi_table_madt *madt_ptr;
|
||||
void *first, *end, *iterator;
|
||||
struct acpi_subtable_header *entry;
|
||||
uint16_t ioapic_idx = 0U;
|
||||
uint8_t ioapic_idx = 0U;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
rsdp = get_rsdp();
|
||||
|
@ -203,7 +203,7 @@ void *get_acpi_tbl(const char *signature);
|
||||
|
||||
struct ioapic_info;
|
||||
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
|
||||
int32_t acpi_fixup(void);
|
||||
|
@ -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 ((((!irq.intx.pic_pin) && (irq.intx.virt_pin < vioapic_pincount(target_vm))) ||
|
||||
((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,
|
||||
irq.intx.phys_pin, irq.intx.pic_pin);
|
||||
} else {
|
||||
|
@ -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;
|
||||
|
@ -21,8 +21,8 @@ struct ioapic_info {
|
||||
|
||||
void ioapic_setup_irqs(void);
|
||||
|
||||
bool ioapic_irq_is_gsi(uint32_t irq);
|
||||
uint32_t ioapic_irq_to_pin(uint32_t irq);
|
||||
bool is_ioapic_irq(uint32_t irq);
|
||||
uint32_t gsi_to_ioapic_pin(uint32_t gsi);
|
||||
int32_t init_ioapic_id_info(void);
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
uint8_t ioapic_id;
|
||||
uint32_t pin;
|
||||
void *addr;
|
||||
bool is_valid;
|
||||
struct {
|
||||
uint8_t acpi_id;
|
||||
uint8_t index;
|
||||
uint32_t pin;
|
||||
void *base_addr;
|
||||
} ioapic_info;
|
||||
};
|
||||
|
||||
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);
|
||||
bool ioapic_is_pin_valid(uint32_t pin);
|
||||
|
||||
bool is_gsi_valid(uint32_t gsi);
|
||||
#endif /* IOAPIC_H */
|
||||
|
Loading…
Reference in New Issue
Block a user