]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iommu/vt-d: Don't clobber posted vCPU IRTE when host IRQ affinity changes
authorSean Christopherson <seanjc@google.com>
Wed, 19 Mar 2025 02:21:00 +0000 (10:21 +0800)
committerJoerg Roedel <jroedel@suse.de>
Thu, 20 Mar 2025 08:03:56 +0000 (09:03 +0100)
Don't overwrite an IRTE that is posting IRQs to a vCPU with a posted MSI
entry if the host IRQ affinity happens to change.  If/when the IRTE is
reverted back to "host mode", it will be reconfigured as a posted MSI or
remapped entry as appropriate.

Drop the "mode" field, which doesn't differentiate between posted MSIs and
posted vCPUs, in favor of a dedicated posted_vcpu flag.  Note!  The two
posted_{msi,vcpu} flags are intentionally not mutually exclusive; an IRTE
can transition between posted MSI and posted vCPU.

Fixes: ed1e48ea4370 ("iommu/vt-d: Enable posted mode for device MSIs")
Cc: stable@vger.kernel.org
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/r/20250315025135.2365846-3-seanjc@google.com
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/intel/irq_remapping.c

index c495b533103f384f0746c4b7e5c9aadfbb9d43ae..ea3ca5203919625ee3c7ee0ca676bf7b4085b6d2 100644 (file)
 #include "../irq_remapping.h"
 #include "../iommu-pages.h"
 
-enum irq_mode {
-       IRQ_REMAPPING,
-       IRQ_POSTING,
-};
-
 struct ioapic_scope {
        struct intel_iommu *iommu;
        unsigned int id;
@@ -49,8 +44,8 @@ struct irq_2_iommu {
        u16 irte_index;
        u16 sub_handle;
        u8  irte_mask;
-       enum irq_mode mode;
        bool posted_msi;
+       bool posted_vcpu;
 };
 
 struct intel_ir_data {
@@ -138,7 +133,6 @@ static int alloc_irte(struct intel_iommu *iommu,
                irq_iommu->irte_index =  index;
                irq_iommu->sub_handle = 0;
                irq_iommu->irte_mask = mask;
-               irq_iommu->mode = IRQ_REMAPPING;
        }
        raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
@@ -193,8 +187,6 @@ static int modify_irte(struct irq_2_iommu *irq_iommu,
 
        rc = qi_flush_iec(iommu, index, 0);
 
-       /* Update iommu mode according to the IRTE mode */
-       irq_iommu->mode = irte->pst ? IRQ_POSTING : IRQ_REMAPPING;
        raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
        return rc;
@@ -1173,9 +1165,18 @@ static void __intel_ir_reconfigure_irte(struct irq_data *irqd, bool force_host)
 {
        struct intel_ir_data *ir_data = irqd->chip_data;
 
+       /*
+        * Don't modify IRTEs for IRQs that are being posted to vCPUs if the
+        * host CPU affinity changes.
+        */
+       if (ir_data->irq_2_iommu.posted_vcpu && !force_host)
+               return;
+
+       ir_data->irq_2_iommu.posted_vcpu = false;
+
        if (ir_data->irq_2_iommu.posted_msi)
                intel_ir_reconfigure_irte_posted(irqd);
-       else if (force_host || ir_data->irq_2_iommu.mode == IRQ_REMAPPING)
+       else
                modify_irte(&ir_data->irq_2_iommu, &ir_data->irte_entry);
 }
 
@@ -1270,6 +1271,7 @@ static int intel_ir_set_vcpu_affinity(struct irq_data *data, void *info)
                irte_pi.pda_h = (vcpu_pi_info->pi_desc_addr >> 32) &
                                ~(-1UL << PDA_HIGH_BIT);
 
+               ir_data->irq_2_iommu.posted_vcpu = true;
                modify_irte(&ir_data->irq_2_iommu, &irte_pi);
        }
 
@@ -1496,6 +1498,9 @@ static void intel_irq_remapping_deactivate(struct irq_domain *domain,
        struct intel_ir_data *data = irq_data->chip_data;
        struct irte entry;
 
+       WARN_ON_ONCE(data->irq_2_iommu.posted_vcpu);
+       data->irq_2_iommu.posted_vcpu = false;
+
        memset(&entry, 0, sizeof(entry));
        modify_irte(&data->irq_2_iommu, &entry);
 }