mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-07 16:07:03 +00:00
ptirq: Fix INTx assignment for Post-launched VM
When assigning a physical interrupt to a Post-launched VM, if it has been assigned to ServiceVM, we should remove that mapping first to reset ioapic pin state and rte, and build new mapping for the Post-launched VM. Tracked-On: #8370 Signed-off-by: Qiang Zhang <qiang4.zhang@linux.intel.com> Reviewed-by: Junjie Mao <junjie.mao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
bf9341844a
commit
fcb8e9bb2d
@ -382,15 +382,9 @@ static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint3
|
|||||||
pr_err("INTX re-add vpin %d", virt_gsi);
|
pr_err("INTX re-add vpin %d", virt_gsi);
|
||||||
}
|
}
|
||||||
} else if (entry->vm != vm) {
|
} else if (entry->vm != vm) {
|
||||||
if (is_service_vm(entry->vm)) {
|
pr_err("INTX gsi%d already in vm%d with vgsi%d, not able to add into vm%d with vgsi%d",
|
||||||
entry->vm = vm;
|
phys_gsi, entry->vm->vm_id, entry->virt_sid.intx_id.gsi, vm->vm_id, virt_gsi);
|
||||||
entry->virt_sid.value = virt_sid.value;
|
entry = NULL;
|
||||||
entry->polarity = 0U;
|
|
||||||
} else {
|
|
||||||
pr_err("INTX gsi%d already in vm%d with vgsi%d, not able to add into vm%d with vgsi%d",
|
|
||||||
phys_gsi, entry->vm->vm_id, entry->virt_sid.intx_id.gsi, vm->vm_id, virt_gsi);
|
|
||||||
entry = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* The mapping has already been added to the VM. No action
|
/* The mapping has already been added to the VM. No action
|
||||||
* required.
|
* required.
|
||||||
@ -410,15 +404,24 @@ static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint3
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deactive & remove mapping entry of vpin for vm */
|
/* deactivate & remove mapping entry of vpin for vm */
|
||||||
static void remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_gsi, enum intx_ctlr vgsi_ctlr)
|
static void remove_intx_remapping(const struct acrn_vm *vm, uint32_t gsi, enum intx_ctlr gsi_ctlr, bool is_phy_gsi)
|
||||||
{
|
{
|
||||||
uint32_t phys_irq;
|
uint32_t phys_irq;
|
||||||
struct ptirq_remapping_info *entry;
|
struct ptirq_remapping_info *entry;
|
||||||
struct intr_source intr_src;
|
struct intr_source intr_src;
|
||||||
DEFINE_INTX_SID(virt_sid, virt_gsi, vgsi_ctlr);
|
|
||||||
|
|
||||||
entry = find_ptirq_entry(PTDEV_INTR_INTX, &virt_sid, vm);
|
if (is_phy_gsi) {
|
||||||
|
DEFINE_INTX_SID(sid, gsi, INTX_CTLR_IOAPIC);
|
||||||
|
entry = find_ptirq_entry(PTDEV_INTR_INTX, &sid, NULL);
|
||||||
|
if ((entry != NULL) && (entry->vm != vm)) {
|
||||||
|
entry = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEFINE_INTX_SID(sid, gsi, gsi_ctlr);
|
||||||
|
entry = find_ptirq_entry(PTDEV_INTR_INTX, &sid, vm);
|
||||||
|
}
|
||||||
|
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
if (is_entry_active(entry)) {
|
if (is_entry_active(entry)) {
|
||||||
phys_irq = entry->allocated_pirq;
|
phys_irq = entry->allocated_pirq;
|
||||||
@ -431,11 +434,11 @@ static void remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_gsi, e
|
|||||||
|
|
||||||
dmar_free_irte(&intr_src, entry->irte_idx);
|
dmar_free_irte(&intr_src, entry->irte_idx);
|
||||||
dev_dbg(DBG_LEVEL_IRQ,
|
dev_dbg(DBG_LEVEL_IRQ,
|
||||||
"deactive %s intx entry:pgsi=%d, pirq=%d ",
|
"deactivate %s intx entry:pgsi=%d, pirq=%d ",
|
||||||
(vgsi_ctlr == INTX_CTLR_PIC) ? "vPIC" : "vIOAPIC",
|
(entry->virt_sid.intx_id.ctlr == INTX_CTLR_PIC) ? "vPIC" : "vIOAPIC",
|
||||||
entry->phys_sid.intx_id.gsi, phys_irq);
|
entry->phys_sid.intx_id.gsi, phys_irq);
|
||||||
dev_dbg(DBG_LEVEL_IRQ, "from vm%d vgsi=%d\n",
|
dev_dbg(DBG_LEVEL_IRQ, "from vm%d vgsi=%d\n",
|
||||||
entry->vm->vm_id, virt_gsi);
|
entry->vm->vm_id, entry->virt_sid.intx_id.gsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptirq_release_entry(entry);
|
ptirq_release_entry(entry);
|
||||||
@ -735,7 +738,7 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_gsi, enum intx_ct
|
|||||||
uint32_t phys_gsi = virt_gsi;
|
uint32_t phys_gsi = virt_gsi;
|
||||||
|
|
||||||
remove_intx_remapping(vm, alt_virt_sid.intx_id.gsi,
|
remove_intx_remapping(vm, alt_virt_sid.intx_id.gsi,
|
||||||
alt_virt_sid.intx_id.ctlr);
|
alt_virt_sid.intx_id.ctlr, false);
|
||||||
entry = add_intx_remapping(vm, virt_gsi, phys_gsi, vgsi_ctlr);
|
entry = add_intx_remapping(vm, virt_gsi, phys_gsi, vgsi_ctlr);
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
pr_err("%s, add intx remapping failed", __func__);
|
pr_err("%s, add intx remapping failed", __func__);
|
||||||
@ -806,12 +809,12 @@ int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_gsi, uint32_t
|
|||||||
/*
|
/*
|
||||||
* @pre vm != NULL
|
* @pre vm != NULL
|
||||||
*/
|
*/
|
||||||
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_gsi, bool pic_pin)
|
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t gsi, bool pic_pin, bool is_phy_gsi)
|
||||||
{
|
{
|
||||||
enum intx_ctlr vgsi_ctlr = pic_pin ? INTX_CTLR_PIC : INTX_CTLR_IOAPIC;
|
enum intx_ctlr vgsi_ctlr = pic_pin ? INTX_CTLR_PIC : INTX_CTLR_IOAPIC;
|
||||||
|
|
||||||
spinlock_obtain(&ptdev_lock);
|
spinlock_obtain(&ptdev_lock);
|
||||||
remove_intx_remapping(vm, virt_gsi, vgsi_ctlr);
|
remove_intx_remapping(vm, gsi, vgsi_ctlr, is_phy_gsi);
|
||||||
spinlock_release(&ptdev_lock);
|
spinlock_release(&ptdev_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -839,6 +842,6 @@ void ptirq_remove_configured_intx_remappings(const struct acrn_vm *vm)
|
|||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
for (i = 0; i < vm_config->pt_intx_num; i++) {
|
for (i = 0; i < vm_config->pt_intx_num; i++) {
|
||||||
ptirq_remove_intx_remapping(vm, vm_config->pt_intx[i].virt_gsi, false);
|
ptirq_remove_intx_remapping(vm, vm_config->pt_intx[i].virt_gsi, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1016,6 +1016,7 @@ int32_t hcall_set_ptdev_intr_info(struct acrn_vcpu *vcpu, struct acrn_vm *target
|
|||||||
if ((((!irq.intx.pic_pin) && (irq.intx.virt_pin < get_vm_gsicount(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())))
|
|| ((irq.intx.pic_pin) && (irq.intx.virt_pin < vpic_pincount())))
|
||||||
&& is_gsi_valid(irq.intx.phys_pin)) {
|
&& is_gsi_valid(irq.intx.phys_pin)) {
|
||||||
|
ptirq_remove_intx_remapping(get_service_vm(), irq.intx.phys_pin, false, true);
|
||||||
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 {
|
||||||
@ -1067,7 +1068,7 @@ int32_t hcall_reset_ptdev_intr_info(struct acrn_vcpu *vcpu, struct acrn_vm *targ
|
|||||||
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 < get_vm_gsicount(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()))) {
|
((irq.intx.pic_pin) && (irq.intx.virt_pin < vpic_pincount()))) {
|
||||||
ptirq_remove_intx_remapping(target_vm, irq.intx.virt_pin, irq.intx.pic_pin);
|
ptirq_remove_intx_remapping(target_vm, irq.intx.virt_pin, irq.intx.pic_pin, false);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
pr_err("%s: Invalid virt pin\n", __func__);
|
pr_err("%s: Invalid virt pin\n", __func__);
|
||||||
|
@ -112,18 +112,20 @@ int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_gsi, uint32_t
|
|||||||
/**
|
/**
|
||||||
* @brief Remove an interrupt remapping entry for INTx.
|
* @brief Remove an interrupt remapping entry for INTx.
|
||||||
*
|
*
|
||||||
* Deactivate & remove mapping entry of the given virt_pin for given vm.
|
* Deactivate & remove mapping entry of the given virt gsi for given vm or
|
||||||
|
* phys gsi assigned to this vm.
|
||||||
*
|
*
|
||||||
* @param[in] vm pointer to acrn_vm
|
* @param[in] vm pointer to acrn_vm
|
||||||
* @param[in] virt_gsi virtual pin number associated with the passthrough device
|
* @param[in] gsi virtual gsi number or physical gsi number associated with the passthrough device
|
||||||
* @param[in] pic_pin true for pic, false for ioapic
|
* @param[in] pic_pin true for pic, false for ioapic
|
||||||
|
* @param[in] is_phy_gsi true if gsi is physical, false if gsi is virtual
|
||||||
*
|
*
|
||||||
* @return None
|
* @return None
|
||||||
*
|
*
|
||||||
* @pre vm != NULL
|
* @pre vm != NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_gsi, bool pic_pin);
|
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t gsi, bool pic_pin, bool is_phy_gsi);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove interrupt remapping entry/entries for MSI/MSI-x.
|
* @brief Remove interrupt remapping entry/entries for MSI/MSI-x.
|
||||||
|
Loading…
Reference in New Issue
Block a user