From fe5a108c7b7d5d38a497f3a413b83674002e9c46 Mon Sep 17 00:00:00 2001 From: Sainath Grandhi Date: Sun, 16 Feb 2020 19:22:26 -0800 Subject: [PATCH] hv: vioapic init for SOS VM on platforms with multiple IO-APICs For SOS VM, when the target platform has multiple IO-APICs, there should be equal number of virtual IO-APICs. This patch adds support for emulating multiple vIOAPICs per VM. Tracked-On: #4151 Signed-off-by: Sainath Grandhi Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/vlapic.c | 11 +- hypervisor/arch/x86/guest/vm.c | 2 +- hypervisor/arch/x86/ioapic.c | 11 ++ hypervisor/common/hypercall.c | 16 +- hypervisor/debug/shell.c | 9 +- hypervisor/dm/vioapic.c | 197 ++++++++++++++++++------- hypervisor/include/arch/x86/guest/vm.h | 2 +- hypervisor/include/arch/x86/ioapic.h | 3 + hypervisor/include/dm/vioapic.h | 28 +++- 9 files changed, 206 insertions(+), 73 deletions(-) diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 00f049888..a3d997a90 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -898,8 +898,13 @@ vlapic_process_eoi(struct acrn_vlapic *vlapic) vlapic_update_ppr(vlapic); if (bitmap32_test((uint16_t)bitpos, &tmrptr[i].v)) { - /* hook to vIOAPIC */ - vioapic_process_eoi(vlapic->vm, vector); + /* + * Per Intel SDM 10.8.5, Software can inhibit the broadcast of + * EOI by setting bit 12 of the Spurious Interrupt Vector + * Register of the LAPIC. + * TODO: Check if the bit 12 "Suppress EOI Broadcasts" is set. + */ + vioapic_broadcast_eoi(vlapic->vm, vector); } vcpu_make_request(vlapic->vcpu, ACRN_REQUEST_EVENT); @@ -2513,7 +2518,7 @@ int32_t veoi_vmexit_handler(struct acrn_vcpu *vcpu) if (bitmap32_test((uint16_t)(vector & 0x1fU), &tmrptr[idx].v)) { /* hook to vIOAPIC */ - vioapic_process_eoi(vlapic->vm, vector); + vioapic_broadcast_eoi(vlapic->vm, vector); } TRACE_2L(TRACE_VMEXIT_APICV_VIRT_EOI, vector, 0UL); diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index f8a309bb3..2f43b8b04 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -659,7 +659,7 @@ int32_t reset_vm(struct acrn_vm *vm) } reset_vm_ioreqs(vm); - vioapic_reset(vm); + reset_vioapics(vm); destroy_secure_world(vm, false); vm->sworld_control.flag.active = 0UL; vm->state = VM_CREATED; diff --git a/hypervisor/arch/x86/ioapic.c b/hypervisor/arch/x86/ioapic.c index f8cbd59ab..3a70e252f 100644 --- a/hypervisor/arch/x86/ioapic.c +++ b/hypervisor/arch/x86/ioapic.c @@ -73,6 +73,17 @@ uint32_t get_pic_pin_from_ioapic_pin(uint32_t pin_index) return pin_id; } +uint8_t get_platform_ioapic_info (struct ioapic_info **plat_ioapic_info) +{ + *plat_ioapic_info = ioapic_array; + return ioapic_num; +} + +uint8_t get_gsi_to_ioapic_index(uint32_t gsi) +{ + return gsi_table_data[gsi].ioapic_info.index; +} + /* * @pre gsi < NR_MAX_GSI */ diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 8561087d6..bcca75a06 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -353,7 +353,7 @@ int32_t hcall_set_irqline(const struct acrn_vm *vm, uint16_t vmid, int32_t ret = -1; if (!is_poweroff_vm(target_vm) && is_postlaunched_vm(target_vm)) { - if (ops->gsi < vioapic_pincount(vm)) { + if (ops->gsi < get_vm_gsicount(vm)) { if (ops->gsi < vpic_pincount()) { /* * IRQ line for 8254 timer is connected to @@ -905,8 +905,13 @@ int32_t hcall_set_ptdev_intr_info(struct acrn_vm *vm, uint16_t vmid, uint64_t pa spinlock_obtain(&vpci->lock); vdev = pci_find_vdev(vpci, bdf); spinlock_release(&vpci->lock); + /* + * TODO: Change the hc_ptdev_irq structure member names + * virt_pin to virt_gsi + * phys_pin to phys_gsi + */ 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 < get_vm_gsicount(target_vm))) || ((irq.intx.pic_pin) && (irq.intx.virt_pin < vpic_pincount()))) && is_gsi_valid(irq.intx.phys_pin)) { ret = ptirq_add_intx_remapping(target_vm, irq.intx.virt_pin, @@ -954,8 +959,13 @@ hcall_reset_ptdev_intr_info(struct acrn_vm *vm, uint16_t vmid, uint64_t param) spinlock_obtain(&vpci->lock); vdev = pci_find_vdev(vpci, bdf); spinlock_release(&vpci->lock); + /* + * TODO: Change the hc_ptdev_irq structure member names + * virt_pin to virt_gsi + * phys_pin to phys_gsi + */ 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 < get_vm_gsicount(target_vm))) || ((irq.intx.pic_pin) && (irq.intx.virt_pin < vpic_pincount()))) { ptirq_remove_intx_remapping(target_vm, irq.intx.virt_pin, irq.intx.pic_pin); ret = 0; diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c index b6055ec63..ae649eeb3 100644 --- a/hypervisor/debug/shell.c +++ b/hypervisor/debug/shell.c @@ -1173,7 +1173,7 @@ static void get_vioapic_info(char *str_arg, size_t str_max, uint16_t vmid) uint32_t delmode, vector, dest; bool level, phys, remote_irr, mask; struct acrn_vm *vm = get_vm_from_vmid(vmid); - uint32_t gsi, pincount; + uint32_t gsi, gsi_count; if (is_poweroff_vm(vm)) { len = snprintf(str, size, "\r\nvm is not exist for vmid %hu", vmid); @@ -1192,9 +1192,12 @@ static void get_vioapic_info(char *str_arg, size_t str_max, uint16_t vmid) size -= len; str += len; - pincount = vioapic_pincount(vm); + gsi_count = get_vm_gsicount(vm); rte.full = 0UL; - for (gsi = 0U; gsi < pincount; gsi++) { + for (gsi = 0U; gsi < gsi_count; gsi++) { + if (is_sos_vm(vm) && (!is_gsi_valid(gsi))) { + continue; + } vioapic_get_rte(vm, gsi, &rte); mask = (rte.bits.intr_mask == IOAPIC_RTE_MASK_SET); remote_irr = (rte.bits.remote_irr == IOAPIC_RTE_REM_IRR); diff --git a/hypervisor/dm/vioapic.c b/hypervisor/dm/vioapic.c index d8ef3019c..ea54e0cab 100644 --- a/hypervisor/dm/vioapic.c +++ b/hypervisor/dm/vioapic.c @@ -36,6 +36,7 @@ #include #include #include +#include #define RTBL_RO_BITS ((uint32_t)0x00004000U | (uint32_t)0x00001000U) /*Remote IRR and Delivery Status bits*/ @@ -45,16 +46,16 @@ #define IOAPIC_ID_MASK 0x0f000000U #define MASK_ALL_INTERRUPTS 0x0001000000010000UL -static inline struct acrn_vioapic *vm_ioapic(const struct acrn_vm *vm) +static inline struct acrn_vioapics *vm_ioapics(const struct acrn_vm *vm) { - return (struct acrn_vioapic *)&(vm->arch_vm.vioapic); + return (struct acrn_vioapics *)&(vm->arch_vm.vioapics); } /** - * @pre pin < vioapic_pincount(vm) + * @pre pin < vioapic->nr_pins */ static void -vioapic_generate_intr(struct acrn_vioapic *vioapic, uint32_t pin) +vioapic_generate_intr(struct acrn_single_vioapic *vioapic, uint32_t pin) { uint32_t vector, dest, delmode; union ioapic_rte rte; @@ -84,10 +85,10 @@ vioapic_generate_intr(struct acrn_vioapic *vioapic, uint32_t pin) } /** - * @pre pin < vioapic_pincount(vm) + * @pre pin < vioapic->nr_pins */ static void -vioapic_set_pinstate(struct acrn_vioapic *vioapic, uint32_t pin, uint32_t level) +vioapic_set_pinstate(struct acrn_single_vioapic *vioapic, uint32_t pin, uint32_t level) { uint32_t old_lvl; union ioapic_rte rte; @@ -113,6 +114,30 @@ vioapic_set_pinstate(struct acrn_vioapic *vioapic, uint32_t pin, uint32_t level) } } + +static struct acrn_single_vioapic * +vgsi_to_vioapic_and_vpin(const struct acrn_vm *vm, uint32_t vgsi, uint32_t *vpin) +{ + struct acrn_single_vioapic *vioapic; + uint8_t vioapic_index = 0U; + + if (is_sos_vm(vm)) { + /* + * Utilize platform ioapic_info for SOS VM + */ + vioapic_index = get_gsi_to_ioapic_index(vgsi); + if (vpin != NULL) { + *vpin = gsi_to_ioapic_pin(vgsi); + } + } else { + if (vpin != NULL) { + *vpin = vgsi; + } + } + vioapic = (struct acrn_single_vioapic *)&(vm->arch_vm.vioapics.vioapic_array[vioapic_index]); + return vioapic; +} + /** * @brief Set vIOAPIC IRQ line status. * @@ -120,11 +145,11 @@ vioapic_set_pinstate(struct acrn_vioapic *vioapic, uint32_t pin, uint32_t level) * operation be done with ioapic lock. * * @param[in] vm Pointer to target VM - * @param[in] irqline Target IRQ number + * @param[in] vgsi Target GSI number * @param[in] operation Action options: GSI_SET_HIGH/GSI_SET_LOW/ * GSI_RAISING_PULSE/GSI_FALLING_PULSE * - * @pre irqline < vioapic_pincount(vm) + * @pre vgsi < get_vm_gsicount(vm) * @pre vm != NULL * @pre vioapic->ready == true * @return None @@ -132,10 +157,10 @@ vioapic_set_pinstate(struct acrn_vioapic *vioapic, uint32_t pin, uint32_t level) void vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t operation) { - struct acrn_vioapic *vioapic; - uint32_t pin = vgsi; + struct acrn_single_vioapic *vioapic; + uint32_t pin; - vioapic = vm_ioapic(vm); + vioapic = vgsi_to_vioapic_and_vpin(vm, vgsi, &pin); switch (operation) { case GSI_SET_HIGH: @@ -164,11 +189,11 @@ vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t ope * @brief Set vIOAPIC IRQ line status. * * @param[in] vm Pointer to target VM - * @param[in] irqline Target IRQ number + * @param[in] vgsi Target GSI number * @param[in] operation Action options: GSI_SET_HIGH/GSI_SET_LOW/ * GSI_RAISING_PULSE/GSI_FALLING_PULSE * - * @pre irqline < vioapic_pincount(vm) + * @pre vgsi < get_vm_gsicount(vm) * @pre vm != NULL * * @return None @@ -177,20 +202,21 @@ void vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t operation) { uint64_t rflags; - uint32_t irqline = vgsi; - struct acrn_vioapic *vioapic = vm_ioapic(vm); + struct acrn_single_vioapic *vioapic; + + vioapic = vgsi_to_vioapic_and_vpin(vm, vgsi, NULL); if (vioapic->ready) { spinlock_irqsave_obtain(&(vioapic->mtx), &rflags); - vioapic_set_irqline_nolock(vm, irqline, operation); + vioapic_set_irqline_nolock(vm, vgsi, operation); spinlock_irqrestore_release(&(vioapic->mtx), rflags); } } static uint32_t -vioapic_indirect_read(const struct acrn_vioapic *vioapic, uint32_t addr) +vioapic_indirect_read(const struct acrn_single_vioapic *vioapic, uint32_t addr) { uint32_t regnum, ret = 0U; - uint32_t pin, pincount = vioapic_pincount(vioapic->vm); + uint32_t pin, pincount = vioapic->nr_pins; regnum = addr & 0xffU; switch (regnum) { @@ -229,7 +255,7 @@ vioapic_indirect_read(const struct acrn_vioapic *vioapic, uint32_t addr) return ret; } -static inline bool vioapic_need_intr(const struct acrn_vioapic *vioapic, uint16_t pin) +static inline bool vioapic_need_intr(const struct acrn_single_vioapic *vioapic, uint16_t pin) { uint32_t lvl; union ioapic_rte rte; @@ -250,11 +276,11 @@ static inline bool vioapic_need_intr(const struct acrn_vioapic *vioapic, uint16_ * spinlock_irqsave_obtain(&(vioapic->mtx), &rflags) & spinlock_irqrestore_release(&(vioapic->mtx), rflags) * by caller. */ -static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr, uint32_t data) +static void vioapic_indirect_write(struct acrn_single_vioapic *vioapic, uint32_t addr, uint32_t data) { union ioapic_rte last, new, changed; uint32_t regnum; - uint32_t pin, pincount = vioapic_pincount(vioapic->vm); + uint32_t pin, pincount = vioapic->nr_pins; regnum = addr & 0xffUL; switch (regnum) { @@ -332,7 +358,8 @@ static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr, if ((new.bits.intr_mask == IOAPIC_RTE_MASK_CLR) || (last.bits.intr_mask == IOAPIC_RTE_MASK_CLR)) { /* VM enable intr */ /* NOTE: only support max 256 pin */ - (void)ptirq_intx_pin_remap(vioapic->vm, pin, INTX_CTLR_IOAPIC); + + (void)ptirq_intx_pin_remap(vioapic->vm, vioapic->gsi_base + pin, INTX_CTLR_IOAPIC); } /* @@ -352,7 +379,7 @@ static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr, } static void -vioapic_mmio_rw(struct acrn_vioapic *vioapic, uint64_t gpa, +vioapic_mmio_rw(struct acrn_single_vioapic *vioapic, uint64_t gpa, uint32_t *data, bool do_read) { uint32_t offset; @@ -396,11 +423,10 @@ vioapic_mmio_rw(struct acrn_vioapic *vioapic, uint64_t gpa, * @pre vm != NULL * @pre vioapic->ready == true */ -void -vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector) +static void +vioapic_process_eoi(struct acrn_single_vioapic *vioapic, uint32_t vector) { - struct acrn_vioapic *vioapic; - uint32_t pin, pincount = vioapic_pincount(vm); + uint32_t pin, pincount = vioapic->nr_pins; union ioapic_rte rte; uint64_t rflags; @@ -408,7 +434,6 @@ vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector) pr_err("vioapic_process_eoi: invalid vector %u", vector); } - vioapic = vm_ioapic(vm); dev_dbg(DBG_LEVEL_VIOAPIC, "ioapic processing eoi for vector %u", vector); /* notify device to ack if assigned pin */ @@ -419,7 +444,7 @@ vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector) continue; } - ptirq_intx_ack(vm, pin, INTX_CTLR_IOAPIC); + ptirq_intx_ack(vioapic->vm, vioapic->gsi_base + pin, INTX_CTLR_IOAPIC); } /* @@ -444,14 +469,28 @@ vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector) spinlock_irqrestore_release(&(vioapic->mtx), rflags); } -void -vioapic_reset(struct acrn_vm *vm) +void vioapic_broadcast_eoi(const struct acrn_vm *vm, uint32_t vector) +{ + struct acrn_single_vioapic *vioapic; + uint8_t vioapic_index; + + /* + * For platforms with multiple IO-APICs, EOI message from LAPIC is + * broadcast to all IO-APICs. Emulating the same behavior here. + */ + + for (vioapic_index = 0U; vioapic_index < vm->arch_vm.vioapics.ioapic_num; vioapic_index++) { + vioapic = &(vm_ioapics(vm)->vioapic_array[vioapic_index]); + vioapic_process_eoi(vioapic, vector); + } +} + +static void reset_one_vioapic(struct acrn_single_vioapic *vioapic) { uint32_t pin, pincount; - struct acrn_vioapic *vioapic = vm_ioapic(vm); /* Initialize all redirection entries to mask all interrupts */ - pincount = vioapic_pincount(vm); + pincount = vioapic->nr_pins; for (pin = 0U; pin < pincount; pin++) { vioapic->rtbl[pin].full = MASK_ALL_INTERRUPTS; } @@ -459,35 +498,80 @@ vioapic_reset(struct acrn_vm *vm) vioapic->ioregsel = 0U; } +void reset_vioapics(const struct acrn_vm *vm) +{ + struct acrn_vioapics *vioapics = vm_ioapics(vm); + uint8_t vioapic_index; + + for (vioapic_index = 0U; vioapic_index < vioapics->ioapic_num; vioapic_index++) { + reset_one_vioapic(&vioapics->vioapic_array[vioapic_index]); + } +} + void vioapic_init(struct acrn_vm *vm) { - vm->arch_vm.vioapic.vm = vm; - spinlock_init(&(vm->arch_vm.vioapic.mtx)); + struct ioapic_info *platform_ioapic_info; + uint8_t platform_ioapic_num; + uint8_t vioapic_index; + struct acrn_single_vioapic *vioapic; - vm->arch_vm.vioapic.base_addr = VIOAPIC_BASE; if (is_sos_vm(vm)) { - vm->arch_vm.vioapic.nr_pins = REDIR_ENTRIES_HW; + platform_ioapic_num = get_platform_ioapic_info(&platform_ioapic_info); + vm->arch_vm.vioapics.ioapic_num = platform_ioapic_num; + for (vioapic_index = 0U; vioapic_index < platform_ioapic_num; vioapic_index++) { + vioapic = &vm->arch_vm.vioapics.vioapic_array[vioapic_index]; + spinlock_init(&(vioapic->mtx)); + vioapic->nr_pins = platform_ioapic_info[vioapic_index].nr_pins; + vioapic->base_addr = platform_ioapic_info[vioapic_index].addr; + vioapic->gsi_base = platform_ioapic_info[vioapic_index].gsi_base; + + vioapic->vm = vm; + reset_one_vioapic(vioapic); + + register_mmio_emulation_handler(vm, + vioapic_mmio_access_handler, + (uint64_t)vioapic->base_addr, + (uint64_t)vioapic->base_addr + VIOAPIC_SIZE, + (void *)vioapic, false); + ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, + (uint64_t)vioapic->base_addr, VIOAPIC_SIZE); + vioapic->ready = true; + } + /* + * Maximum number of GSI is computed as GSI base of the IOAPIC i.e. enumerated last in ACPI MADT + * plus the number of interrupt pins of that IOAPIC. + */ + vm->arch_vm.vioapics.nr_gsi = platform_ioapic_info[platform_ioapic_num - 1U].gsi_base + + platform_ioapic_info[platform_ioapic_num - 1U].nr_pins; } else { - vm->arch_vm.vioapic.nr_pins = VIOAPIC_RTE_NUM; + vm->arch_vm.vioapics.ioapic_num = 1U; + vioapic = &vm->arch_vm.vioapics.vioapic_array[0U]; + spinlock_init(&(vioapic->mtx)); + vioapic->nr_pins = VIOAPIC_RTE_NUM; + vioapic->base_addr = VIOAPIC_BASE; + vioapic->gsi_base = 0U; + vioapic->vm = vm; + reset_one_vioapic(&vm->arch_vm.vioapics.vioapic_array[0U]); + + + register_mmio_emulation_handler(vm, + vioapic_mmio_access_handler, + (uint64_t)vioapic->base_addr, + (uint64_t)vioapic->base_addr + VIOAPIC_SIZE, + (void *)vioapic, false); + ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, + (uint64_t)vioapic->base_addr, VIOAPIC_SIZE); + vioapic->ready = true; + + vm->arch_vm.vioapics.nr_gsi = VIOAPIC_RTE_NUM; } - - vioapic_reset(vm); - - register_mmio_emulation_handler(vm, - vioapic_mmio_access_handler, - (uint64_t)vm->arch_vm.vioapic.base_addr, - (uint64_t)vm->arch_vm.vioapic.base_addr + VIOAPIC_SIZE, - (void *)&vm->arch_vm.vioapic, false); - ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, - (uint64_t)vm->arch_vm.vioapic.base_addr, VIOAPIC_SIZE); - vm->arch_vm.vioapic.ready = true; } uint32_t -vioapic_pincount(const struct acrn_vm *vm) +get_vm_gsicount(const struct acrn_vm *vm) { - return vm->arch_vm.vioapic.nr_pins; + return vm->arch_vm.vioapics.nr_gsi; } /* @@ -496,7 +580,7 @@ vioapic_pincount(const struct acrn_vm *vm) */ int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_private_data) { - struct acrn_vioapic *vioapic = (struct acrn_vioapic *)handler_private_data; + struct acrn_single_vioapic *vioapic = (struct acrn_single_vioapic *)handler_private_data; struct mmio_request *mmio = &io_req->reqs.mmio; uint64_t gpa = mmio->address; int32_t ret = 0; @@ -522,14 +606,15 @@ int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_pri } /** - * @pre vm->arch_vm.vioapic != NULL + * @pre vm->arch_vm.vioapics != NULL + * @pre vgsi < get_vm_gsicount(vm) * @pre rte != NULL */ void vioapic_get_rte(const struct acrn_vm *vm, uint32_t vgsi, union ioapic_rte *rte) { - struct acrn_vioapic *vioapic; - uint32_t pin = vgsi; + struct acrn_single_vioapic *vioapic; + uint32_t pin; + vioapic = vgsi_to_vioapic_and_vpin(vm, vgsi, &pin); - vioapic = vm_ioapic(vm); *rte = vioapic->rtbl[pin]; } diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index 2ddcd56b9..ee52ee2b2 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -107,7 +107,7 @@ struct vm_arch { void *sworld_eptp; struct memory_ops ept_mem_ops; - struct acrn_vioapic vioapic; /* Virtual IOAPIC base address */ + struct acrn_vioapics vioapics; /* Virtual IOAPIC/s */ struct acrn_vpic vpic; /* Virtual PIC */ #ifdef CONFIG_HYPERV_ENABLED struct acrn_hyperv hyperv; diff --git a/hypervisor/include/arch/x86/ioapic.h b/hypervisor/include/arch/x86/ioapic.h index a1a9c4f9e..a96ccaa70 100644 --- a/hypervisor/include/arch/x86/ioapic.h +++ b/hypervisor/include/arch/x86/ioapic.h @@ -26,6 +26,8 @@ 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); +uint8_t get_platform_ioapic_info (struct ioapic_info **plat_ioapic_info); + /** * @defgroup ioapic_ext_apis IOAPIC External Interfaces * @@ -108,6 +110,7 @@ struct gsi_table { void *gsi_to_ioapic_base(uint32_t gsi); uint32_t get_max_nr_gsi(void); +uint8_t get_gsi_to_ioapic_index(uint32_t gsi); uint32_t get_pic_pin_from_ioapic_pin(uint32_t pin_index); bool is_gsi_valid(uint32_t gsi); #endif /* IOAPIC_H */ diff --git a/hypervisor/include/dm/vioapic.h b/hypervisor/include/dm/vioapic.h index b0d2f2f3f..4de34eaf5 100644 --- a/hypervisor/include/dm/vioapic.h +++ b/hypervisor/include/dm/vioapic.h @@ -48,11 +48,16 @@ #define IOAPIC_RTE_LOW_INTVEC ((uint32_t)IOAPIC_RTE_INTVEC) -struct acrn_vioapic { - struct acrn_vm *vm; +/* + * id field is used to emulate the IOAPIC_ID register of vIOAPIC + */ + +struct acrn_single_vioapic { spinlock_t mtx; + struct acrn_vm *vm; uint32_t base_addr; uint32_t nr_pins; + uint32_t gsi_base; uint32_t id; bool ready; uint32_t ioregsel; @@ -61,8 +66,19 @@ struct acrn_vioapic { uint64_t pin_state[STATE_BITMAP_SIZE]; }; -void vioapic_init(struct acrn_vm *vm); -void vioapic_reset(struct acrn_vm *vm); +/* + * ioapic_num represents the number of IO-APICs emulated for the VM. + * nr_gsi represents the maximum number of GSI emulated for the VM. + */ +struct acrn_vioapics { + uint8_t ioapic_num; + uint32_t nr_gsi; + struct acrn_single_vioapic vioapic_array[CONFIG_MAX_IOAPIC_NUM]; +}; + +void dump_vioapic(struct acrn_vm *vm); +void vioapic_init(struct acrn_vm *vm); +void reset_vioapics(const struct acrn_vm *vm); /** @@ -102,8 +118,8 @@ void vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t */ void vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t operation); -uint32_t vioapic_pincount(const struct acrn_vm *vm); -void vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector); +uint32_t get_vm_gsicount(const struct acrn_vm *vm); +void vioapic_broadcast_eoi(const struct acrn_vm *vm, uint32_t vector); void vioapic_get_rte(const struct acrn_vm *vm, uint32_t vgsi, union ioapic_rte *rte); int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_private_data);