When GAPPI is enabled, a guest-mode IRTE with is_run clear delivers a GAPPI interrupt to the physical APIC ID in the IRTE destination fields, with the wake vector carried in ga_tag. Program the guest-activated IRTE accordingly. Reuse the POSTED_INTR_WAKEUP_VECTOR for gappi which is already reserved for posted interrupt wakeup handler on x86 and is handled by IDTE entry sysvec_kvm_posted_intr_wakeup_ipi. Intel VMX already uses same vector for the wakeup case. Signed-off-by: Sairaj Kodilkar --- arch/x86/kvm/svm/avic.c | 5 +++++ drivers/iommu/amd/amd_iommu.h | 1 + drivers/iommu/amd/amd_iommu_types.h | 4 +++- drivers/iommu/amd/init.c | 3 +++ drivers/iommu/amd/iommu.c | 21 +++++++++++++++++---- include/linux/amd-iommu.h | 1 + 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 7862b13c5409..b666efb5d91c 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -955,6 +955,11 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm, } else { posted_intr = !!(entry & AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR); pi_data.flags = posted_intr << AMD_IOMMU_FLAG_POSTED_INTR_SHIFT; + /* GAPPI is disabled at this point (amd_iommu_gappi is + * enabled in the following patches) hence keep the + * apicid as 0. + */ + pi_data.apicid = 0; } ret = irq_set_vcpu_affinity(host_irq, &pi_data); diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h index 834d8fabfba3..044179cab12e 100644 --- a/drivers/iommu/amd/amd_iommu.h +++ b/drivers/iommu/amd/amd_iommu.h @@ -41,6 +41,7 @@ int amd_iommu_enable(void); void amd_iommu_disable(void); int amd_iommu_reenable(int mode); int amd_iommu_enable_faulting(unsigned int cpu); +extern bool amd_iommu_gappi; extern int amd_iommu_guest_ir; extern enum protection_domain_mode amd_iommu_pgtable; extern int amd_iommu_gpt_level; diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index f9f718087893..26d7a9796e64 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -113,6 +113,7 @@ /* Extended Feature 2 Bits */ #define FEATURE_SEVSNPIO_SUP BIT_ULL(1) #define FEATURE_GCR3TRPMODE BIT_ULL(3) +#define FEATURE_GAPPIDISSUP BIT_ULL(4) #define FEATURE_SNPAVICSUP GENMASK_ULL(7, 5) #define FEATURE_SNPAVICSUP_GAM(x) \ (FIELD_GET(FEATURE_SNPAVICSUP, x) == 0x1) @@ -1004,7 +1005,8 @@ union irte_ga_lo { no_fault : 1, /* ------ */ ga_log_intr : 1, - rsvd1 : 3, + rsvd1 : 2, + gappi_dis : 1, is_run : 1, /* ------ */ guest_mode : 1, diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 3bdb380d23e9..2e1889f8a9e4 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -160,6 +160,9 @@ u8 amd_iommu_hpt_level; /* Guest page table level */ int amd_iommu_gpt_level = PAGE_MODE_4_LEVEL; +bool amd_iommu_gappi; +EXPORT_SYMBOL(amd_iommu_gappi); + int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC; static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE; diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 76f0e469490e..4690cecc9aa7 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -3969,9 +3969,18 @@ static void __amd_iommu_update_ga(struct irte_ga *entry, int apicid, int flags) entry->lo.fields_vapic.is_run = true; entry->lo.fields_vapic.ga_log_intr = false; } else { - entry->lo.fields_vapic.is_run = false; - entry->lo.fields_vapic.ga_log_intr = !!(flags & - AMD_IOMMU_FLAG_POSTED_INTR); + bool posted_intr = !!(flags & AMD_IOMMU_FLAG_POSTED_INTR); + if (amd_iommu_gappi) { + entry->lo.fields_vapic.gappi_dis = !posted_intr && + check_feature2(FEATURE_GAPPIDISSUP); + entry->lo.fields_vapic.is_run = false; + entry->lo.fields_vapic.destination = + APICID_TO_IRTE_DEST_LO(apicid); + entry->hi.fields.destination = APICID_TO_IRTE_DEST_HI(apicid); + } else { + entry->lo.fields_vapic.is_run = false; + entry->lo.fields_vapic.ga_log_intr = posted_intr; + } } } @@ -4034,7 +4043,11 @@ int amd_iommu_activate_guest_mode(void *data, int apicid, int flags) entry->lo.fields_vapic.guest_mode = 1; entry->hi.fields.ga_root_ptr = ir_data->ga_root_ptr; entry->hi.fields.vector = ir_data->ga_vector; - entry->lo.fields_vapic.ga_tag = ir_data->ga_tag; + + if (amd_iommu_gappi) + entry->lo.fields_vapic.ga_tag = POSTED_INTR_WAKEUP_VECTOR; + else + entry->lo.fields_vapic.ga_tag = ir_data->ga_tag; __amd_iommu_update_ga(entry, apicid, flags); diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h index 3dd9074e5967..87e76f617ea1 100644 --- a/include/linux/amd-iommu.h +++ b/include/linux/amd-iommu.h @@ -82,4 +82,5 @@ static inline bool amd_iommu_sev_tio_supported(void) { return false; } #define AMD_IOMMU_FLAG_POSTED_INTR_SHIFT 1 #define AMD_IOMMU_FLAG_POSTED_INTR BIT(1) +extern bool amd_iommu_gappi; #endif /* _ASM_X86_AMD_IOMMU_H */ -- 2.34.1