|
Joerg Roedel |
d89aa8 |
From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
|
|
Joerg Roedel |
d89aa8 |
Date: Wed, 27 Jun 2018 10:31:22 -0500
|
|
Joerg Roedel |
d89aa8 |
Subject: iommu/amd: Add support for IOMMU XT mode
|
|
Joerg Roedel |
d89aa8 |
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
|
|
Joerg Roedel |
d89aa8 |
Git-commit: 90fcffd9cf5e7cc593169f529799f3e3c5437e75
|
|
Joerg Roedel |
d89aa8 |
Patch-mainline: queued, upstream in v4.19-rc1
|
|
Joerg Roedel |
d89aa8 |
References: fate#324429
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
The AMD IOMMU XT mode enables interrupt remapping with 32-bit destination
|
|
Joerg Roedel |
d89aa8 |
APIC ID, which is required for x2APIC. The feature is available when
|
|
Joerg Roedel |
d89aa8 |
the XTSup bit is set in the IOMMU Extended Feature register
|
|
Joerg Roedel |
d89aa8 |
and/or the IVHD Type 10h IOMMU Feature Reporting field.
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
For more information, please see section "IOMMU x2APIC Support" of
|
|
Joerg Roedel |
d89aa8 |
the AMD I/O Virtualization Technology (IOMMU) Specification.
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
Cc: Joerg Roedel <jroedel@suse.de>
|
|
Joerg Roedel |
d89aa8 |
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
|
|
Joerg Roedel |
d89aa8 |
Signed-off-by: Joerg Roedel <jroedel@suse.de>
|
|
Joerg Roedel |
d89aa8 |
---
|
|
Joerg Roedel |
d89aa8 |
drivers/iommu/amd_iommu.c | 21 ++++++++++++++++-----
|
|
Joerg Roedel |
d89aa8 |
drivers/iommu/amd_iommu_init.c | 25 +++++++++++++++++++++++--
|
|
Joerg Roedel |
d89aa8 |
drivers/iommu/amd_iommu_types.h | 17 +++++++++++------
|
|
Joerg Roedel |
d89aa8 |
3 files changed, 50 insertions(+), 13 deletions(-)
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
--- a/drivers/iommu/amd_iommu.c
|
|
Joerg Roedel |
d89aa8 |
+++ b/drivers/iommu/amd_iommu.c
|
|
Joerg Roedel |
d89aa8 |
@@ -3809,7 +3809,8 @@ static void irte_ga_prepare(void *entry,
|
|
Joerg Roedel |
d89aa8 |
irte->lo.fields_remap.int_type = delivery_mode;
|
|
Joerg Roedel |
d89aa8 |
irte->lo.fields_remap.dm = dest_mode;
|
|
Joerg Roedel |
d89aa8 |
irte->hi.fields.vector = vector;
|
|
Joerg Roedel |
d89aa8 |
- irte->lo.fields_remap.destination = dest_apicid;
|
|
Joerg Roedel |
d89aa8 |
+ irte->lo.fields_remap.destination = APICID_TO_IRTE_DEST_LO(dest_apicid);
|
|
Joerg Roedel |
d89aa8 |
+ irte->hi.fields.destination = APICID_TO_IRTE_DEST_HI(dest_apicid);
|
|
Joerg Roedel |
d89aa8 |
irte->lo.fields_remap.valid = 1;
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
@@ -3864,7 +3865,10 @@ static void irte_ga_set_affinity(void *e
|
|
Joerg Roedel |
d89aa8 |
if (!dev_data || !dev_data->use_vapic ||
|
|
Joerg Roedel |
d89aa8 |
!irte->lo.fields_remap.guest_mode) {
|
|
Joerg Roedel |
d89aa8 |
irte->hi.fields.vector = vector;
|
|
Joerg Roedel |
d89aa8 |
- irte->lo.fields_remap.destination = dest_apicid;
|
|
Joerg Roedel |
d89aa8 |
+ irte->lo.fields_remap.destination =
|
|
Joerg Roedel |
d89aa8 |
+ APICID_TO_IRTE_DEST_LO(dest_apicid);
|
|
Joerg Roedel |
d89aa8 |
+ irte->hi.fields.destination =
|
|
Joerg Roedel |
d89aa8 |
+ APICID_TO_IRTE_DEST_HI(dest_apicid);
|
|
Joerg Roedel |
d89aa8 |
modify_irte_ga(devid, index, irte, NULL);
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
@@ -4255,7 +4259,10 @@ static int amd_ir_set_vcpu_affinity(stru
|
|
Joerg Roedel |
d89aa8 |
irte->lo.val = 0;
|
|
Joerg Roedel |
d89aa8 |
irte->hi.fields.vector = cfg->vector;
|
|
Joerg Roedel |
d89aa8 |
irte->lo.fields_remap.guest_mode = 0;
|
|
Joerg Roedel |
d89aa8 |
- irte->lo.fields_remap.destination = cfg->dest_apicid;
|
|
Joerg Roedel |
d89aa8 |
+ irte->lo.fields_remap.destination =
|
|
Joerg Roedel |
d89aa8 |
+ APICID_TO_IRTE_DEST_LO(cfg->dest_apicid);
|
|
Joerg Roedel |
d89aa8 |
+ irte->hi.fields.destination =
|
|
Joerg Roedel |
d89aa8 |
+ APICID_TO_IRTE_DEST_HI(cfg->dest_apicid);
|
|
Joerg Roedel |
d89aa8 |
irte->lo.fields_remap.int_type = apic->irq_delivery_mode;
|
|
Joerg Roedel |
d89aa8 |
irte->lo.fields_remap.dm = apic->irq_dest_mode;
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
@@ -4354,8 +4361,12 @@ int amd_iommu_update_ga(int cpu, bool is
|
|
Joerg Roedel |
d89aa8 |
spin_lock_irqsave(&irt->lock, flags);
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
if (ref->lo.fields_vapic.guest_mode) {
|
|
Joerg Roedel |
d89aa8 |
- if (cpu >= 0)
|
|
Joerg Roedel |
d89aa8 |
- ref->lo.fields_vapic.destination = cpu;
|
|
Joerg Roedel |
d89aa8 |
+ if (cpu >= 0) {
|
|
Joerg Roedel |
d89aa8 |
+ ref->lo.fields_vapic.destination =
|
|
Joerg Roedel |
d89aa8 |
+ APICID_TO_IRTE_DEST_LO(cpu);
|
|
Joerg Roedel |
d89aa8 |
+ ref->hi.fields.destination =
|
|
Joerg Roedel |
d89aa8 |
+ APICID_TO_IRTE_DEST_HI(cpu);
|
|
Joerg Roedel |
d89aa8 |
+ }
|
|
Joerg Roedel |
d89aa8 |
ref->lo.fields_vapic.is_run = is_run;
|
|
Joerg Roedel |
d89aa8 |
barrier();
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
--- a/drivers/iommu/amd_iommu_init.c
|
|
Joerg Roedel |
d89aa8 |
+++ b/drivers/iommu/amd_iommu_init.c
|
|
Joerg Roedel |
d89aa8 |
@@ -153,6 +153,7 @@ bool amd_iommu_dump;
|
|
Joerg Roedel |
d89aa8 |
bool amd_iommu_irq_remap __read_mostly;
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
|
|
Joerg Roedel |
d89aa8 |
+static int amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
static bool amd_iommu_detected;
|
|
Joerg Roedel |
d89aa8 |
static bool __initdata amd_iommu_disabled;
|
|
Joerg Roedel |
d89aa8 |
@@ -827,6 +828,19 @@ static int iommu_init_ga(struct amd_iomm
|
|
Joerg Roedel |
d89aa8 |
return ret;
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
+static void iommu_enable_xt(struct amd_iommu *iommu)
|
|
Joerg Roedel |
d89aa8 |
+{
|
|
Joerg Roedel |
d89aa8 |
+#ifdef CONFIG_IRQ_REMAP
|
|
Joerg Roedel |
d89aa8 |
+ /*
|
|
Joerg Roedel |
d89aa8 |
+ * XT mode (32-bit APIC destination ID) requires
|
|
Joerg Roedel |
d89aa8 |
+ * GA mode (128-bit IRTE support) as a prerequisite.
|
|
Joerg Roedel |
d89aa8 |
+ */
|
|
Joerg Roedel |
d89aa8 |
+ if (AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir) &&
|
|
Joerg Roedel |
d89aa8 |
+ amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
|
|
Joerg Roedel |
d89aa8 |
+ iommu_feature_enable(iommu, CONTROL_XT_EN);
|
|
Joerg Roedel |
d89aa8 |
+#endif /* CONFIG_IRQ_REMAP */
|
|
Joerg Roedel |
d89aa8 |
+}
|
|
Joerg Roedel |
d89aa8 |
+
|
|
Joerg Roedel |
d89aa8 |
static void iommu_enable_gt(struct amd_iommu *iommu)
|
|
Joerg Roedel |
d89aa8 |
{
|
|
Joerg Roedel |
d89aa8 |
if (!iommu_feature(iommu, FEATURE_GT))
|
|
Joerg Roedel |
d89aa8 |
@@ -1507,6 +1521,8 @@ static int __init init_iommu_one(struct
|
|
Joerg Roedel |
d89aa8 |
iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
|
|
Joerg Roedel |
d89aa8 |
if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
|
|
Joerg Roedel |
d89aa8 |
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
|
|
Joerg Roedel |
d89aa8 |
+ if (((h->efr_attr & (0x1 << IOMMU_FEAT_XTSUP_SHIFT)) == 0))
|
|
Joerg Roedel |
d89aa8 |
+ amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
|
|
Joerg Roedel |
d89aa8 |
break;
|
|
Joerg Roedel |
d89aa8 |
case 0x11:
|
|
Joerg Roedel |
d89aa8 |
case 0x40:
|
|
Joerg Roedel |
d89aa8 |
@@ -1516,6 +1532,8 @@ static int __init init_iommu_one(struct
|
|
Joerg Roedel |
d89aa8 |
iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
|
|
Joerg Roedel |
d89aa8 |
if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0))
|
|
Joerg Roedel |
d89aa8 |
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
|
|
Joerg Roedel |
d89aa8 |
+ if (((h->efr_reg & (0x1 << IOMMU_EFR_XTSUP_SHIFT)) == 0))
|
|
Joerg Roedel |
d89aa8 |
+ amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
|
|
Joerg Roedel |
d89aa8 |
break;
|
|
Joerg Roedel |
d89aa8 |
default:
|
|
Joerg Roedel |
d89aa8 |
return -EINVAL;
|
|
Joerg Roedel |
d89aa8 |
@@ -1831,6 +1849,8 @@ static void print_iommu_info(void)
|
|
Joerg Roedel |
d89aa8 |
pr_info("AMD-Vi: Interrupt remapping enabled\n");
|
|
Joerg Roedel |
d89aa8 |
if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
|
|
Joerg Roedel |
d89aa8 |
pr_info("AMD-Vi: virtual APIC enabled\n");
|
|
Joerg Roedel |
d89aa8 |
+ if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
|
|
Joerg Roedel |
d89aa8 |
+ pr_info("AMD-Vi: X2APIC enabled\n");
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
@@ -2167,6 +2187,7 @@ static void early_enable_iommu(struct am
|
|
Joerg Roedel |
d89aa8 |
iommu_enable_event_buffer(iommu);
|
|
Joerg Roedel |
d89aa8 |
iommu_set_exclusion_range(iommu);
|
|
Joerg Roedel |
d89aa8 |
iommu_enable_ga(iommu);
|
|
Joerg Roedel |
d89aa8 |
+ iommu_enable_xt(iommu);
|
|
Joerg Roedel |
d89aa8 |
iommu_enable(iommu);
|
|
Joerg Roedel |
d89aa8 |
iommu_flush_all_caches(iommu);
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
@@ -2211,6 +2232,7 @@ static void early_enable_iommus(void)
|
|
Joerg Roedel |
d89aa8 |
iommu_enable_command_buffer(iommu);
|
|
Joerg Roedel |
d89aa8 |
iommu_enable_event_buffer(iommu);
|
|
Joerg Roedel |
d89aa8 |
iommu_enable_ga(iommu);
|
|
Joerg Roedel |
d89aa8 |
+ iommu_enable_xt(iommu);
|
|
Joerg Roedel |
d89aa8 |
iommu_set_device_table(iommu);
|
|
Joerg Roedel |
d89aa8 |
iommu_flush_all_caches(iommu);
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
@@ -2690,8 +2712,7 @@ int __init amd_iommu_enable(void)
|
|
Joerg Roedel |
d89aa8 |
return ret;
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
irq_remapping_enabled = 1;
|
|
Joerg Roedel |
d89aa8 |
-
|
|
Joerg Roedel |
d89aa8 |
- return 0;
|
|
Joerg Roedel |
d89aa8 |
+ return amd_iommu_xt_mode;
|
|
Joerg Roedel |
d89aa8 |
}
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
void amd_iommu_disable(void)
|
|
Joerg Roedel |
d89aa8 |
--- a/drivers/iommu/amd_iommu_types.h
|
|
Joerg Roedel |
d89aa8 |
+++ b/drivers/iommu/amd_iommu_types.h
|
|
Joerg Roedel |
d89aa8 |
@@ -159,6 +159,7 @@
|
|
Joerg Roedel |
d89aa8 |
#define CONTROL_GAM_EN 0x19ULL
|
|
Joerg Roedel |
d89aa8 |
#define CONTROL_GALOG_EN 0x1CULL
|
|
Joerg Roedel |
d89aa8 |
#define CONTROL_GAINT_EN 0x1DULL
|
|
Joerg Roedel |
d89aa8 |
+#define CONTROL_XT_EN 0x32ULL
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT)
|
|
Joerg Roedel |
d89aa8 |
#define CTRL_INV_TO_NONE 0
|
|
Joerg Roedel |
d89aa8 |
@@ -375,9 +376,11 @@
|
|
Joerg Roedel |
d89aa8 |
#define IOMMU_CAP_EFR 27
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
/* IOMMU Feature Reporting Field (for IVHD type 10h */
|
|
Joerg Roedel |
d89aa8 |
+#define IOMMU_FEAT_XTSUP_SHIFT 0
|
|
Joerg Roedel |
d89aa8 |
#define IOMMU_FEAT_GASUP_SHIFT 6
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
/* IOMMU Extended Feature Register (EFR) */
|
|
Joerg Roedel |
d89aa8 |
+#define IOMMU_EFR_XTSUP_SHIFT 2
|
|
Joerg Roedel |
d89aa8 |
#define IOMMU_EFR_GASUP_SHIFT 7
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
#define MAX_DOMAIN_ID 65536
|
|
Joerg Roedel |
d89aa8 |
@@ -434,7 +437,6 @@ extern struct kmem_cache *amd_iommu_irq_
|
|
Joerg Roedel |
d89aa8 |
#define APERTURE_RANGE_INDEX(a) ((a) >> APERTURE_RANGE_SHIFT)
|
|
Joerg Roedel |
d89aa8 |
#define APERTURE_PAGE_INDEX(a) (((a) >> 21) & 0x3fULL)
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
-
|
|
Joerg Roedel |
d89aa8 |
/*
|
|
Joerg Roedel |
d89aa8 |
* This struct is used to pass information about
|
|
Joerg Roedel |
d89aa8 |
* incoming PPR faults around.
|
|
Joerg Roedel |
d89aa8 |
@@ -807,6 +809,9 @@ union irte {
|
|
Joerg Roedel |
d89aa8 |
} fields;
|
|
Joerg Roedel |
d89aa8 |
};
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
+#define APICID_TO_IRTE_DEST_LO(x) (x & 0xffffff)
|
|
Joerg Roedel |
d89aa8 |
+#define APICID_TO_IRTE_DEST_HI(x) ((x >> 24) & 0xff)
|
|
Joerg Roedel |
d89aa8 |
+
|
|
Joerg Roedel |
d89aa8 |
union irte_ga_lo {
|
|
Joerg Roedel |
d89aa8 |
u64 val;
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
@@ -820,8 +825,8 @@ union irte_ga_lo {
|
|
Joerg Roedel |
d89aa8 |
dm : 1,
|
|
Joerg Roedel |
d89aa8 |
/* ------ */
|
|
Joerg Roedel |
d89aa8 |
guest_mode : 1,
|
|
Joerg Roedel |
d89aa8 |
- destination : 8,
|
|
Joerg Roedel |
d89aa8 |
- rsvd : 48;
|
|
Joerg Roedel |
d89aa8 |
+ destination : 24,
|
|
Joerg Roedel |
d89aa8 |
+ ga_tag : 32;
|
|
Joerg Roedel |
d89aa8 |
} fields_remap;
|
|
Joerg Roedel |
d89aa8 |
|
|
Joerg Roedel |
d89aa8 |
/* For guest vAPIC */
|
|
Joerg Roedel |
d89aa8 |
@@ -834,8 +839,7 @@ union irte_ga_lo {
|
|
Joerg Roedel |
d89aa8 |
is_run : 1,
|
|
Joerg Roedel |
d89aa8 |
/* ------ */
|
|
Joerg Roedel |
d89aa8 |
guest_mode : 1,
|
|
Joerg Roedel |
d89aa8 |
- destination : 8,
|
|
Joerg Roedel |
d89aa8 |
- rsvd2 : 16,
|
|
Joerg Roedel |
d89aa8 |
+ destination : 24,
|
|
Joerg Roedel |
d89aa8 |
ga_tag : 32;
|
|
Joerg Roedel |
d89aa8 |
} fields_vapic;
|
|
Joerg Roedel |
d89aa8 |
};
|
|
Joerg Roedel |
d89aa8 |
@@ -846,7 +850,8 @@ union irte_ga_hi {
|
|
Joerg Roedel |
d89aa8 |
u64 vector : 8,
|
|
Joerg Roedel |
d89aa8 |
rsvd_1 : 4,
|
|
Joerg Roedel |
d89aa8 |
ga_root_ptr : 40,
|
|
Joerg Roedel |
d89aa8 |
- rsvd_2 : 12;
|
|
Joerg Roedel |
d89aa8 |
+ rsvd_2 : 4,
|
|
Joerg Roedel |
d89aa8 |
+ destination : 8;
|
|
Joerg Roedel |
d89aa8 |
} fields;
|
|
Joerg Roedel |
d89aa8 |
};
|
|
Joerg Roedel |
d89aa8 |
|