Implement irq_set_vcpu_affinity for intel_ir_chip.

Signed-off-by: Feng Wu <[email protected]>
Reviewed-by: Jiang Liu <[email protected]>
Acked-by: David Woodhouse <[email protected]>
---
 arch/x86/include/asm/irq_remapping.h |  5 +++++
 drivers/iommu/intel_irq_remapping.c  | 43 ++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/arch/x86/include/asm/irq_remapping.h 
b/arch/x86/include/asm/irq_remapping.h
index 0953723..202e040 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -57,6 +57,11 @@ static inline struct irq_domain 
*arch_get_ir_parent_domain(void)
        return x86_vector_domain;
 }
 
+struct vcpu_data {
+       u64 pi_desc_addr;       /* Physical address of PI Descriptor */
+       u32 vector;             /* Guest vector of the interrupt */
+};
+
 #else  /* CONFIG_IRQ_REMAP */
 
 static inline void set_irq_remapping_broken(void) { }
diff --git a/drivers/iommu/intel_irq_remapping.c 
b/drivers/iommu/intel_irq_remapping.c
index 8fad71c..9bbc235 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -1013,10 +1013,53 @@ static void intel_ir_compose_msi_msg(struct irq_data 
*irq_data,
        *msg = ir_data->msi_entry;
 }
 
+static int intel_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info)
+{
+       struct intel_ir_data *ir_data = data->chip_data;
+       struct irte irte_pi;
+       struct vcpu_data *vcpu_pi_info;
+
+       /* stop posting interrupts, back to remapping mode */
+       if (!vcpu_info) {
+               modify_irte(&ir_data->irq_2_iommu, &ir_data->irte_entry);
+       } else {
+               vcpu_pi_info = (struct vcpu_data *)vcpu_info;
+
+               /*
+                * "ir_data->irte_entry" saves the remapped format of IRTE,
+                * which being a cached irte is still updated when setting
+                * the affinity even when we are in posted mode. So this makes
+                * it possible to switch back to remapped mode from posted mode,
+                * we can just set "ir_data->irte_entry" to hardware for that
+                * purpose.
+                */
+               memcpy(&irte_pi, &ir_data->irte_entry, sizeof(struct irte));
+
+               irte_pi.p_urgent = 0;
+               irte_pi.p_vector = vcpu_pi_info->vector;
+               irte_pi.pda_l = (vcpu_pi_info->pi_desc_addr >>
+                               (32 - PDA_LOW_BIT)) & ~(-1UL << PDA_LOW_BIT);
+               irte_pi.pda_h = (vcpu_pi_info->pi_desc_addr >> 32) &
+                               ~(-1UL << PDA_HIGH_BIT);
+
+               irte_pi.p_res0 = 0;
+               irte_pi.p_res1 = 0;
+               irte_pi.p_res2 = 0;
+               irte_pi.p_res3 = 0;
+
+               irte_pi.p_pst = 1;
+
+               modify_irte(&ir_data->irq_2_iommu, &irte_pi);
+       }
+
+       return 0;
+}
+
 static struct irq_chip intel_ir_chip = {
        .irq_ack = ir_ack_apic_edge,
        .irq_set_affinity = intel_ir_set_affinity,
        .irq_compose_msi_msg = intel_ir_compose_msi_msg,
+       .irq_set_vcpu_affinity = intel_ir_set_vcpu_affinity,
 };
 
 static void intel_irq_remapping_prepare_irte(struct intel_ir_data *data,
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to