diff --git a/hypervisor/arch/x86/assign.c b/hypervisor/arch/x86/assign.c index f013a7243..8a4c181c3 100644 --- a/hypervisor/arch/x86/assign.c +++ b/hypervisor/arch/x86/assign.c @@ -21,6 +21,7 @@ ptirq_lookup_entry_by_sid(uint32_t intr_type, { uint16_t idx; struct ptirq_remapping_info *entry; + struct ptirq_remapping_info *entry_found = NULL; for (idx = 0U; idx < CONFIG_MAX_PT_IRQ_ENTRIES; idx++) { entry = &ptirq_entries[idx]; @@ -32,11 +33,11 @@ ptirq_lookup_entry_by_sid(uint32_t intr_type, (sid->value == entry->phys_sid.value) : ((vm == entry->vm) && (sid->value == entry->virt_sid.value)))) { - return entry; + entry_found = entry; + break; } } - - return NULL; + return entry_found; } static inline struct ptirq_remapping_info * @@ -214,20 +215,17 @@ static struct ptirq_remapping_info *add_msix_remapping(struct acrn_vm *vm, if (entry == NULL) { if (ptirq_lookup_entry_by_sid(PTDEV_INTR_MSI, &virt_sid, vm) != NULL) { pr_err("MSIX re-add vbdf%x", virt_bdf); - return NULL; - } - - entry = ptirq_alloc_entry(vm, PTDEV_INTR_MSI); - if (entry == NULL) { - return NULL; - } - entry->phys_sid.value = phys_sid.value; - entry->virt_sid.value = virt_sid.value; - - /* update msi source and active entry */ - if (ptirq_activate_entry(entry, IRQ_INVALID) < 0) { - ptirq_release_entry(entry); - entry = NULL; + } else { + entry = ptirq_alloc_entry(vm, PTDEV_INTR_MSI); + if (entry != NULL) { + entry->phys_sid.value = phys_sid.value; + entry->virt_sid.value = virt_sid.value; + /* update msi source and active entry */ + if (ptirq_activate_entry(entry, IRQ_INVALID) < 0) { + ptirq_release_entry(entry); + entry = NULL; + } + } } } else if (entry->vm != vm) { if (is_vm0(entry->vm)) { @@ -260,22 +258,20 @@ remove_msix_remapping(const struct acrn_vm *vm, uint16_t virt_bdf, uint32_t entr DEFINE_MSI_SID(virt_sid, virt_bdf, entry_nr); entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_MSI, &virt_sid, vm); - if (entry == NULL) { - return; + if (entry != NULL) { + if (is_entry_active(entry)) { + /*TODO: disable MSIX device when HV can in future */ + ptirq_deactivate_entry(entry); + } + + dev_dbg(ACRN_DBG_IRQ, + "VM%d MSIX remove vector mapping vbdf-pbdf:0x%x-0x%x idx=%d", + entry->vm->vm_id, virt_bdf, + entry->phys_sid.msi_id.bdf, entry_nr); + + ptirq_release_entry(entry); } - if (is_entry_active(entry)) { - /*TODO: disable MSIX device when HV can in future */ - ptirq_deactivate_entry(entry); - } - - dev_dbg(ACRN_DBG_IRQ, - "VM%d MSIX remove vector mapping vbdf-pbdf:0x%x-0x%x idx=%d", - entry->vm->vm_id, virt_bdf, - entry->phys_sid.msi_id.bdf, entry_nr); - - ptirq_release_entry(entry); - } /* add intx entry for a vm, based on intx id (phys_pin) @@ -286,63 +282,59 @@ remove_msix_remapping(const struct acrn_vm *vm, uint16_t virt_bdf, uint32_t entr static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint8_t virt_pin, uint8_t phys_pin, bool pic_pin) { - struct ptirq_remapping_info *entry; + struct ptirq_remapping_info *entry = NULL; enum ptirq_vpin_source 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); - if ((!pic_pin && virt_pin >= vioapic_pincount(vm)) - || (pic_pin && virt_pin >= vpic_pincount())) { + if ((!pic_pin && (virt_pin >= vioapic_pincount(vm))) || (pic_pin && (virt_pin >= vpic_pincount()))) { pr_err("ptirq_add_intx_remapping fails!\n"); - return NULL; - } - - if (!irq_is_gsi(phys_irq)) { + } else if (!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); - return NULL; - } - - entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &phys_sid, NULL); - if (entry == NULL) { - if (ptirq_lookup_entry_by_vpin(vm, virt_pin, pic_pin) != NULL) { - pr_err("INTX re-add vpin %d", virt_pin); - return NULL; - } - entry = ptirq_alloc_entry(vm, PTDEV_INTR_INTX); + } else { + entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &phys_sid, NULL); if (entry == NULL) { - return NULL; - } - entry->phys_sid.value = phys_sid.value; - entry->virt_sid.value = virt_sid.value; + if (ptirq_lookup_entry_by_vpin(vm, virt_pin, pic_pin) == NULL) { + entry = ptirq_alloc_entry(vm, PTDEV_INTR_INTX); + if (entry != NULL) { + entry->phys_sid.value = phys_sid.value; + entry->virt_sid.value = virt_sid.value; - /* activate entry */ - if (ptirq_activate_entry(entry, phys_irq) < 0) { - ptirq_release_entry(entry); - entry = NULL; - } - } else if (entry->vm != vm) { - if (is_vm0(entry->vm)) { - entry->vm = vm; - entry->virt_sid.value = virt_sid.value; + /* activate entry */ + if (ptirq_activate_entry(entry, phys_irq) < 0) { + ptirq_release_entry(entry); + entry = NULL; + } + } + } else { + pr_err("INTX re-add vpin %d", virt_pin); + } + } else if (entry->vm != vm) { + if (is_vm0(entry->vm)) { + entry->vm = vm; + entry->virt_sid.value = virt_sid.value; + } else { + pr_err("INTX pin%d already in vm%d with vpin%d, not able to add into vm%d with vpin%d", + phys_pin, entry->vm->vm_id, entry->virt_sid.intx_id.pin, vm->vm_id, virt_pin); + entry = NULL; + } } else { - pr_err("INTX pin%d already in vm%d with vpin%d, not able to add into vm%d with vpin%d", - phys_pin, entry->vm->vm_id, entry->virt_sid.intx_id.pin, vm->vm_id, virt_pin); - entry = NULL; + /* The mapping has already been added to the VM. No action + * required. */ } - } else { - /* The mapping has already been added to the VM. No action - * required. */ - } - if (pic_pin) { - vm->arch_vm.vpic.vpin_to_pt_entry[virt_pin] = entry; - } else { - vm->arch_vm.vioapic.vpin_to_pt_entry[virt_pin] = entry; + if (entry != NULL) { + if (pic_pin) { + vm->arch_vm.vpic.vpin_to_pt_entry[virt_pin] = entry; + } else { + vm->arch_vm.vioapic.vpin_to_pt_entry[virt_pin] = entry; + } + dev_dbg(ACRN_DBG_IRQ, "VM%d INTX add pin mapping vpin%d:ppin%d", + entry->vm->vm_id, virt_pin, phys_pin); + } } - dev_dbg(ACRN_DBG_IRQ, "VM%d INTX add pin mapping vpin%d:ppin%d", entry->vm->vm_id, virt_pin, phys_pin); - return entry; } @@ -352,37 +344,34 @@ static void remove_intx_remapping(struct acrn_vm *vm, uint8_t virt_pin, bool pic uint32_t phys_irq; struct ptirq_remapping_info *entry; - if ((!pic_pin && virt_pin >= vioapic_pincount(vm)) - || (pic_pin && virt_pin >= vpic_pincount())) { + if ((!pic_pin && (virt_pin >= vioapic_pincount(vm))) || (pic_pin && (virt_pin >= vpic_pincount()))) { pr_err("virtual irq pin is invalid!\n"); - return; - } - - entry = ptirq_lookup_entry_by_vpin(vm, virt_pin, pic_pin); - if (entry == NULL) { - return; - } - if (is_entry_active(entry)) { - phys_irq = entry->allocated_pirq; - /* disable interrupt */ - gsi_mask_irq(phys_irq); - - ptirq_deactivate_entry(entry); - dev_dbg(ACRN_DBG_IRQ, - "deactive %s intx entry:ppin=%d, pirq=%d ", - pic_pin ? "vPIC" : "vIOAPIC", - entry->phys_sid.intx_id.pin, phys_irq); - dev_dbg(ACRN_DBG_IRQ, "from vm%d vpin=%d\n", - entry->vm->vm_id, virt_pin); - } - - if (pic_pin) { - vm->arch_vm.vpic.vpin_to_pt_entry[virt_pin] = NULL; } else { - vm->arch_vm.vioapic.vpin_to_pt_entry[virt_pin] = NULL; - } + entry = ptirq_lookup_entry_by_vpin(vm, virt_pin, pic_pin); + if (entry != NULL) { + if (is_entry_active(entry)) { + phys_irq = entry->allocated_pirq; + /* disable interrupt */ + gsi_mask_irq(phys_irq); - ptirq_release_entry(entry); + ptirq_deactivate_entry(entry); + dev_dbg(ACRN_DBG_IRQ, + "deactive %s intx entry:ppin=%d, pirq=%d ", + pic_pin ? "vPIC" : "vIOAPIC", + entry->phys_sid.intx_id.pin, phys_irq); + dev_dbg(ACRN_DBG_IRQ, "from vm%d vpin=%d\n", + entry->vm->vm_id, virt_pin); + } + + if (pic_pin) { + vm->arch_vm.vpic.vpin_to_pt_entry[virt_pin] = NULL; + } else { + vm->arch_vm.vioapic.vpin_to_pt_entry[virt_pin] = NULL; + } + + ptirq_release_entry(entry); + } + } } static void ptirq_handle_intx(struct acrn_vm *vm, @@ -536,6 +525,7 @@ int32_t ptirq_msix_remap(struct acrn_vm *vm, uint16_t virt_bdf, { struct ptirq_remapping_info *entry; DEFINE_MSI_SID(virt_sid, virt_bdf, entry_nr); + int32_t ret = -ENODEV; /* * Device Model should pre-hold the mapping entries by calling @@ -549,12 +539,9 @@ int32_t ptirq_msix_remap(struct acrn_vm *vm, uint16_t virt_bdf, if (entry == NULL) { /* VM0 we add mapping dynamically */ if (is_vm0(vm)) { - entry = add_msix_remapping(vm, - virt_bdf, virt_bdf, entry_nr); + entry = add_msix_remapping(vm, virt_bdf, virt_bdf, entry_nr); if (entry == NULL) { pr_err("dev-assign: msi entry exist in others"); - spinlock_release(&ptdev_lock); - return -ENODEV; } } else { /* ptirq_msix_remap is called by SOS on demand, if @@ -562,28 +549,26 @@ int32_t ptirq_msix_remap(struct acrn_vm *vm, uint16_t virt_bdf, * the caller. */ pr_err("dev-assign: msi entry not exist"); - spinlock_release(&ptdev_lock); - return -ENODEV; } } - spinlock_release(&ptdev_lock); - /* handle destroy case */ - if (is_entry_active(entry) && (info->vmsi_data == 0U)) { - info->pmsi_data = 0U; - goto END; + if (entry != NULL) { + if (is_entry_active(entry) && (info->vmsi_data == 0U)) { + /* handle destroy case */ + info->pmsi_data = 0U; + } else { + /* build physical config MSI, update to info->pmsi_xxx */ + ptirq_build_physical_msi(vm, info, irq_to_vector(entry->allocated_pirq)); + entry->msi = *info; + dev_dbg(ACRN_DBG_IRQ, "PCI %x:%x.%x MSI VR[%d] 0x%x->0x%x assigned to vm%d", + pci_bus(virt_bdf), pci_slot(virt_bdf), pci_func(virt_bdf), entry_nr, + info->vmsi_data & 0xFFU, irq_to_vector(entry->allocated_pirq), entry->vm->vm_id); + } + ret = 0; } - /* build physical config MSI, update to info->pmsi_xxx */ - ptirq_build_physical_msi(vm, info, irq_to_vector(entry->allocated_pirq)); - entry->msi = *info; - - dev_dbg(ACRN_DBG_IRQ, "PCI %x:%x.%x MSI VR[%d] 0x%x->0x%x assigned to vm%d", - pci_bus(virt_bdf), pci_slot(virt_bdf), pci_func(virt_bdf), entry_nr, - info->vmsi_data & 0xFFU, irq_to_vector(entry->allocated_pirq), entry->vm->vm_id); -END: - return 0; + return ret; } static void activate_physical_ioapic(struct acrn_vm *vm, @@ -758,17 +743,19 @@ int32_t ptirq_add_msix_remapping(struct acrn_vm *vm, uint16_t virt_bdf, { struct ptirq_remapping_info *entry; uint32_t i; + uint32_t vector_added = 0U; for (i = 0U; i < vector_count; i++) { spinlock_obtain(&ptdev_lock); entry = add_msix_remapping(vm, virt_bdf, phys_bdf, i); spinlock_release(&ptdev_lock); if (entry == NULL) { - return -ENODEV; + break; } + vector_added++; } - return 0; + return (vector_added == vector_count) ? 0 : -ENODEV; } /*