diff options
author | Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> | 2018-06-27 11:31:22 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2018-07-06 08:43:47 -0400 |
commit | 90fcffd9cf5e7cc593169f529799f3e3c5437e75 (patch) | |
tree | 8cea3c13a5a83e5bf4667e05888ec7ac919f8556 | |
parent | e881dbd5d4a6950c9e2e7623c79d9578949365c9 (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.c | 21 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_init.c | 25 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_types.h | 17 |
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; | |||
153 | bool amd_iommu_irq_remap __read_mostly; | 153 | bool amd_iommu_irq_remap __read_mostly; |
154 | 154 | ||
155 | int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC; | 155 | int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC; |
156 | static int amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE; | ||
156 | 157 | ||
157 | static bool amd_iommu_detected; | 158 | static bool amd_iommu_detected; |
158 | static bool __initdata amd_iommu_disabled; | 159 | static 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 | ||
831 | static 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 | |||
830 | static void iommu_enable_gt(struct amd_iommu *iommu) | 844 | static 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 | ||
2698 | void amd_iommu_disable(void) | 2719 | void 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 | |||
813 | union irte_ga_lo { | 818 | union 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 | ||