Skip to content

Commit 6641903

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Introduce Disable IRTE Caching Support
An Interrupt Remapping Table (IRT) stores interrupt remapping configuration for each device. In a normal operation, the AMD IOMMU caches the table to optimize subsequent data accesses. This requires the IOMMU driver to invalidate IRT whenever it updates the table. The invalidation process includes issuing an INVALIDATE_INTERRUPT_TABLE command following by a COMPLETION_WAIT command. However, there are cases in which the IRT is updated at a high rate. For example, for IOMMU AVIC, the IRTE[IsRun] bit is updated on every vcpu scheduling (i.e. amd_iommu_update_ga()). On system with large amount of vcpus and VFIO PCI pass-through devices, the invalidation process could potentially become a performance bottleneck. Introducing a new kernel boot option: amd_iommu=irtcachedis which disables IRTE caching by setting the IRTCachedis bit in each IOMMU Control register, and bypass the IRT invalidation process. Reviewed-by: Jerry Snitselaar <[email protected]> Co-developed-by: Alejandro Jimenez <[email protected]> Signed-off-by: Alejandro Jimenez <[email protected]> Signed-off-by: Suravee Suthikulpanit <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 74a3781 commit 6641903

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@
323323
option with care.
324324
pgtbl_v1 - Use v1 page table for DMA-API (Default).
325325
pgtbl_v2 - Use v2 page table for DMA-API.
326+
irtcachedis - Disable Interrupt Remapping Table (IRT) caching.
326327

327328
amd_iommu_dump= [HW,X86-64]
328329
Enable AMD IOMMU driver option to dump the ACPI table

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
#define CONTROL_GAINT_EN 29
175175
#define CONTROL_XT_EN 50
176176
#define CONTROL_INTCAPXT_EN 51
177+
#define CONTROL_IRTCACHEDIS 59
177178
#define CONTROL_SNPAVIC_EN 61
178179

179180
#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT)
@@ -716,6 +717,9 @@ struct amd_iommu {
716717
/* if one, we need to send a completion wait command */
717718
bool need_sync;
718719

720+
/* true if disable irte caching */
721+
bool irtcachedis_enabled;
722+
719723
/* Handle for IOMMU core code */
720724
struct iommu_device iommu;
721725

drivers/iommu/amd/init.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
162162
static bool amd_iommu_detected;
163163
static bool amd_iommu_disabled __initdata;
164164
static bool amd_iommu_force_enable __initdata;
165+
static bool amd_iommu_irtcachedis;
165166
static int amd_iommu_target_ivhd_type;
166167

167168
/* Global EFR and EFR2 registers */
@@ -484,6 +485,9 @@ static void iommu_disable(struct amd_iommu *iommu)
484485

485486
/* Disable IOMMU hardware itself */
486487
iommu_feature_disable(iommu, CONTROL_IOMMU_EN);
488+
489+
/* Clear IRTE cache disabling bit */
490+
iommu_feature_disable(iommu, CONTROL_IRTCACHEDIS);
487491
}
488492

489493
/*
@@ -2686,6 +2690,33 @@ static void iommu_enable_ga(struct amd_iommu *iommu)
26862690
#endif
26872691
}
26882692

2693+
static void iommu_disable_irtcachedis(struct amd_iommu *iommu)
2694+
{
2695+
iommu_feature_disable(iommu, CONTROL_IRTCACHEDIS);
2696+
}
2697+
2698+
static void iommu_enable_irtcachedis(struct amd_iommu *iommu)
2699+
{
2700+
u64 ctrl;
2701+
2702+
if (!amd_iommu_irtcachedis)
2703+
return;
2704+
2705+
/*
2706+
* Note:
2707+
* The support for IRTCacheDis feature is dertermined by
2708+
* checking if the bit is writable.
2709+
*/
2710+
iommu_feature_enable(iommu, CONTROL_IRTCACHEDIS);
2711+
ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
2712+
ctrl &= (1ULL << CONTROL_IRTCACHEDIS);
2713+
if (ctrl)
2714+
iommu->irtcachedis_enabled = true;
2715+
pr_info("iommu%d (%#06x) : IRT cache is %s\n",
2716+
iommu->index, iommu->devid,
2717+
iommu->irtcachedis_enabled ? "disabled" : "enabled");
2718+
}
2719+
26892720
static void early_enable_iommu(struct amd_iommu *iommu)
26902721
{
26912722
iommu_disable(iommu);
@@ -2696,6 +2727,7 @@ static void early_enable_iommu(struct amd_iommu *iommu)
26962727
iommu_set_exclusion_range(iommu);
26972728
iommu_enable_ga(iommu);
26982729
iommu_enable_xt(iommu);
2730+
iommu_enable_irtcachedis(iommu);
26992731
iommu_enable(iommu);
27002732
iommu_flush_all_caches(iommu);
27012733
}
@@ -2746,10 +2778,12 @@ static void early_enable_iommus(void)
27462778
for_each_iommu(iommu) {
27472779
iommu_disable_command_buffer(iommu);
27482780
iommu_disable_event_buffer(iommu);
2781+
iommu_disable_irtcachedis(iommu);
27492782
iommu_enable_command_buffer(iommu);
27502783
iommu_enable_event_buffer(iommu);
27512784
iommu_enable_ga(iommu);
27522785
iommu_enable_xt(iommu);
2786+
iommu_enable_irtcachedis(iommu);
27532787
iommu_set_device_table(iommu);
27542788
iommu_flush_all_caches(iommu);
27552789
}
@@ -3402,6 +3436,8 @@ static int __init parse_amd_iommu_options(char *str)
34023436
amd_iommu_pgtable = AMD_IOMMU_V1;
34033437
} else if (strncmp(str, "pgtbl_v2", 8) == 0) {
34043438
amd_iommu_pgtable = AMD_IOMMU_V2;
3439+
} else if (strncmp(str, "irtcachedis", 11) == 0) {
3440+
amd_iommu_irtcachedis = true;
34053441
} else {
34063442
pr_notice("Unknown option - '%s'\n", str);
34073443
}

0 commit comments

Comments
 (0)