diff --git a/hypervisor/arch/x86/assign.c b/hypervisor/arch/x86/assign.c index bb831c525..d039ae30c 100644 --- a/hypervisor/arch/x86/assign.c +++ b/hypervisor/arch/x86/assign.c @@ -5,6 +5,7 @@ */ #include +#include /* * lookup a ptdev entry by sid @@ -286,11 +287,11 @@ static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint8 uint8_t vpin_src = pic_pin ? PTDEV_VPIN_PIC : PTDEV_VPIN_IOAPIC; DEFINE_IOAPIC_SID(phys_sid, phys_pin, 0); DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src); - uint32_t phys_irq = pin_to_irq(phys_pin); + uint32_t phys_irq = ioapic_pin_to_irq(phys_pin); if ((!pic_pin && (virt_pin >= vioapic_pincount(vm))) || (pic_pin && (virt_pin >= vpic_pincount()))) { pr_err("ptirq_add_intx_remapping fails!\n"); - } else if (!irq_is_gsi(phys_irq)) { + } else if (!ioapic_irq_is_gsi(phys_irq)) { pr_err("%s, invalid phys_pin: %d <-> irq: 0x%x is not a GSI\n", __func__, phys_pin, phys_irq); } else { entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &phys_sid, NULL); @@ -352,7 +353,7 @@ static void remove_intx_remapping(struct acrn_vm *vm, uint8_t virt_pin, bool pic if (is_entry_active(entry)) { phys_irq = entry->allocated_pirq; /* disable interrupt */ - gsi_mask_irq(phys_irq); + ioapic_gsi_mask_irq(phys_irq); ptirq_deactivate_entry(entry); dev_dbg(ACRN_DBG_IRQ, @@ -510,7 +511,7 @@ void ptirq_intx_ack(struct acrn_vm *vm, uint8_t virt_pin, dev_dbg(ACRN_DBG_PTIRQ, "dev-assign: irq=0x%x acked vr: 0x%x", phys_irq, irq_to_vector(phys_irq)); - gsi_unmask_irq(phys_irq); + ioapic_gsi_unmask_irq(phys_irq); } } @@ -580,7 +581,7 @@ static void activate_physical_ioapic(struct acrn_vm *vm, bool is_lvl_trigger = false; /* disable interrupt */ - gsi_mask_irq(phys_irq); + ioapic_gsi_mask_irq(phys_irq); /* build physical IOAPIC RTE */ rte = ptirq_build_physical_rte(vm, entry); @@ -597,7 +598,7 @@ static void activate_physical_ioapic(struct acrn_vm *vm, ioapic_set_rte(phys_irq, rte); if (intr_mask == IOAPIC_RTE_INTMCLR) { - gsi_unmask_irq(phys_irq); + ioapic_gsi_unmask_irq(phys_irq); } } @@ -647,7 +648,7 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin, uint8_t vpin_ * switch vpin source is needed */ if (virt_pin < NR_LEGACY_PIN) { - uint8_t vpin = pic_ioapic_pin_map[virt_pin]; + uint8_t vpin = get_pic_pin_from_ioapic_pin(virt_pin); entry = ptirq_lookup_entry_by_vpin(vm, vpin, !pic_pin); if (entry != NULL) { @@ -661,7 +662,7 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin, uint8_t vpin_ /* fix vPIC pin to correct native IOAPIC pin */ if (pic_pin) { - phys_pin = pic_ioapic_pin_map[virt_pin]; + phys_pin = get_pic_pin_from_ioapic_pin(virt_pin); } entry = add_intx_remapping(vm, virt_pin, phys_pin, pic_pin); diff --git a/hypervisor/arch/x86/ioapic.c b/hypervisor/arch/x86/ioapic.c index c99fe76d7..3fbdb7c7e 100644 --- a/hypervisor/arch/x86/ioapic.c +++ b/hypervisor/arch/x86/ioapic.c @@ -5,12 +5,20 @@ */ #include +#include #define IOAPIC_MAX_PIN 240U #define IOAPIC_INVALID_PIN 0xffU -struct gsi_table gsi_table[NR_MAX_GSI]; -uint32_t nr_gsi; +/* + * IOAPIC_MAX_LINES is architecturally defined. + * The usable RTEs may be a subset of the total on a per IO APIC basis. + */ +#define IOAPIC_MAX_LINES 120U +#define NR_MAX_GSI (NR_IOAPICS * IOAPIC_MAX_LINES) + +static struct gsi_table gsi_table_data[NR_MAX_GSI]; +static uint32_t ioapic_nr_gsi; static spinlock_t ioapic_lock; static union ioapic_rte saved_rte[NR_IOAPICS][IOAPIC_MAX_PIN]; @@ -76,6 +84,26 @@ const uint8_t pic_ioapic_pin_map[NR_LEGACY_PIN] = { 15U, /* pin15*/ }; +uint8_t get_pic_pin_from_ioapic_pin (uint8_t pin_index) { + uint8_t pin_id = IOAPIC_INVALID_PIN; + if (pin_index < NR_LEGACY_PIN) { + pin_id = pic_ioapic_pin_map[pin_index]; + } + return pin_id; +} + +void *ioapic_get_gsi_irq_addr (uint32_t irq_num) { + void *addr = NULL; + if (irq_num < NR_MAX_GSI) { + addr = gsi_table_data[irq_num].addr; + } + return addr; +} + +uint32_t ioapic_get_nr_gsi (void) { + return ioapic_nr_gsi; +} + static void *map_ioapic(uint64_t ioapic_paddr) { /* At some point we may need to translate this paddr to a vaddr. @@ -199,9 +227,9 @@ static void ioapic_set_routing(uint32_t gsi, uint32_t vr) void *addr; union ioapic_rte rte; - addr = gsi_table[gsi].addr; + addr = gsi_table_data[gsi].addr; rte = create_rte_for_gsi_irq(gsi, vr); - ioapic_set_rte_entry(addr, gsi_table[gsi].pin, rte); + ioapic_set_rte_entry(addr, gsi_table_data[gsi].pin, rte); if ((rte.full & IOAPIC_RTE_TRGRMOD) != 0UL) { set_irq_trigger_mode(gsi, true); @@ -210,7 +238,7 @@ static void ioapic_set_routing(uint32_t gsi, uint32_t vr) } dev_dbg(ACRN_DBG_IRQ, "GSI: irq:%d pin:%hhu rte:%lx", - gsi, gsi_table[gsi].pin, + gsi, gsi_table_data[gsi].pin, rte.full); } @@ -221,9 +249,9 @@ void ioapic_get_rte(uint32_t irq, union ioapic_rte *rte) { void *addr; - if (irq_is_gsi(irq)) { - addr = gsi_table[irq].addr; - ioapic_get_rte_entry(addr, gsi_table[irq].pin, rte); + if (ioapic_irq_is_gsi(irq)) { + addr = gsi_table_data[irq].addr; + ioapic_get_rte_entry(addr, gsi_table_data[irq].pin, rte); } } @@ -231,27 +259,27 @@ void ioapic_set_rte(uint32_t irq, union ioapic_rte rte) { void *addr; - if (irq_is_gsi(irq)) { - addr = gsi_table[irq].addr; - ioapic_set_rte_entry(addr, gsi_table[irq].pin, rte); + if (ioapic_irq_is_gsi(irq)) { + addr = gsi_table_data[irq].addr; + ioapic_set_rte_entry(addr, gsi_table_data[irq].pin, rte); dev_dbg(ACRN_DBG_IRQ, "GSI: irq:%d pin:%hhu rte:%lx", - irq, gsi_table[irq].pin, + irq, gsi_table_data[irq].pin, rte.full); } } -bool irq_is_gsi(uint32_t irq) +bool ioapic_irq_is_gsi(uint32_t irq) { - return irq < nr_gsi; + return irq < ioapic_nr_gsi; } -uint8_t irq_to_pin(uint32_t irq) +uint8_t ioapic_irq_to_pin(uint32_t irq) { uint8_t ret; - if (irq_is_gsi(irq)) { - ret = gsi_table[irq].pin; + if (ioapic_irq_is_gsi(irq)) { + ret = gsi_table_data[irq].pin; } else { ret = IOAPIC_INVALID_PIN; } @@ -259,13 +287,17 @@ uint8_t irq_to_pin(uint32_t irq) return ret; } -uint32_t pin_to_irq(uint8_t pin) +bool ioapic_is_pin_valid (uint8_t pin) { + return (pin != IOAPIC_INVALID_PIN); +} + +uint32_t ioapic_pin_to_irq(uint8_t pin) { uint32_t i; uint32_t irq = IRQ_INVALID; - for (i = 0U; i < nr_gsi; i++) { - if (gsi_table[i].pin == pin) { + for (i = 0U; i < ioapic_nr_gsi; i++) { + if (gsi_table_data[i].pin == pin) { irq = i; break; } @@ -274,36 +306,40 @@ uint32_t pin_to_irq(uint8_t pin) } static void -irq_gsi_mask_unmask(uint32_t irq, bool mask) +ioapic_irq_gsi_mask_unmask(uint32_t irq, bool mask) { - void *addr; + void *addr = NULL; uint8_t pin; union ioapic_rte rte; - if (irq_is_gsi(irq)) { - addr = gsi_table[irq].addr; - pin = gsi_table[irq].pin; + if (ioapic_irq_is_gsi(irq)) { + addr = gsi_table_data[irq].addr; + pin = gsi_table_data[irq].pin; - ioapic_get_rte_entry(addr, pin, &rte); - if (mask) { - rte.full |= IOAPIC_RTE_INTMSET; + if (addr != NULL) { + ioapic_get_rte_entry(addr, pin, &rte); + if (mask) { + rte.full |= IOAPIC_RTE_INTMSET; + } else { + rte.full &= ~IOAPIC_RTE_INTMASK; + } + ioapic_set_rte_entry(addr, pin, rte); + dev_dbg(ACRN_DBG_PTIRQ, "update: irq:%d pin:%hhu rte:%lx", + irq, pin, rte.full); } else { - rte.full &= ~IOAPIC_RTE_INTMASK; + dev_dbg(ACRN_DBG_PTIRQ, "NULL Address returned from gsi_table_data"); } - ioapic_set_rte_entry(addr, pin, rte); - dev_dbg(ACRN_DBG_PTIRQ, "update: irq:%d pin:%hhu rte:%lx", - irq, pin, rte.full); } } -void gsi_mask_irq(uint32_t irq) +void ioapic_gsi_mask_irq(uint32_t irq) { - irq_gsi_mask_unmask(irq, true); + ioapic_irq_gsi_mask_unmask(irq, true); } -void gsi_unmask_irq(uint32_t irq) +void ioapic_gsi_unmask_irq(uint32_t irq) { - irq_gsi_mask_unmask(irq, false); + ioapic_irq_gsi_mask_unmask(irq, false); } static uint8_t @@ -327,7 +363,7 @@ ioapic_nr_pins(void *ioapic_base) return nr_pins; } -void setup_ioapic_irqs(void) +void ioapic_setup_irqs(void) { uint8_t ioapic_id; uint32_t gsi = 0U; @@ -345,14 +381,14 @@ void setup_ioapic_irqs(void) nr_pins = ioapic_nr_pins(addr); for (pin = 0U; pin < nr_pins; pin++) { - gsi_table[gsi].ioapic_id = ioapic_id; - gsi_table[gsi].addr = addr; + gsi_table_data[gsi].ioapic_id = ioapic_id; + gsi_table_data[gsi].addr = addr; if (gsi < NR_LEGACY_IRQ) { - gsi_table[gsi].pin = + gsi_table_data[gsi].pin = legacy_irq_to_pin[gsi] & 0xffU; } else { - gsi_table[gsi].pin = pin; + gsi_table_data[gsi].pin = pin; } /* pinned irq before use it */ @@ -382,8 +418,8 @@ void setup_ioapic_irqs(void) } /* system max gsi numbers */ - nr_gsi = gsi; - ASSERT(nr_gsi <= NR_MAX_GSI, "GSI table overflow"); + ioapic_nr_gsi = gsi; + ASSERT(ioapic_nr_gsi <= NR_MAX_GSI, "GSI table overflow"); } void suspend_ioapic(void) diff --git a/hypervisor/arch/x86/irq.c b/hypervisor/arch/x86/irq.c index 89ac62746..78bf41e05 100644 --- a/hypervisor/arch/x86/irq.c +++ b/hypervisor/arch/x86/irq.c @@ -6,6 +6,7 @@ #include #include +#include static spinlock_t exception_spinlock = { .head = 0U, .tail = 0U, }; static spinlock_t irq_alloc_spinlock = { .head = 0U, .tail = 0U, }; @@ -69,7 +70,7 @@ static void free_irq_num(uint32_t irq) uint64_t rflags; if (irq < NR_IRQS) { - if (!irq_is_gsi(irq)) { + if (!ioapic_irq_is_gsi(irq)) { spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags); (void)bitmap_test_and_clear_nolock((uint16_t)(irq & 0x3FU), irq_alloc_bitmap + (irq >> 6U)); @@ -288,7 +289,7 @@ static inline bool irq_need_mask(const struct irq_desc *desc) { /* level triggered gsi should be masked */ return (((desc->flags & IRQF_LEVEL) != 0U) - && irq_is_gsi(desc->irq)); + && ioapic_irq_is_gsi(desc->irq)); } static inline bool irq_need_unmask(const struct irq_desc *desc) @@ -296,7 +297,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) - && irq_is_gsi(desc->irq)); + && ioapic_irq_is_gsi(desc->irq)); } static inline void handle_irq(const struct irq_desc *desc) @@ -304,7 +305,7 @@ static inline void handle_irq(const struct irq_desc *desc) irq_action_t action = desc->action; if (irq_need_mask(desc)) { - gsi_mask_irq(desc->irq); + ioapic_gsi_mask_irq(desc->irq); } /* Send EOI to LAPIC/IOAPIC IRR */ @@ -315,7 +316,7 @@ static inline void handle_irq(const struct irq_desc *desc) } if (irq_need_unmask(desc)) { - gsi_unmask_irq(desc->irq); + ioapic_gsi_unmask_irq(desc->irq); } } @@ -429,7 +430,7 @@ void init_default_irqs(uint16_t cpu_id) /* we use ioapic only, disable legacy PIC */ disable_pic_irqs(); - setup_ioapic_irqs(); + ioapic_setup_irqs(); init_softirq(); } } diff --git a/hypervisor/arch/x86/pm.c b/hypervisor/arch/x86/pm.c index c62d1edbf..775b03ed1 100644 --- a/hypervisor/arch/x86/pm.c +++ b/hypervisor/arch/x86/pm.c @@ -4,6 +4,7 @@ */ #include #include +#include struct cpu_context cpu_ctx; diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c index 9d9dccce4..4707667a2 100644 --- a/hypervisor/debug/shell.c +++ b/hypervisor/debug/shell.c @@ -5,6 +5,7 @@ */ #include +#include #include "shell_priv.h" #define TEMP_STR_SIZE 60U @@ -1120,6 +1121,7 @@ static int32_t get_ioapic_info(char *str_arg, size_t str_max_len) char *str = str_arg; uint32_t irq; size_t len, size = str_max_len; + uint32_t ioapic_nr_gsi = 0U; len = snprintf(str, size, "\r\nIRQ\tPIN\tRTE.HI32\tRTE.LO32\tVEC\tDST\tDM\tTM\tDELM\tIRR\tMASK"); if (len >= size) { @@ -1128,14 +1130,20 @@ static int32_t get_ioapic_info(char *str_arg, size_t str_max_len) size -= len; str += len; - for (irq = 0U; irq < nr_gsi; irq++) { - void *addr = gsi_table[irq].addr; - uint8_t pin = gsi_table[irq].pin; + ioapic_nr_gsi = ioapic_get_nr_gsi (); + for (irq = 0U; irq < ioapic_nr_gsi; irq++) { + void *addr = ioapic_get_gsi_irq_addr (irq); + uint8_t pin = ioapic_irq_to_pin (irq); union ioapic_rte rte; bool irr, phys, level, mask; uint32_t delmode, vector, dest; + /* Add NULL check for addr, INVALID_PIN check for pin */ + if ((addr == NULL) || (!ioapic_is_pin_valid(pin))) { + goto overflow; + } + ioapic_get_rte_entry(addr, pin, &rte); get_rte_info(rte, &mask, &irr, &phys, &delmode, &level, &vector, &dest); diff --git a/hypervisor/debug/vuart.c b/hypervisor/debug/vuart.c index cd5c56fb3..c904d8b22 100644 --- a/hypervisor/debug/vuart.c +++ b/hypervisor/debug/vuart.c @@ -29,6 +29,7 @@ */ #include +#include #include "uart16550.h" diff --git a/hypervisor/include/arch/x86/hv_arch.h b/hypervisor/include/arch/x86/hv_arch.h index ff7f1b657..e385027e3 100644 --- a/hypervisor/include/arch/x86/hv_arch.h +++ b/hypervisor/include/arch/x86/hv_arch.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/hypervisor/include/arch/x86/ioapic.h b/hypervisor/include/arch/x86/ioapic.h index 630f5dcda..fa6c7e6d5 100644 --- a/hypervisor/include/arch/x86/ioapic.h +++ b/hypervisor/include/arch/x86/ioapic.h @@ -9,26 +9,19 @@ #include -/* - * IOAPIC_MAX_LINES is architecturally defined. - * The usable RTEs may be a subset of the total on a per IO APIC basis. - */ -#define IOAPIC_MAX_LINES 120U #define NR_LEGACY_IRQ 16U #define NR_LEGACY_PIN NR_LEGACY_IRQ -#define NR_MAX_GSI (NR_IOAPICS * IOAPIC_MAX_LINES) +void ioapic_setup_irqs(void); -void setup_ioapic_irqs(void); - -bool irq_is_gsi(uint32_t irq); -uint8_t irq_to_pin(uint32_t irq); +bool ioapic_irq_is_gsi(uint32_t irq); +uint8_t ioapic_irq_to_pin(uint32_t irq); /** * @brief Get irq num from pin num * * @param[in] pin The pin number */ -uint32_t pin_to_irq(uint8_t pin); +uint32_t ioapic_pin_to_irq(uint8_t pin); /** * @brief Set the redirection table entry @@ -55,8 +48,8 @@ void ioapic_get_rte(uint32_t irq, union ioapic_rte *rte); void suspend_ioapic(void); void resume_ioapic(void); -void gsi_mask_irq(uint32_t irq); -void gsi_unmask_irq(uint32_t irq); +void ioapic_gsi_mask_irq(uint32_t irq); +void ioapic_gsi_unmask_irq(uint32_t irq); void ioapic_get_rte_entry(void *ioapic_addr, uint8_t pin, union ioapic_rte *rte); @@ -66,8 +59,9 @@ struct gsi_table { void *addr; }; -extern struct gsi_table gsi_table[NR_MAX_GSI]; -extern uint32_t nr_gsi; -extern const uint8_t pic_ioapic_pin_map[NR_LEGACY_PIN]; +void *ioapic_get_gsi_irq_addr(uint32_t irq_num); +uint32_t ioapic_get_nr_gsi(void); +uint8_t get_pic_pin_from_ioapic_pin(uint8_t pin_index); +bool ioapic_is_pin_valid(uint8_t pin); #endif /* IOAPIC_H */