aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>2016-08-23 14:52:32 -0400
committerJoerg Roedel <jroedel@suse.de>2016-09-05 06:41:46 -0400
commit3928aa3f5775fc4e40117077e97d73d8526039c9 (patch)
tree4694f5be6a1013a1c159425f0df465b48034435b
parent29b4817d4018df78086157ea3a55c1d9424a7cfc (diff)
iommu/amd: Detect and enable guest vAPIC support
This patch introduces a new IOMMU driver parameter, amd_iommu_guest_ir, which can be used to specify different interrupt remapping mode for passthrough devices to VM guest: * legacy: Legacy interrupt remapping (w/ 32-bit IRTE) * vapic : Guest vAPIC interrupt remapping (w/ GA mode 128-bit IRTE) Note that in vapic mode, it can also supports legacy interrupt remapping for non-passthrough devices with the 128-bit IRTE. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--Documentation/kernel-parameters.txt9
-rw-r--r--drivers/iommu/amd_iommu_init.c71
-rw-r--r--drivers/iommu/amd_iommu_proto.h1
-rw-r--r--drivers/iommu/amd_iommu_types.h24
4 files changed, 99 insertions, 6 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 46c030a49186..748ef7bdd64d 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -460,6 +460,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
460 driver will print ACPI tables for AMD IOMMU during 460 driver will print ACPI tables for AMD IOMMU during
461 IOMMU initialization. 461 IOMMU initialization.
462 462
463 amd_iommu_intr= [HW,X86-64]
464 Specifies one of the following AMD IOMMU interrupt
465 remapping modes:
466 legacy - Use legacy interrupt remapping mode.
467 vapic - Use virtual APIC mode, which allows IOMMU
468 to inject interrupts directly into guest.
469 This mode requires kvm-amd.avic=1.
470 (Default when IOMMU HW support is present.)
471
463 amijoy.map= [HW,JOY] Amiga joystick support 472 amijoy.map= [HW,JOY] Amiga joystick support
464 Map of devices attached to JOY0DAT and JOY1DAT 473 Map of devices attached to JOY0DAT and JOY1DAT
465 Format: <a>,<b> 474 Format: <a>,<b>
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 59741ead7e15..c3afd8669bfb 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -145,6 +145,8 @@ struct ivmd_header {
145bool amd_iommu_dump; 145bool amd_iommu_dump;
146bool amd_iommu_irq_remap __read_mostly; 146bool amd_iommu_irq_remap __read_mostly;
147 147
148int amd_iommu_guest_ir;
149
148static bool amd_iommu_detected; 150static bool amd_iommu_detected;
149static bool __initdata amd_iommu_disabled; 151static bool __initdata amd_iommu_disabled;
150static int amd_iommu_target_ivhd_type; 152static int amd_iommu_target_ivhd_type;
@@ -1258,6 +1260,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
1258 iommu->mmio_phys_end = MMIO_REG_END_OFFSET; 1260 iommu->mmio_phys_end = MMIO_REG_END_OFFSET;
1259 else 1261 else
1260 iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; 1262 iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
1263 if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
1264 amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
1261 break; 1265 break;
1262 case 0x11: 1266 case 0x11:
1263 case 0x40: 1267 case 0x40:
@@ -1265,6 +1269,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
1265 iommu->mmio_phys_end = MMIO_REG_END_OFFSET; 1269 iommu->mmio_phys_end = MMIO_REG_END_OFFSET;
1266 else 1270 else
1267 iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; 1271 iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
1272 if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0))
1273 amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
1268 break; 1274 break;
1269 default: 1275 default:
1270 return -EINVAL; 1276 return -EINVAL;
@@ -1488,6 +1494,14 @@ static int iommu_init_pci(struct amd_iommu *iommu)
1488 if (iommu_feature(iommu, FEATURE_PPR) && alloc_ppr_log(iommu)) 1494 if (iommu_feature(iommu, FEATURE_PPR) && alloc_ppr_log(iommu))
1489 return -ENOMEM; 1495 return -ENOMEM;
1490 1496
1497 /* Note: We have already checked GASup from IVRS table.
1498 * Now, we need to make sure that GAMSup is set.
1499 */
1500 if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) &&
1501 !iommu_feature(iommu, FEATURE_GAM_VAPIC))
1502 amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA;
1503
1504
1491 if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) 1505 if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE))
1492 amd_iommu_np_cache = true; 1506 amd_iommu_np_cache = true;
1493 1507
@@ -1545,16 +1559,24 @@ static void print_iommu_info(void)
1545 dev_name(&iommu->dev->dev), iommu->cap_ptr); 1559 dev_name(&iommu->dev->dev), iommu->cap_ptr);
1546 1560
1547 if (iommu->cap & (1 << IOMMU_CAP_EFR)) { 1561 if (iommu->cap & (1 << IOMMU_CAP_EFR)) {
1548 pr_info("AMD-Vi: Extended features: "); 1562 pr_info("AMD-Vi: Extended features (%#llx):\n",
1563 iommu->features);
1549 for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { 1564 for (i = 0; i < ARRAY_SIZE(feat_str); ++i) {
1550 if (iommu_feature(iommu, (1ULL << i))) 1565 if (iommu_feature(iommu, (1ULL << i)))
1551 pr_cont(" %s", feat_str[i]); 1566 pr_cont(" %s", feat_str[i]);
1552 } 1567 }
1568
1569 if (iommu->features & FEATURE_GAM_VAPIC)
1570 pr_cont(" GA_vAPIC");
1571
1553 pr_cont("\n"); 1572 pr_cont("\n");
1554 } 1573 }
1555 } 1574 }
1556 if (irq_remapping_enabled) 1575 if (irq_remapping_enabled) {
1557 pr_info("AMD-Vi: Interrupt remapping enabled\n"); 1576 pr_info("AMD-Vi: Interrupt remapping enabled\n");
1577 if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
1578 pr_info("AMD-Vi: virtual APIC enabled\n");
1579 }
1558} 1580}
1559 1581
1560static int __init amd_iommu_init_pci(void) 1582static int __init amd_iommu_init_pci(void)
@@ -1862,6 +1884,22 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu)
1862 iommu->stored_addr_lo | 1); 1884 iommu->stored_addr_lo | 1);
1863} 1885}
1864 1886
1887static void iommu_enable_ga(struct amd_iommu *iommu)
1888{
1889#ifdef CONFIG_IRQ_REMAP
1890 switch (amd_iommu_guest_ir) {
1891 case AMD_IOMMU_GUEST_IR_VAPIC:
1892 iommu_feature_enable(iommu, CONTROL_GAM_EN);
1893 /* Fall through */
1894 case AMD_IOMMU_GUEST_IR_LEGACY_GA:
1895 iommu_feature_enable(iommu, CONTROL_GA_EN);
1896 break;
1897 default:
1898 break;
1899 }
1900#endif
1901}
1902
1865/* 1903/*
1866 * This function finally enables all IOMMUs found in the system after 1904 * This function finally enables all IOMMUs found in the system after
1867 * they have been initialized 1905 * they have been initialized
@@ -1877,6 +1915,7 @@ static void early_enable_iommus(void)
1877 iommu_enable_command_buffer(iommu); 1915 iommu_enable_command_buffer(iommu);
1878 iommu_enable_event_buffer(iommu); 1916 iommu_enable_event_buffer(iommu);
1879 iommu_set_exclusion_range(iommu); 1917 iommu_set_exclusion_range(iommu);
1918 iommu_enable_ga(iommu);
1880 iommu_enable(iommu); 1919 iommu_enable(iommu);
1881 iommu_flush_all_caches(iommu); 1920 iommu_flush_all_caches(iommu);
1882 } 1921 }
@@ -2059,7 +2098,7 @@ static int __init early_amd_iommu_init(void)
2059 struct acpi_table_header *ivrs_base; 2098 struct acpi_table_header *ivrs_base;
2060 acpi_size ivrs_size; 2099 acpi_size ivrs_size;
2061 acpi_status status; 2100 acpi_status status;
2062 int i, ret = 0; 2101 int i, remap_cache_sz, ret = 0;
2063 2102
2064 if (!amd_iommu_detected) 2103 if (!amd_iommu_detected)
2065 return -ENODEV; 2104 return -ENODEV;
@@ -2157,10 +2196,14 @@ static int __init early_amd_iommu_init(void)
2157 * remapping tables. 2196 * remapping tables.
2158 */ 2197 */
2159 ret = -ENOMEM; 2198 ret = -ENOMEM;
2199 if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir))
2200 remap_cache_sz = MAX_IRQS_PER_TABLE * sizeof(u32);
2201 else
2202 remap_cache_sz = MAX_IRQS_PER_TABLE * (sizeof(u64) * 2);
2160 amd_iommu_irq_cache = kmem_cache_create("irq_remap_cache", 2203 amd_iommu_irq_cache = kmem_cache_create("irq_remap_cache",
2161 MAX_IRQS_PER_TABLE * sizeof(u32), 2204 remap_cache_sz,
2162 IRQ_TABLE_ALIGNMENT, 2205 IRQ_TABLE_ALIGNMENT,
2163 0, NULL); 2206 0, NULL);
2164 if (!amd_iommu_irq_cache) 2207 if (!amd_iommu_irq_cache)
2165 goto out; 2208 goto out;
2166 2209
@@ -2413,6 +2456,21 @@ static int __init parse_amd_iommu_dump(char *str)
2413 return 1; 2456 return 1;
2414} 2457}
2415 2458
2459static int __init parse_amd_iommu_intr(char *str)
2460{
2461 for (; *str; ++str) {
2462 if (strncmp(str, "legacy", 6) == 0) {
2463 amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
2464 break;
2465 }
2466 if (strncmp(str, "vapic", 5) == 0) {
2467 amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
2468 break;
2469 }
2470 }
2471 return 1;
2472}
2473
2416static int __init parse_amd_iommu_options(char *str) 2474static int __init parse_amd_iommu_options(char *str)
2417{ 2475{
2418 for (; *str; ++str) { 2476 for (; *str; ++str) {
@@ -2521,6 +2579,7 @@ static int __init parse_ivrs_acpihid(char *str)
2521 2579
2522__setup("amd_iommu_dump", parse_amd_iommu_dump); 2580__setup("amd_iommu_dump", parse_amd_iommu_dump);
2523__setup("amd_iommu=", parse_amd_iommu_options); 2581__setup("amd_iommu=", parse_amd_iommu_options);
2582__setup("amd_iommu_intr=", parse_amd_iommu_intr);
2524__setup("ivrs_ioapic", parse_ivrs_ioapic); 2583__setup("ivrs_ioapic", parse_ivrs_ioapic);
2525__setup("ivrs_hpet", parse_ivrs_hpet); 2584__setup("ivrs_hpet", parse_ivrs_hpet);
2526__setup("ivrs_acpihid", parse_ivrs_acpihid); 2585__setup("ivrs_acpihid", parse_ivrs_acpihid);
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index 0bd9eb374462..faa3b4895cf0 100644
--- a/drivers/iommu/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -38,6 +38,7 @@ extern int amd_iommu_enable(void);
38extern void amd_iommu_disable(void); 38extern void amd_iommu_disable(void);
39extern int amd_iommu_reenable(int); 39extern int amd_iommu_reenable(int);
40extern int amd_iommu_enable_faulting(void); 40extern int amd_iommu_enable_faulting(void);
41extern int amd_iommu_guest_ir;
41 42
42/* IOMMUv2 specific functions */ 43/* IOMMUv2 specific functions */
43struct iommu_domain; 44struct iommu_domain;
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index caf5e3822715..3d1fc37b051b 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -92,6 +92,7 @@
92#define FEATURE_GA (1ULL<<7) 92#define FEATURE_GA (1ULL<<7)
93#define FEATURE_HE (1ULL<<8) 93#define FEATURE_HE (1ULL<<8)
94#define FEATURE_PC (1ULL<<9) 94#define FEATURE_PC (1ULL<<9)
95#define FEATURE_GAM_VAPIC (1ULL<<21)
95 96
96#define FEATURE_PASID_SHIFT 32 97#define FEATURE_PASID_SHIFT 32
97#define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT) 98#define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT)
@@ -146,6 +147,8 @@
146#define CONTROL_PPFINT_EN 0x0eULL 147#define CONTROL_PPFINT_EN 0x0eULL
147#define CONTROL_PPR_EN 0x0fULL 148#define CONTROL_PPR_EN 0x0fULL
148#define CONTROL_GT_EN 0x10ULL 149#define CONTROL_GT_EN 0x10ULL
150#define CONTROL_GA_EN 0x11ULL
151#define CONTROL_GAM_EN 0x19ULL
149 152
150#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT) 153#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT)
151#define CTRL_INV_TO_NONE 0 154#define CTRL_INV_TO_NONE 0
@@ -329,6 +332,12 @@
329#define IOMMU_CAP_NPCACHE 26 332#define IOMMU_CAP_NPCACHE 26
330#define IOMMU_CAP_EFR 27 333#define IOMMU_CAP_EFR 27
331 334
335/* IOMMU Feature Reporting Field (for IVHD type 10h */
336#define IOMMU_FEAT_GASUP_SHIFT 6
337
338/* IOMMU Extended Feature Register (EFR) */
339#define IOMMU_EFR_GASUP_SHIFT 7
340
332#define MAX_DOMAIN_ID 65536 341#define MAX_DOMAIN_ID 65536
333 342
334/* Protection domain flags */ 343/* Protection domain flags */
@@ -681,4 +690,19 @@ static inline int get_hpet_devid(int id)
681 return -EINVAL; 690 return -EINVAL;
682} 691}
683 692
693enum amd_iommu_intr_mode_type {
694 AMD_IOMMU_GUEST_IR_LEGACY,
695
696 /* This mode is not visible to users. It is used when
697 * we cannot fully enable vAPIC and fallback to only support
698 * legacy interrupt remapping via 128-bit IRTE.
699 */
700 AMD_IOMMU_GUEST_IR_LEGACY_GA,
701 AMD_IOMMU_GUEST_IR_VAPIC,
702};
703
704#define AMD_IOMMU_GUEST_IR_GA(x) (x == AMD_IOMMU_GUEST_IR_VAPIC || \
705 x == AMD_IOMMU_GUEST_IR_LEGACY_GA)
706
707#define AMD_IOMMU_GUEST_IR_VAPIC(x) (x == AMD_IOMMU_GUEST_IR_VAPIC)
684#endif /* _ASM_X86_AMD_IOMMU_TYPES_H */ 708#endif /* _ASM_X86_AMD_IOMMU_TYPES_H */