Skip to content

Commit 85f058c

Browse files
ssuthiku-amdsmb49
authored andcommitted
iommu/amd: Introduce Disable IRTE Caching Support
BugLink: https://bugs.launchpad.net/bugs/2039110 [ Upstream commit 6641903 ] 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 <jsnitsel@redhat.com> Co-developed-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com> Signed-off-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Link: https://lore.kernel.org/r/20230530141137.14376-4-suravee.suthikulpanit@amd.com Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 884aa40 commit 85f058c

3 files changed

Lines changed: 41 additions & 0 deletions

File tree

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
@@ -172,6 +172,7 @@
172172
#define CONTROL_GAINT_EN 29
173173
#define CONTROL_XT_EN 50
174174
#define CONTROL_INTCAPXT_EN 51
175+
#define CONTROL_IRTCACHEDIS 59
175176
#define CONTROL_SNPAVIC_EN 61
176177

177178
#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT)
@@ -708,6 +709,9 @@ struct amd_iommu {
708709
/* if one, we need to send a completion wait command */
709710
bool need_sync;
710711

712+
/* true if disable irte caching */
713+
bool irtcachedis_enabled;
714+
711715
/* Handle for IOMMU core code */
712716
struct iommu_device iommu;
713717

drivers/iommu/amd/init.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
160160
static bool amd_iommu_detected;
161161
static bool amd_iommu_disabled __initdata;
162162
static bool amd_iommu_force_enable __initdata;
163+
static bool amd_iommu_irtcachedis;
163164
static int amd_iommu_target_ivhd_type;
164165

165166
/* Global EFR and EFR2 registers */
@@ -477,6 +478,9 @@ static void iommu_disable(struct amd_iommu *iommu)
477478

478479
/* Disable IOMMU hardware itself */
479480
iommu_feature_disable(iommu, CONTROL_IOMMU_EN);
481+
482+
/* Clear IRTE cache disabling bit */
483+
iommu_feature_disable(iommu, CONTROL_IRTCACHEDIS);
480484
}
481485

482486
/*
@@ -2700,6 +2704,33 @@ static void iommu_enable_ga(struct amd_iommu *iommu)
27002704
#endif
27012705
}
27022706

2707+
static void iommu_disable_irtcachedis(struct amd_iommu *iommu)
2708+
{
2709+
iommu_feature_disable(iommu, CONTROL_IRTCACHEDIS);
2710+
}
2711+
2712+
static void iommu_enable_irtcachedis(struct amd_iommu *iommu)
2713+
{
2714+
u64 ctrl;
2715+
2716+
if (!amd_iommu_irtcachedis)
2717+
return;
2718+
2719+
/*
2720+
* Note:
2721+
* The support for IRTCacheDis feature is dertermined by
2722+
* checking if the bit is writable.
2723+
*/
2724+
iommu_feature_enable(iommu, CONTROL_IRTCACHEDIS);
2725+
ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
2726+
ctrl &= (1ULL << CONTROL_IRTCACHEDIS);
2727+
if (ctrl)
2728+
iommu->irtcachedis_enabled = true;
2729+
pr_info("iommu%d (%#06x) : IRT cache is %s\n",
2730+
iommu->index, iommu->devid,
2731+
iommu->irtcachedis_enabled ? "disabled" : "enabled");
2732+
}
2733+
27032734
static void early_enable_iommu(struct amd_iommu *iommu)
27042735
{
27052736
iommu_disable(iommu);
@@ -2710,6 +2741,7 @@ static void early_enable_iommu(struct amd_iommu *iommu)
27102741
iommu_set_exclusion_range(iommu);
27112742
iommu_enable_ga(iommu);
27122743
iommu_enable_xt(iommu);
2744+
iommu_enable_irtcachedis(iommu);
27132745
iommu_enable(iommu);
27142746
iommu_flush_all_caches(iommu);
27152747
}
@@ -2760,10 +2792,12 @@ static void early_enable_iommus(void)
27602792
for_each_iommu(iommu) {
27612793
iommu_disable_command_buffer(iommu);
27622794
iommu_disable_event_buffer(iommu);
2795+
iommu_disable_irtcachedis(iommu);
27632796
iommu_enable_command_buffer(iommu);
27642797
iommu_enable_event_buffer(iommu);
27652798
iommu_enable_ga(iommu);
27662799
iommu_enable_xt(iommu);
2800+
iommu_enable_irtcachedis(iommu);
27672801
iommu_set_device_table(iommu);
27682802
iommu_flush_all_caches(iommu);
27692803
}
@@ -3411,6 +3445,8 @@ static int __init parse_amd_iommu_options(char *str)
34113445
amd_iommu_pgtable = AMD_IOMMU_V1;
34123446
} else if (strncmp(str, "pgtbl_v2", 8) == 0) {
34133447
amd_iommu_pgtable = AMD_IOMMU_V2;
3448+
} else if (strncmp(str, "irtcachedis", 11) == 0) {
3449+
amd_iommu_irtcachedis = true;
34143450
} else {
34153451
pr_notice("Unknown option - '%s'\n", str);
34163452
}

0 commit comments

Comments
 (0)