From c2d350c5ccf7cc3599c994ec6715b5eb62547ef7 Mon Sep 17 00:00:00 2001 From: dongshen Date: Wed, 18 Mar 2020 16:29:00 -0700 Subject: [PATCH] hv: enable VT-d PI for ptdev if intr_src->pid_addr is non-zero Fill in posted interrupt fields (vector, pda, etc) and set mode to 1 to enable VT-d PI (posted mode) for this ptdev. If intr_src->pi_vcpu is 0, fall back to use the remapped mode. Tracked-On: #4506 Signed-off-by: dongshen Reviewed-by: Eddie Dong --- hypervisor/arch/x86/vtd.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/hypervisor/arch/x86/vtd.c b/hypervisor/arch/x86/vtd.c index 10ea0a013..bd3f6652b 100644 --- a/hypervisor/arch/x86/vtd.c +++ b/hypervisor/arch/x86/vtd.c @@ -1351,18 +1351,37 @@ int32_t dmar_assign_irte(const struct intr_source *intr_src, union dmar_ir_entry ret = -EINVAL; } else { dmar_enable_intr_remapping(dmar_unit); - irte->bits.remap.svt = 0x1UL; - irte->bits.remap.sq = 0x0UL; - irte->bits.remap.sid = sid.value; - irte->bits.remap.present = 0x1UL; - irte->bits.remap.mode = 0x0UL; - irte->bits.remap.trigger_mode = trigger_mode; - irte->bits.remap.fpd = 0x0UL; + ir_table = (union dmar_ir_entry *)hpa2hva(dmar_unit->ir_table_addr); ir_entry = ir_table + index; - ir_entry->value.hi_64 = irte->value.hi_64; - ir_entry->value.lo_64 = irte->value.lo_64; + if (intr_src->pid_paddr != 0UL) { + union dmar_ir_entry irte_pi; + + /* irte is in remapped mode format, convert to posted mode format */ + irte_pi.value.lo_64 = 0UL; + irte_pi.value.hi_64 = 0UL; + + irte_pi.bits.post.vector = irte->bits.remap.vector; + + irte_pi.bits.post.svt = 0x1UL; + irte_pi.bits.post.sid = sid.value; + irte_pi.bits.post.present = 0x1UL; + irte_pi.bits.post.mode = 0x1UL; + + irte_pi.bits.post.pda_l = (intr_src->pid_paddr) >> 6U; + irte_pi.bits.post.pda_h = (intr_src->pid_paddr) >> 32U; + + *ir_entry = irte_pi; + } else { + /* Fields that have not been initialized explicitly default to 0 */ + irte->bits.remap.svt = 0x1UL; + irte->bits.remap.sid = sid.value; + irte->bits.remap.present = 0x1UL; + irte->bits.remap.trigger_mode = trigger_mode; + + *ir_entry = *irte; + } iommu_flush_cache(ir_entry, sizeof(union dmar_ir_entry)); dmar_invalid_iec(dmar_unit, index, 0U, false); }