aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>2018-06-27 11:31:22 -0400
committerJoerg Roedel <jroedel@suse.de>2018-07-06 08:43:47 -0400
commit90fcffd9cf5e7cc593169f529799f3e3c5437e75 (patch)
tree8cea3c13a5a83e5bf4667e05888ec7ac919f8556
parente881dbd5d4a6950c9e2e7623c79d9578949365c9 (diff)
iommu/amd: Add support for IOMMU XT mode
The AMD IOMMU XT mode enables interrupt remapping with 32-bit destination APIC ID, which is required for x2APIC. The feature is available when the XTSup bit is set in the IOMMU Extended Feature register and/or the IVHD Type 10h IOMMU Feature Reporting field. For more information, please see section "IOMMU x2APIC Support" of the AMD I/O Virtualization Technology (IOMMU) Specification. Cc: Joerg Roedel <jroedel@suse.de> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/amd_iommu.c21
-rw-r--r--drivers/iommu/amd_iommu_init.c25
-rw-r--r--drivers/iommu/amd_iommu_types.h17
3 files changed, 50 insertions, 13 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 874e6480e391..64cfe854e0f5 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3876,7 +3876,8 @@ static void irte_ga_prepare(void *entry,
3876 irte->lo.fields_remap.int_type = delivery_mode; 3876 irte->lo.fields_remap.int_type = delivery_mode;
3877 irte->lo.fields_remap.dm = dest_mode; 3877 irte->lo.fields_remap.dm = dest_mode;
3878 irte->hi.fields.vector = vector; 3878 irte->hi.fields.vector = vector;
3879 irte->lo.fields_remap.destination = dest_apicid; 3879 irte->lo.fields_remap.destination = APICID_TO_IRTE_DEST_LO(dest_apicid);
3880 irte->hi.fields.destination = APICID_TO_IRTE_DEST_HI(dest_apicid);
3880 irte->lo.fields_remap.valid = 1; 3881 irte->lo.fields_remap.valid = 1;
3881} 3882}
3882 3883
@@ -3929,7 +3930,10 @@ static void irte_ga_set_affinity(void *entry, u16 devid, u16 index,
3929 3930
3930 if (!irte->lo.fields_remap.guest_mode) { 3931 if (!irte->lo.fields_remap.guest_mode) {
3931 irte->hi.fields.vector = vector; 3932 irte->hi.fields.vector = vector;
3932 irte->lo.fields_remap.destination = dest_apicid; 3933 irte->lo.fields_remap.destination =
3934 APICID_TO_IRTE_DEST_LO(dest_apicid);
3935 irte->hi.fields.destination =
3936 APICID_TO_IRTE_DEST_HI(dest_apicid);
3933 modify_irte_ga(devid, index, irte, NULL); 3937 modify_irte_ga(devid, index, irte, NULL);
3934 } 3938 }
3935} 3939}
@@ -4346,7 +4350,10 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info)
4346 irte->lo.val = 0; 4350 irte->lo.val = 0;
4347 irte->hi.fields.vector = cfg->vector; 4351 irte->hi.fields.vector = cfg->vector;
4348 irte->lo.fields_remap.guest_mode = 0; 4352 irte->lo.fields_remap.guest_mode = 0;
4349 irte->lo.fields_remap.destination = cfg->dest_apicid; 4353 irte->lo.fields_remap.destination =
4354 APICID_TO_IRTE_DEST_LO(cfg->dest_apicid);
4355 irte->hi.fields.destination =
4356 APICID_TO_IRTE_DEST_HI(cfg->dest_apicid);
4350 irte->lo.fields_remap.int_type = apic->irq_delivery_mode; 4357 irte->lo.fields_remap.int_type = apic->irq_delivery_mode;
4351 irte->lo.fields_remap.dm = apic->irq_dest_mode; 4358 irte->lo.fields_remap.dm = apic->irq_dest_mode;
4352 4359
@@ -4463,8 +4470,12 @@ int amd_iommu_update_ga(int cpu, bool is_run, void *data)
4463 raw_spin_lock_irqsave(&table->lock, flags); 4470 raw_spin_lock_irqsave(&table->lock, flags);
4464 4471
4465 if (ref->lo.fields_vapic.guest_mode) { 4472 if (ref->lo.fields_vapic.guest_mode) {
4466 if (cpu >= 0) 4473 if (cpu >= 0) {
4467 ref->lo.fields_vapic.destination = cpu; 4474 ref->lo.fields_vapic.destination =
4475 APICID_TO_IRTE_DEST_LO(cpu);
4476 ref->hi.fields.destination =
4477 APICID_TO_IRTE_DEST_HI(cpu);
4478 }
4468 ref->lo.fields_vapic.is_run = is_run; 4479 ref->lo.fields_vapic.is_run = is_run;
4469 barrier(); 4480 barrier();
4470 } 4481 }
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 7d494f2c28a1..f6dd63fed21e 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -153,6 +153,7 @@ bool amd_iommu_dump;
153bool amd_iommu_irq_remap __read_mostly; 153bool amd_iommu_irq_remap __read_mostly;
154 154
155int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC; 155int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
156static int amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
156 157
157static bool amd_iommu_detected; 158static bool amd_iommu_detected;
158static bool __initdata amd_iommu_disabled; 159static bool __initdata amd_iommu_disabled;
@@ -827,6 +828,19 @@ static int iommu_init_ga(struct amd_iommu *iommu)
827 return ret; 828 return ret;
828} 829}
829 830
831static void iommu_enable_xt(struct amd_iommu *iommu)
832{
833#ifdef CONFIG_IRQ_REMAP
834 /*
835 * XT mode (32-bit APIC destination ID) requires
836 * GA mode (128-bit IRTE support) as a prerequisite.
837 */
838 if (AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir) &&
839 amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
840 iommu_feature_enable(iommu, CONTROL_XT_EN);
841#endif /* CONFIG_IRQ_REMAP */
842}
843
830static void iommu_enable_gt(struct amd_iommu *iommu) 844static void iommu_enable_gt(struct amd_iommu *iommu)
831{ 845{
832 if (!iommu_feature(iommu, FEATURE_GT)) 846 if (!iommu_feature(iommu, FEATURE_GT))
@@ -1507,6 +1521,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
1507 iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; 1521 iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
1508 if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0)) 1522 if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
1509 amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; 1523 amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
1524 if (((h->efr_attr & (0x1 << IOMMU_FEAT_XTSUP_SHIFT)) == 0))
1525 amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
1510 break; 1526 break;
1511 case 0x11: 1527 case 0x11:
1512 case 0x40: 1528 case 0x40:
@@ -1516,6 +1532,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
1516 iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; 1532 iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
1517 if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0)) 1533 if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0))
1518 amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; 1534 amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
1535 if (((h->efr_reg & (0x1 << IOMMU_EFR_XTSUP_SHIFT)) == 0))
1536 amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
1519 break; 1537 break;
1520 default: 1538 default:
1521 return -EINVAL; 1539 return -EINVAL;
@@ -1832,6 +1850,8 @@ static void print_iommu_info(void)
1832 pr_info("AMD-Vi: Interrupt remapping enabled\n"); 1850 pr_info("AMD-Vi: Interrupt remapping enabled\n");
1833 if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) 1851 if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
1834 pr_info("AMD-Vi: virtual APIC enabled\n"); 1852 pr_info("AMD-Vi: virtual APIC enabled\n");
1853 if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
1854 pr_info("AMD-Vi: X2APIC enabled\n");
1835 } 1855 }
1836} 1856}
1837 1857
@@ -2168,6 +2188,7 @@ static void early_enable_iommu(struct amd_iommu *iommu)
2168 iommu_enable_event_buffer(iommu); 2188 iommu_enable_event_buffer(iommu);
2169 iommu_set_exclusion_range(iommu); 2189 iommu_set_exclusion_range(iommu);
2170 iommu_enable_ga(iommu); 2190 iommu_enable_ga(iommu);
2191 iommu_enable_xt(iommu);
2171 iommu_enable(iommu); 2192 iommu_enable(iommu);
2172 iommu_flush_all_caches(iommu); 2193 iommu_flush_all_caches(iommu);
2173} 2194}
@@ -2212,6 +2233,7 @@ static void early_enable_iommus(void)
2212 iommu_enable_command_buffer(iommu); 2233 iommu_enable_command_buffer(iommu);
2213 iommu_enable_event_buffer(iommu); 2234 iommu_enable_event_buffer(iommu);
2214 iommu_enable_ga(iommu); 2235 iommu_enable_ga(iommu);
2236 iommu_enable_xt(iommu);
2215 iommu_set_device_table(iommu); 2237 iommu_set_device_table(iommu);
2216 iommu_flush_all_caches(iommu); 2238 iommu_flush_all_caches(iommu);
2217 } 2239 }
@@ -2691,8 +2713,7 @@ int __init amd_iommu_enable(void)
2691 return ret; 2713 return ret;
2692 2714
2693 irq_remapping_enabled = 1; 2715 irq_remapping_enabled = 1;
2694 2716 return amd_iommu_xt_mode;
2695 return 0;
2696} 2717}
2697 2718
2698void amd_iommu_disable(void) 2719void amd_iommu_disable(void)
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 986cbe0cc189..aa892fdbd158 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -161,6 +161,7 @@
161#define CONTROL_GAM_EN 0x19ULL 161#define CONTROL_GAM_EN 0x19ULL
162#define CONTROL_GALOG_EN 0x1CULL 162#define CONTROL_GALOG_EN 0x1CULL
163#define CONTROL_GAINT_EN 0x1DULL 163#define CONTROL_GAINT_EN 0x1DULL
164#define CONTROL_XT_EN 0x32ULL
164 165
165#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT) 166#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT)
166#define CTRL_INV_TO_NONE 0 167#define CTRL_INV_TO_NONE 0
@@ -378,9 +379,11 @@
378#define IOMMU_CAP_EFR 27 379#define IOMMU_CAP_EFR 27
379 380
380/* IOMMU Feature Reporting Field (for IVHD type 10h */ 381/* IOMMU Feature Reporting Field (for IVHD type 10h */
382#define IOMMU_FEAT_XTSUP_SHIFT 0
381#define IOMMU_FEAT_GASUP_SHIFT 6 383#define IOMMU_FEAT_GASUP_SHIFT 6
382 384
383/* IOMMU Extended Feature Register (EFR) */ 385/* IOMMU Extended Feature Register (EFR) */
386#define IOMMU_EFR_XTSUP_SHIFT 2
384#define IOMMU_EFR_GASUP_SHIFT 7 387#define IOMMU_EFR_GASUP_SHIFT 7
385 388
386#define MAX_DOMAIN_ID 65536 389#define MAX_DOMAIN_ID 65536
@@ -437,7 +440,6 @@ extern struct kmem_cache *amd_iommu_irq_cache;
437#define APERTURE_RANGE_INDEX(a) ((a) >> APERTURE_RANGE_SHIFT) 440#define APERTURE_RANGE_INDEX(a) ((a) >> APERTURE_RANGE_SHIFT)
438#define APERTURE_PAGE_INDEX(a) (((a) >> 21) & 0x3fULL) 441#define APERTURE_PAGE_INDEX(a) (((a) >> 21) & 0x3fULL)
439 442
440
441/* 443/*
442 * This struct is used to pass information about 444 * This struct is used to pass information about
443 * incoming PPR faults around. 445 * incoming PPR faults around.
@@ -810,6 +812,9 @@ union irte {
810 } fields; 812 } fields;
811}; 813};
812 814
815#define APICID_TO_IRTE_DEST_LO(x) (x & 0xffffff)
816#define APICID_TO_IRTE_DEST_HI(x) ((x >> 24) & 0xff)
817
813union irte_ga_lo { 818union irte_ga_lo {
814 u64 val; 819 u64 val;
815 820
@@ -823,8 +828,8 @@ union irte_ga_lo {
823 dm : 1, 828 dm : 1,
824 /* ------ */ 829 /* ------ */
825 guest_mode : 1, 830 guest_mode : 1,
826 destination : 8, 831 destination : 24,
827 rsvd : 48; 832 ga_tag : 32;
828 } fields_remap; 833 } fields_remap;
829 834
830 /* For guest vAPIC */ 835 /* For guest vAPIC */
@@ -837,8 +842,7 @@ union irte_ga_lo {
837 is_run : 1, 842 is_run : 1,
838 /* ------ */ 843 /* ------ */
839 guest_mode : 1, 844 guest_mode : 1,
840 destination : 8, 845 destination : 24,
841 rsvd2 : 16,
842 ga_tag : 32; 846 ga_tag : 32;
843 } fields_vapic; 847 } fields_vapic;
844}; 848};
@@ -849,7 +853,8 @@ union irte_ga_hi {
849 u64 vector : 8, 853 u64 vector : 8,
850 rsvd_1 : 4, 854 rsvd_1 : 4,
851 ga_root_ptr : 40, 855 ga_root_ptr : 40,
852 rsvd_2 : 12; 856 rsvd_2 : 4,
857 destination : 8;
853 } fields; 858 } fields;
854}; 859};
855 860