aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/amd_iommu_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/amd_iommu_init.c')
-rw-r--r--drivers/iommu/amd_iommu_init.c63
1 files changed, 51 insertions, 12 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 013bdfff2d4d..bf4959f4225b 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -228,6 +228,10 @@ static int amd_iommu_enable_interrupts(void);
228static int __init iommu_go_to_state(enum iommu_init_state state); 228static int __init iommu_go_to_state(enum iommu_init_state state);
229static void init_device_table_dma(void); 229static void init_device_table_dma(void);
230 230
231static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
232 u8 bank, u8 cntr, u8 fxn,
233 u64 *value, bool is_write);
234
231static inline void update_last_devid(u16 devid) 235static inline void update_last_devid(u16 devid)
232{ 236{
233 if (devid > amd_iommu_last_bdf) 237 if (devid > amd_iommu_last_bdf)
@@ -1016,6 +1020,34 @@ static void amd_iommu_erratum_746_workaround(struct amd_iommu *iommu)
1016} 1020}
1017 1021
1018/* 1022/*
1023 * Family15h Model 30h-3fh (IOMMU Mishandles ATS Write Permission)
1024 * Workaround:
1025 * BIOS should enable ATS write permission check by setting
1026 * L2_DEBUG_3[AtsIgnoreIWDis](D0F2xF4_x47[0]) = 1b
1027 */
1028static void amd_iommu_ats_write_check_workaround(struct amd_iommu *iommu)
1029{
1030 u32 value;
1031
1032 if ((boot_cpu_data.x86 != 0x15) ||
1033 (boot_cpu_data.x86_model < 0x30) ||
1034 (boot_cpu_data.x86_model > 0x3f))
1035 return;
1036
1037 /* Test L2_DEBUG_3[AtsIgnoreIWDis] == 1 */
1038 value = iommu_read_l2(iommu, 0x47);
1039
1040 if (value & BIT(0))
1041 return;
1042
1043 /* Set L2_DEBUG_3[AtsIgnoreIWDis] = 1 */
1044 iommu_write_l2(iommu, 0x47, value | BIT(0));
1045
1046 pr_info("AMD-Vi: Applying ATS write check workaround for IOMMU at %s\n",
1047 dev_name(&iommu->dev->dev));
1048}
1049
1050/*
1019 * This function clues the initialization function for one IOMMU 1051 * This function clues the initialization function for one IOMMU
1020 * together and also allocates the command buffer and programs the 1052 * together and also allocates the command buffer and programs the
1021 * hardware. It does NOT enable the IOMMU. This is done afterwards. 1053 * hardware. It does NOT enable the IOMMU. This is done afterwards.
@@ -1142,8 +1174,8 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu)
1142 amd_iommu_pc_present = true; 1174 amd_iommu_pc_present = true;
1143 1175
1144 /* Check if the performance counters can be written to */ 1176 /* Check if the performance counters can be written to */
1145 if ((0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val, true)) || 1177 if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) ||
1146 (0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val2, false)) || 1178 (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) ||
1147 (val != val2)) { 1179 (val != val2)) {
1148 pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n"); 1180 pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n");
1149 amd_iommu_pc_present = false; 1181 amd_iommu_pc_present = false;
@@ -1284,6 +1316,7 @@ static int iommu_init_pci(struct amd_iommu *iommu)
1284 } 1316 }
1285 1317
1286 amd_iommu_erratum_746_workaround(iommu); 1318 amd_iommu_erratum_746_workaround(iommu);
1319 amd_iommu_ats_write_check_workaround(iommu);
1287 1320
1288 iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu, 1321 iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu,
1289 amd_iommu_groups, "ivhd%d", 1322 amd_iommu_groups, "ivhd%d",
@@ -2283,22 +2316,15 @@ u8 amd_iommu_pc_get_max_counters(u16 devid)
2283} 2316}
2284EXPORT_SYMBOL(amd_iommu_pc_get_max_counters); 2317EXPORT_SYMBOL(amd_iommu_pc_get_max_counters);
2285 2318
2286int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, 2319static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
2320 u8 bank, u8 cntr, u8 fxn,
2287 u64 *value, bool is_write) 2321 u64 *value, bool is_write)
2288{ 2322{
2289 struct amd_iommu *iommu;
2290 u32 offset; 2323 u32 offset;
2291 u32 max_offset_lim; 2324 u32 max_offset_lim;
2292 2325
2293 /* Make sure the IOMMU PC resource is available */
2294 if (!amd_iommu_pc_present)
2295 return -ENODEV;
2296
2297 /* Locate the iommu associated with the device ID */
2298 iommu = amd_iommu_rlookup_table[devid];
2299
2300 /* Check for valid iommu and pc register indexing */ 2326 /* Check for valid iommu and pc register indexing */
2301 if (WARN_ON((iommu == NULL) || (fxn > 0x28) || (fxn & 7))) 2327 if (WARN_ON((fxn > 0x28) || (fxn & 7)))
2302 return -ENODEV; 2328 return -ENODEV;
2303 2329
2304 offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn); 2330 offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn);
@@ -2322,3 +2348,16 @@ int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
2322 return 0; 2348 return 0;
2323} 2349}
2324EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val); 2350EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val);
2351
2352int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
2353 u64 *value, bool is_write)
2354{
2355 struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
2356
2357 /* Make sure the IOMMU PC resource is available */
2358 if (!amd_iommu_pc_present || iommu == NULL)
2359 return -ENODEV;
2360
2361 return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn,
2362 value, is_write);
2363}