Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf/x86/amd: Add IOMMU Performance Counter resource management

Add functionality to check the availability of the AMD IOMMU Performance
Counters and export this functionality to other core drivers, such as in this
case, a perf AMD IOMMU PMU. This feature is not bound to any specific AMD
family/model other than the presence of the IOMMU with P-C enabled.

The AMD IOMMU P-C support static counting only at this time.

Signed-off-by: Steven Kinney <steven.kinney@amd.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1370466709-3212-2-git-send-email-suravee.suthikulpanit@amd.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Steven L Kinney and committed by
Ingo Molnar
30861ddc ae0def05

+150 -12
+131 -9
drivers/iommu/amd_iommu_init.c
··· 99 99 u64 mmio_phys; 100 100 u16 pci_seg; 101 101 u16 info; 102 - u32 reserved; 102 + u32 efr; 103 103 } __attribute__((packed)); 104 104 105 105 /* ··· 154 154 u32 amd_iommu_max_pasids __read_mostly = ~0; 155 155 156 156 bool amd_iommu_v2_present __read_mostly; 157 + bool amd_iommu_pc_present __read_mostly; 157 158 158 159 bool amd_iommu_force_isolation __read_mostly; 159 160 ··· 370 369 * mapping and unmapping functions for the IOMMU MMIO space. Each AMD IOMMU in 371 370 * the system has one. 372 371 */ 373 - static u8 __iomem * __init iommu_map_mmio_space(u64 address) 372 + static u8 __iomem * __init iommu_map_mmio_space(u64 address, u64 end) 374 373 { 375 - if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu")) { 376 - pr_err("AMD-Vi: Can not reserve memory region %llx for mmio\n", 377 - address); 374 + if (!request_mem_region(address, end, "amd_iommu")) { 375 + pr_err("AMD-Vi: Can not reserve memory region %llx-%llx for mmio\n", 376 + address, end); 378 377 pr_err("AMD-Vi: This is a BIOS bug. Please contact your hardware vendor\n"); 379 378 return NULL; 380 379 } 381 380 382 - return (u8 __iomem *)ioremap_nocache(address, MMIO_REGION_LENGTH); 381 + return (u8 __iomem *)ioremap_nocache(address, end); 383 382 } 384 383 385 384 static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu) 386 385 { 387 386 if (iommu->mmio_base) 388 387 iounmap(iommu->mmio_base); 389 - release_mem_region(iommu->mmio_phys, MMIO_REGION_LENGTH); 388 + release_mem_region(iommu->mmio_phys, iommu->mmio_phys_end); 390 389 } 391 390 392 391 /**************************************************************************** ··· 1086 1085 iommu->cap_ptr = h->cap_ptr; 1087 1086 iommu->pci_seg = h->pci_seg; 1088 1087 iommu->mmio_phys = h->mmio_phys; 1089 - iommu->mmio_base = iommu_map_mmio_space(h->mmio_phys); 1088 + 1089 + /* Check if IVHD EFR contains proper max banks/counters */ 1090 + if ((h->efr != 0) && 1091 + ((h->efr & (0xF << 13)) != 0) && 1092 + ((h->efr & (0x3F << 17)) != 0)) { 1093 + iommu->mmio_phys_end = MMIO_REG_END_OFFSET; 1094 + } else { 1095 + iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; 1096 + } 1097 + 1098 + iommu->mmio_base = iommu_map_mmio_space(iommu->mmio_phys, 1099 + iommu->mmio_phys_end); 1090 1100 if (!iommu->mmio_base) 1091 1101 return -ENOMEM; 1092 1102 ··· 1172 1160 return 0; 1173 1161 } 1174 1162 1163 + 1164 + static void init_iommu_perf_ctr(struct amd_iommu *iommu) 1165 + { 1166 + u64 val = 0xabcd, val2 = 0; 1167 + 1168 + if (!iommu_feature(iommu, FEATURE_PC)) 1169 + return; 1170 + 1171 + amd_iommu_pc_present = true; 1172 + 1173 + /* Check if the performance counters can be written to */ 1174 + if ((0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val, true)) || 1175 + (0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val2, false)) || 1176 + (val != val2)) { 1177 + pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n"); 1178 + amd_iommu_pc_present = false; 1179 + return; 1180 + } 1181 + 1182 + pr_info("AMD-Vi: IOMMU performance counters supported\n"); 1183 + 1184 + val = readl(iommu->mmio_base + MMIO_CNTR_CONF_OFFSET); 1185 + iommu->max_banks = (u8) ((val >> 12) & 0x3f); 1186 + iommu->max_counters = (u8) ((val >> 7) & 0xf); 1187 + } 1188 + 1189 + 1175 1190 static int iommu_init_pci(struct amd_iommu *iommu) 1176 1191 { 1177 1192 int cap_ptr = iommu->cap_ptr; ··· 1265 1226 if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) 1266 1227 amd_iommu_np_cache = true; 1267 1228 1229 + init_iommu_perf_ctr(iommu); 1230 + 1268 1231 if (is_rd890_iommu(iommu->dev)) { 1269 1232 int i, j; 1270 1233 ··· 1319 1278 if (iommu_feature(iommu, (1ULL << i))) 1320 1279 pr_cont(" %s", feat_str[i]); 1321 1280 } 1322 - pr_cont("\n"); 1281 + pr_cont("\n"); 1323 1282 } 1324 1283 } 1325 1284 if (irq_remapping_enabled) ··· 2273 2232 return amd_iommu_v2_present; 2274 2233 } 2275 2234 EXPORT_SYMBOL(amd_iommu_v2_supported); 2235 + 2236 + /**************************************************************************** 2237 + * 2238 + * IOMMU EFR Performance Counter support functionality. This code allows 2239 + * access to the IOMMU PC functionality. 2240 + * 2241 + ****************************************************************************/ 2242 + 2243 + u8 amd_iommu_pc_get_max_banks(u16 devid) 2244 + { 2245 + struct amd_iommu *iommu; 2246 + u8 ret = 0; 2247 + 2248 + /* locate the iommu governing the devid */ 2249 + iommu = amd_iommu_rlookup_table[devid]; 2250 + if (iommu) 2251 + ret = iommu->max_banks; 2252 + 2253 + return ret; 2254 + } 2255 + EXPORT_SYMBOL(amd_iommu_pc_get_max_banks); 2256 + 2257 + bool amd_iommu_pc_supported(void) 2258 + { 2259 + return amd_iommu_pc_present; 2260 + } 2261 + EXPORT_SYMBOL(amd_iommu_pc_supported); 2262 + 2263 + u8 amd_iommu_pc_get_max_counters(u16 devid) 2264 + { 2265 + struct amd_iommu *iommu; 2266 + u8 ret = 0; 2267 + 2268 + /* locate the iommu governing the devid */ 2269 + iommu = amd_iommu_rlookup_table[devid]; 2270 + if (iommu) 2271 + ret = iommu->max_counters; 2272 + 2273 + return ret; 2274 + } 2275 + EXPORT_SYMBOL(amd_iommu_pc_get_max_counters); 2276 + 2277 + int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, 2278 + u64 *value, bool is_write) 2279 + { 2280 + struct amd_iommu *iommu; 2281 + u32 offset; 2282 + u32 max_offset_lim; 2283 + 2284 + /* Make sure the IOMMU PC resource is available */ 2285 + if (!amd_iommu_pc_present) 2286 + return -ENODEV; 2287 + 2288 + /* Locate the iommu associated with the device ID */ 2289 + iommu = amd_iommu_rlookup_table[devid]; 2290 + 2291 + /* Check for valid iommu and pc register indexing */ 2292 + if (WARN_ON((iommu == NULL) || (fxn > 0x28) || (fxn & 7))) 2293 + return -ENODEV; 2294 + 2295 + offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn); 2296 + 2297 + /* Limit the offset to the hw defined mmio region aperture */ 2298 + max_offset_lim = (u32)(((0x40|iommu->max_banks) << 12) | 2299 + (iommu->max_counters << 8) | 0x28); 2300 + if ((offset < MMIO_CNTR_REG_OFFSET) || 2301 + (offset > max_offset_lim)) 2302 + return -EINVAL; 2303 + 2304 + if (is_write) { 2305 + writel((u32)*value, iommu->mmio_base + offset); 2306 + writel((*value >> 32), iommu->mmio_base + offset + 4); 2307 + } else { 2308 + *value = readl(iommu->mmio_base + offset + 4); 2309 + *value <<= 32; 2310 + *value = readl(iommu->mmio_base + offset); 2311 + } 2312 + 2313 + return 0; 2314 + } 2315 + EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val);
+7
drivers/iommu/amd_iommu_proto.h
··· 56 56 extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid); 57 57 extern struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev); 58 58 59 + /* IOMMU Performance Counter functions */ 60 + extern bool amd_iommu_pc_supported(void); 61 + extern u8 amd_iommu_pc_get_max_banks(u16 devid); 62 + extern u8 amd_iommu_pc_get_max_counters(u16 devid); 63 + extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, 64 + u64 *value, bool is_write); 65 + 59 66 #define PPR_SUCCESS 0x0 60 67 #define PPR_INVALID 0x1 61 68 #define PPR_FAILURE 0xf
+12 -3
drivers/iommu/amd_iommu_types.h
··· 38 38 #define ALIAS_TABLE_ENTRY_SIZE 2 39 39 #define RLOOKUP_TABLE_ENTRY_SIZE (sizeof(void *)) 40 40 41 - /* Length of the MMIO region for the AMD IOMMU */ 42 - #define MMIO_REGION_LENGTH 0x4000 43 - 44 41 /* Capability offsets used by the driver */ 45 42 #define MMIO_CAP_HDR_OFFSET 0x00 46 43 #define MMIO_RANGE_OFFSET 0x0c ··· 75 78 #define MMIO_STATUS_OFFSET 0x2020 76 79 #define MMIO_PPR_HEAD_OFFSET 0x2030 77 80 #define MMIO_PPR_TAIL_OFFSET 0x2038 81 + #define MMIO_CNTR_CONF_OFFSET 0x4000 82 + #define MMIO_CNTR_REG_OFFSET 0x40000 83 + #define MMIO_REG_END_OFFSET 0x80000 84 + 78 85 79 86 80 87 /* Extended Feature Bits */ ··· 508 507 509 508 /* physical address of MMIO space */ 510 509 u64 mmio_phys; 510 + 511 + /* physical end address of MMIO space */ 512 + u64 mmio_phys_end; 513 + 511 514 /* virtual address of MMIO space */ 512 515 u8 __iomem *mmio_base; 513 516 ··· 589 584 590 585 /* The l2 indirect registers */ 591 586 u32 stored_l2[0x83]; 587 + 588 + /* The maximum PC banks and counters/bank (PCSup=1) */ 589 + u8 max_banks; 590 + u8 max_counters; 592 591 }; 593 592 594 593 struct devid_map {