1 /* $NetBSD: tprof_x86.c,v 1.17 2023/04/12 02:15:51 msaitoh Exp $ */ 2 3 /* 4 * Copyright (c) 2018-2019 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Maxime Villard. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <stdbool.h> 36 #include <string.h> 37 #include <unistd.h> 38 #include <err.h> 39 #include <machine/specialreg.h> 40 #include <dev/tprof/tprof_ioctl.h> 41 #include "../tprof.h" 42 43 int tprof_event_init(uint32_t); 44 void tprof_event_list(void); 45 void tprof_event_lookup(const char *, struct tprof_param *); 46 47 struct name_to_event { 48 const char *name; 49 uint64_t event; 50 uint64_t unit; 51 bool enabled; 52 }; 53 54 struct event_table { 55 const char *tablename; 56 struct name_to_event *names; 57 size_t nevents; 58 struct event_table *next; 59 }; 60 61 static struct event_table *cpuevents = NULL; 62 63 static void 64 x86_cpuid(unsigned int *eax, unsigned int *ebx, 65 unsigned int *ecx, unsigned int *edx) 66 { 67 asm volatile("cpuid" 68 : "=a" (*eax), 69 "=b" (*ebx), 70 "=c" (*ecx), 71 "=d" (*edx) 72 : "0" (*eax), "2" (*ecx)); 73 } 74 75 /* ------------------------------------------------------------------------- */ 76 77 /* 78 * Intel Architectural Version 1. 79 */ 80 static struct name_to_event intel_arch1_names[] = { 81 /* Event Name - Event Select - UMask */ 82 { "unhalted-core-cycles", 0x3c, 0x00, true }, 83 { "instruction-retired", 0xc0, 0x00, true }, 84 { "unhalted-reference-cycles", 0x3c, 0x01, true }, 85 { "llc-reference", 0x2e, 0x4f, true }, 86 { "llc-misses", 0x2e, 0x41, true }, 87 { "branch-instruction-retired", 0xc4, 0x00, true }, 88 { "branch-misses-retired", 0xc5, 0x00, true }, 89 { "topdown-slots", 0xa4, 0x01, true }, 90 }; 91 92 static struct event_table intel_arch1 = { 93 .tablename = "Intel Architectural Version 1", 94 .names = intel_arch1_names, 95 .nevents = sizeof(intel_arch1_names) / 96 sizeof(struct name_to_event), 97 .next = NULL 98 }; 99 100 static struct event_table * 101 init_intel_arch1(void) 102 { 103 unsigned int eax, ebx, ecx, edx, vectorlen; 104 struct event_table *table; 105 size_t i; 106 107 eax = 0x0a; 108 ebx = 0; 109 ecx = 0; 110 edx = 0; 111 x86_cpuid(&eax, &ebx, &ecx, &edx); 112 113 vectorlen = __SHIFTOUT(eax, CPUID_PERF_BVECLEN); 114 115 table = &intel_arch1; 116 for (i = 0; i < table->nevents; i++) { 117 /* 118 * Disable the unsupported events from: 119 * a) the bit vector length in EAX. 120 * b) the disable bit in EBX. 121 */ 122 if (i >= vectorlen) 123 table->names[i].enabled = false; 124 if ((ebx & (i << 1)) != 0) 125 table->names[i].enabled = false; 126 } 127 128 return table; 129 } 130 131 /* 132 * Intel Silvermont/Airmont. 133 */ 134 static struct name_to_event intel_silvermont_airmont_names[] = { 135 { "REHABQ.LD_BLOCK_ST_FORWARD", 0x03, 0x01, true }, 136 { "REHABQ.LD_BLOCK_STD_NOTREADY", 0x03, 0x02, true }, 137 { "REHABQ.ST_SPLITS", 0x03, 0x04, true }, 138 { "REHABQ.LD_SPLITS", 0x03, 0x08, true }, 139 { "REHABQ.LOCK", 0x03, 0x10, true }, 140 { "REHABQ.STA_FULL", 0x03, 0x20, true }, 141 { "REHABQ.ANY_LD", 0x03, 0x40, true }, 142 { "REHABQ.ANY_ST", 0x03, 0x80, true }, 143 { "MEM_UOPS_RETIRED.L1_MISS_LOADS", 0x04, 0x01, true }, 144 { "MEM_UOPS_RETIRED.L2_HIT_LOADS", 0x04, 0x02, true }, 145 { "MEM_UOPS_RETIRED.L2_MISS_LOADS", 0x04, 0x04, true }, 146 { "MEM_UOPS_RETIRED.DTLB_MISS_LOADS", 0x04, 0x08, true }, 147 { "MEM_UOPS_RETIRED.UTLB_MISS", 0x04, 0x10, true }, 148 { "MEM_UOPS_RETIRED.HITM", 0x04, 0x20, true }, 149 { "MEM_UOPS_RETIRED.ALL_LOADS", 0x04, 0x40, true }, 150 { "MEM_UOP_RETIRED.ALL_STORES", 0x04, 0x80, true }, 151 { "PAGE_WALKS.D_SIDE_CYCLES", 0x05, 0x01, true }, 152 { "PAGE_WALKS.I_SIDE_CYCLES", 0x05, 0x02, true }, 153 { "PAGE_WALKS.WALKS", 0x05, 0x03, true }, 154 { "LONGEST_LAT_CACHE.MISS", 0x2e, 0x41, true }, 155 { "LONGEST_LAT_CACHE.REFERENCE", 0x2e, 0x4f, true }, 156 { "L2_REJECT_XQ.ALL", 0x30, 0x00, true }, 157 { "CORE_REJECT_L2Q.ALL", 0x31, 0x00, true }, 158 { "CPU_CLK_UNHALTED.CORE_P", 0x3c, 0x00, true }, 159 { "CPU_CLK_UNHALTED.REF_P", 0x3c, 0x01, true }, 160 { "ICACHE.HIT", 0x80, 0x01, true }, 161 { "ICACHE.MISSES", 0x80, 0x02, true }, 162 { "ICACHE.ACCESSES", 0x80, 0x03, true }, 163 { "OFFCORE_RESPONSE_0", 0xb7, 0x01, true }, 164 { "OFFCORE_RESPONSE_1", 0xb7, 0x02, true }, 165 { "INST_RETIRED.ANY_P", 0xc0, 0x00, true }, 166 { "UOPS_RETIRED.MS", 0xc2, 0x01, true }, 167 { "UOPS_RETIRED.ALL", 0xc2, 0x10, true }, 168 { "MACHINE_CLEARS.SMC", 0xc3, 0x01, true }, 169 { "MACHINE_CLEARS.MEMORY_ORDERING", 0xc3, 0x02, true }, 170 { "MACHINE_CLEARS.FP_ASSIST", 0xc3, 0x04, true }, 171 { "MACHINE_CLEARS.ALL", 0xc3, 0x08, true }, 172 { "BR_INST_RETIRED.ALL_BRANCHES", 0xc4, 0x00, true }, 173 { "BR_INST_RETIRED.JCC", 0xc4, 0x7e, true }, 174 { "BR_INST_RETIRED.FAR_BRANCH", 0xc4, 0xbf, true }, 175 { "BR_INST_RETIRED.NON_RETURN_IND", 0xc4, 0xeb, true }, 176 { "BR_INST_RETIRED.RETURN", 0xc4, 0xf7, true }, 177 { "BR_INST_RETIRED.CALL", 0xc4, 0xf9, true }, 178 { "BR_INST_RETIRED.IND_CALL", 0xc4, 0xfb, true }, 179 { "BR_INST_RETIRED.REL_CALL", 0xc4, 0xfd, true }, 180 { "BR_INST_RETIRED.TAKEN_JCC", 0xc4, 0xfe, true }, 181 { "BR_MISP_RETIRED.ALL_BRANCHES", 0xc5, 0x00, true }, 182 { "BR_MISP_RETIRED.JCC", 0xc5, 0x7e, true }, 183 { "BR_MISP_RETIRED.FAR", 0xc5, 0xbf, true }, 184 { "BR_MISP_RETIRED.NON_RETURN_IND", 0xc5, 0xeb, true }, 185 { "BR_MISP_RETIRED.RETURN", 0xc5, 0xf7, true }, 186 { "BR_MISP_RETIRED.CALL", 0xc5, 0xf9, true }, 187 { "BR_MISP_RETIRED.IND_CALL", 0xc5, 0xfb, true }, 188 { "BR_MISP_RETIRED.REL_CALL", 0xc5, 0xfd, true }, 189 { "BR_MISP_RETIRED.TAKEN_JCC", 0xc5, 0xfe, true }, 190 { "NO_ALLOC_CYCLES.ROB_FULL", 0xca, 0x01, true }, 191 { "NO_ALLOC_CYCLES.RAT_STALL", 0xca, 0x20, true }, 192 { "NO_ALLOC_CYCLES.ALL", 0xca, 0x3f, true }, 193 { "NO_ALLOC_CYCLES.NOT_DELIVERED", 0xca, 0x50, true }, 194 { "RS_FULL_STALL.MEC", 0xcb, 0x01, true }, 195 { "RS_FULL_STALL.ALL", 0xcb, 0x1f, true }, 196 { "CYCLES_DIV_BUSY.ANY", 0xcd, 0x01, true }, 197 { "BACLEARS.ALL", 0xe6, 0x01, true }, 198 { "BACLEARS.RETURN", 0xe6, 0x08, true }, 199 { "BACLEARS.COND", 0xe6, 0x10, true }, 200 { "MS_DECODED.MS_ENTRY", 0xe7, 0x01, true }, 201 }; 202 203 static struct event_table intel_silvermont_airmont = { 204 .tablename = "Intel Silvermont/Airmont", 205 .names = intel_silvermont_airmont_names, 206 .nevents = sizeof(intel_silvermont_airmont_names) / 207 sizeof(struct name_to_event), 208 .next = NULL 209 }; 210 211 static struct event_table * 212 init_intel_silvermont_airmont(void) 213 { 214 215 return &intel_silvermont_airmont; 216 } 217 218 /* 219 * Intel Goldmont 220 */ 221 static struct name_to_event intel_goldmont_names[] = { 222 { "LD_BLOCKS.ALL_BLOCK", 0x03, 0x10, true }, 223 { "LD_BLOCKS.UTLB_MISS", 0x03, 0x08, true }, 224 { "LD_BLOCKS.STORE_FORWARD", 0x03, 0x02, true }, 225 { "LD_BLOCKS.DATA_UNKNOWN", 0x03, 0x01, true }, 226 { "LD_BLOCKS.4K_ALIAS", 0x03, 0x04, true }, 227 { "PAGE_WALKS.D_SIDE_CYCLES", 0x05, 0x01, true }, 228 { "PAGE_WALKS.I_SIDE_CYCLES", 0x05, 0x02, true }, 229 { "PAGE_WALKS.CYCLES", 0x05, 0x03, true }, 230 { "UOPS_ISSUED.ANY", 0x0e, 0x00, true }, 231 { "MISALIGN_MEM_REF.LOAD_PAGE_SPLIT", 0x13, 0x02, true }, 232 { "MISALIGN_MEM_REF.STORE_PAGE_SPLIT", 0x13, 0x04, true }, 233 { "LONGEST_LAT_CACHE.REFERENCE", 0x2e, 0x4f, true }, 234 { "LONGEST_LAT_CACHE.MISS", 0x2e, 0x41, true }, 235 { "L2_REJECT_XQ.ALL", 0x30, 0x00, true }, 236 { "CORE_REJECT_L2Q.ALL", 0x31, 0x00, true }, 237 { "CPU_CLK_UNHALTED.CORE_P", 0x3c, 0x00, true }, 238 { "CPU_CLK_UNHALTED.REF", 0x3c, 0x01, true }, 239 { "DL1.DIRTY_EVICTION", 0x51, 0x01, true }, 240 { "ICACHE.HIT", 0x80, 0x01, true }, 241 { "ICACHE.MISSES", 0x80, 0x02, true }, 242 { "ICACHE.ACCESSES", 0x80, 0x03, true }, 243 { "ITLB.MISS", 0x81, 0x04, true }, 244 { "FETCH_STALL.ALL", 0x86, 0x00, true }, 245 { "FETCH_STALL.ITLB_FILL_PENDING_CYCLES", 0x86, 0x01, true }, 246 { "FETCH_STALL.ICACHE_FILL_PENDING_CYCLES", 0x86, 0x02, true }, 247 { "UOPS_NOT_DELIVERED.ANY", 0x9c, 0x00, true }, 248 { "OFFCORE_RESPONSE.0", 0xb7, 0x01, true }, 249 { "OFFCORE_RESPONSE.1", 0xb7, 0x02, true }, 250 { "INST_RETIRED.ANY_P", 0xc0, 0x00, true }, 251 { "UOPS_RETIRED.ANY", 0xc2, 0x00, true }, 252 { "UOPS_RETIRED.MS", 0xc2, 0x01, true }, 253 { "UOPS_RETIRED.FPDIV", 0xc2, 0x08, true }, 254 { "UOPS_RETIRED.IDIV", 0xc2, 0x10, true }, 255 { "MACHINE_CLEARS.SMC", 0xc3, 0x01, true }, 256 { "MACHINE_CLEARS.MEMORY_ORDERING", 0xc3, 0x02, true }, 257 { "MACHINE_CLEARS.FP_ASSIST", 0xc3, 0x04, true }, 258 { "MACHINE_CLEARS.DISAMBIGUATION", 0xc3, 0x08, true }, 259 { "MACHINE_CLEARS.ALL", 0xc3, 0x00, true }, 260 { "BR_INST_RETIRED.ALL_BRANCHES", 0xc4, 0x00, true }, 261 { "BR_INST_RETIRED.JCC", 0xc4, 0x7e, true }, 262 { "BR_INST_RETIRED.ALL_TAKEN_BRANCHES", 0xc4, 0x80, true }, 263 { "BR_INST_RETIRED.TAKEN_JCC", 0xc4, 0xfe, true }, 264 { "BR_INST_RETIRED.CALL", 0xc4, 0xf9, true }, 265 { "BR_INST_RETIRED.REL_CALL", 0xc4, 0xfd, true }, 266 { "BR_INST_RETIRED.IND_CALL", 0xc4, 0xfb, true }, 267 { "BR_INST_RETIRED.RETURN", 0xc4, 0xf7, true }, 268 { "BR_INST_RETIRED.NON_RETURN_IND", 0xc4, 0xeb, true }, 269 { "BR_INST_RETIRED.FAR_BRANCH", 0xc4, 0xbf, true }, 270 { "BR_MISP_RETIRED.ALL_BRANCHES", 0xc5, 0x00, true }, 271 { "BR_MISP_RETIRED.JCC", 0xc5, 0x7e, true }, 272 { "BR_MISP_RETIRED.TAKEN_JCC", 0xc5, 0xfe, true }, 273 { "BR_MISP_RETIRED.IND_CALL", 0xc5, 0xfb, true }, 274 { "BR_MISP_RETIRED.RETURN", 0xc5, 0xf7, true }, 275 { "BR_MISP_RETIRED.NON_RETURN_IND", 0xc5, 0xeb, true }, 276 { "ISSUE_SLOTS_NOT_CONSUMED.RESOURCE_FULL", 0xca, 0x01, true }, 277 { "ISSUE_SLOTS_NOT_CONSUMED.RECOVERY", 0xca, 0x02, true }, 278 { "ISSUE_SLOTS_NOT_CONSUMED.ANY", 0xca, 0x00, true }, 279 { "HW_INTERRUPTS.RECEIVED", 0xcb, 0x01, true }, 280 { "HW_INTERRUPTS.MASKED", 0xcb, 0x02, true }, 281 { "HW_INTERRUPTS.PENDING_AND_MASKED", 0xcb, 0x04, true }, 282 { "CYCLES_DIV_BUSY.ALL", 0xcd, 0x00, true }, 283 { "CYCLES_DIV_BUSY.IDIV", 0xcd, 0x01, true }, 284 { "CYCLES_DIV_BUSY.FPDIV", 0xcd, 0x02, true }, 285 { "MEM_UOPS_RETIRED.ALL_LOADS", 0xd0, 0x81, true }, 286 { "MEM_UOPS_RETIRED.ALL_STORES", 0xd0, 0x82, true }, 287 { "MEM_UOPS_RETIRED.ALL", 0xd0, 0x83, true }, 288 { "MEM_UOPS_RETIRED.DTLB_MISS_LOADS", 0xd0, 0x11, true }, 289 { "MEM_UOPS_RETIRED.DTLB_MISS_STORES", 0xd0, 0x12, true }, 290 { "MEM_UOPS_RETIRED.DTLB_MISS", 0xd0, 0x13, true }, 291 { "MEM_UOPS_RETIRED.LOCK_LOADS", 0xd0, 0x21, true }, 292 { "MEM_UOPS_RETIRED.SPLIT_LOADS", 0xd0, 0x41, true }, 293 { "MEM_UOPS_RETIRED.SPLIT_STORES", 0xd0, 0x42, true }, 294 { "MEM_UOPS_RETIRED.SPLIT", 0xd0, 0x43, true }, 295 { "MEM_LOAD_UOPS_RETIRED.L1_HIT", 0xd1, 0x01, true }, 296 { "MEM_LOAD_UOPS_RETIRED.L1_MISS", 0xd1, 0x08, true }, 297 { "MEM_LOAD_UOPS_RETIRED.L2_HIT", 0xd1, 0x02, true }, 298 { "MEM_LOAD_UOPS_RETIRED.L2_MISS", 0xd1, 0x10, true }, 299 { "MEM_LOAD_UOPS_RETIRED.HITM", 0xd1, 0x20, true }, 300 { "MEM_LOAD_UOPS_RETIRED.WCB_HIT", 0xd1, 0x40, true }, 301 { "MEM_LOAD_UOPS_RETIRED.DRAM_HIT", 0xd1, 0x80, true }, 302 { "BACLEARS.ALL", 0xe6, 0x01, true }, 303 { "BACLEARS.RETURN", 0xe6, 0x08, true }, 304 { "BACLEAR.CONDS", 0xe6, 0x10, true }, 305 { "MS_DECODED.MS_ENTRY", 0xe7, 0x01, true }, 306 { "DECODED_RESTRICTION.PREDECODE_WRONG", 0xe9, 0x01, true }, 307 }; 308 309 static struct event_table intel_goldmont = { 310 .tablename = "Intel Goldmont", 311 .names = intel_goldmont_names, 312 .nevents = sizeof(intel_goldmont_names) / 313 sizeof(struct name_to_event), 314 .next = NULL 315 }; 316 317 static struct event_table * 318 init_intel_goldmont(void) 319 { 320 321 return &intel_goldmont; 322 } 323 324 /* 325 * Intel Goldmont Plus (Additions from Goldmont) 326 */ 327 static struct name_to_event intel_goldmontplus_names[] = { 328 { "INST_RETIRED.ANY", 0x00, 0x01, true }, 329 { "DTLB_LOAD_MISSES.WALK_COMPLETED_4K", 0x08, 0x02, true }, 330 { "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M", 0x08, 0x04, true }, 331 { "DTLB_LOAD_MISSES.WALK_COMPLETED_1GB", 0x08, 0x08, true }, 332 { "DTLB_LOAD_MISSES.WALK_PENDING", 0x08, 0x10, true }, 333 { "DTLB_STORE_MISSES.WALK_COMPLETED_4K", 0x49, 0x02, true }, 334 { "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M", 0x49, 0x04, true }, 335 { "DTLB_STORE_MISSES.WALK_COMPLETED_1GB", 0x49, 0x08, true }, 336 { "DTLB_STORE_MISSES.WALK_PENDING", 0x49, 0x10, true }, 337 { "EPT.WALK_PENDING", 0x4f, 0x10, true }, 338 { "ITLB_MISSES.WALK_COMPLETED_4K", 0x85, 0x08, true }, 339 { "ITLB_MISSES.WALK_COMPLETED_2M_4M", 0x85, 0x04, true }, 340 { "ITLB_MISSES.WALK_COMPLETED_1GB", 0x85, 0x08, true }, 341 { "ITLB_MISSES.WALK_PENDING", 0x85, 0x10, true }, 342 { "TLB_FLUSHES.STLB_ANY", 0xbd, 0x20, true }, 343 { "MACHINE_CLEARS.PAGE_FAULT", 0xc3, 0x20, true }, 344 }; 345 346 static struct event_table intel_goldmontplus = { 347 .tablename = "Intel Goldmont Plus", 348 .names = intel_goldmontplus_names, 349 .nevents = sizeof(intel_goldmontplus_names) / 350 sizeof(struct name_to_event), 351 .next = NULL 352 }; 353 354 static struct event_table * 355 init_intel_goldmontplus(void) 356 { 357 358 intel_goldmont.next = &intel_goldmontplus; 359 360 return &intel_goldmont; 361 } 362 363 /* 364 * Intel Skylake/Kabylake. 365 * 366 * The events that are not listed, because they are of little interest or 367 * require extra configuration: 368 * TX_* 369 * FRONTEND_RETIRED.* 370 * FP_ARITH_INST_RETIRED.* 371 * HLE_RETIRED.* 372 * RTM_RETIRED.* 373 * MEM_TRANS_RETIRED.* 374 * UOPS_DISPATCHED_PORT.* 375 */ 376 static struct name_to_event intel_skylake_kabylake_names[] = { 377 /* Event Name - Event Select - UMask */ 378 { "LD_BLOCKS.STORE_FORWARD", 0x03, 0x02, true }, 379 { "LD_BLOCKS.NO_SR", 0x03, 0x08, true }, 380 { "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS", 0x07, 0x01, true }, 381 { "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK", 0x08, 0x01, true }, 382 { "DTLB_LOAD_MISSES.WALK_COMPLETED_4K", 0x08, 0x02, true }, 383 { "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M", 0x08, 0x04, true }, 384 { "DTLB_LOAD_MISSES.WALK_COMPLETED_1G", 0x08, 0x08, true }, 385 { "DTLB_LOAD_MISSES.WALK_COMPLETED", 0x08, 0x0e, true }, 386 { "DTLB_LOAD_MISSES.WALK_PENDING", 0x08, 0x10, true }, 387 { "DTLB_LOAD_MISSES.STLB_HIT", 0x08, 0x20, true }, 388 { "INT_MISC.RECOVERY_CYCLES", 0x0d, 0x01, true }, 389 { "INT_MISC.CLEAR_RESTEER_CYCLES", 0x0d, 0x80, true }, 390 { "UOPS_ISSUED.ANY", 0x0e, 0x01, true }, 391 { "UOPS_ISSUED.VECTOR_WIDTH_MISMATCH", 0x0e, 0x02, true }, 392 { "UOPS_ISSUED.SLOW_LEA", 0x0e, 0x20, true }, 393 { "L2_RQSTS.DEMAND_DATA_RD_MISS", 0x24, 0x21, true }, 394 { "L2_RQSTS.RFO_MISS", 0x24, 0x22, true }, 395 { "L2_RQSTS.CODE_RD_MISS", 0x24, 0x24, true }, 396 { "L2_RQSTS.ALL_DEMAND_MISS", 0x24, 0x27, true }, 397 { "L2_RQSTS.PF_MISS", 0x24, 0x38, true }, 398 { "L2_RQSTS.MISS", 0x24, 0x3f, true }, 399 { "L2_RQSTS.DEMAND_DATA_RD_HIT", 0x24, 0x41, true }, 400 { "L2_RQSTS.RFO_HIT", 0x24, 0x42, true }, 401 { "L2_RQSTS.CODE_RD_HIT", 0x24, 0x44, true }, 402 { "L2_RQSTS.PF_HIT", 0x24, 0xd8, true }, 403 { "L2_RQSTS.ALL_DEMAND_DATA_RD", 0x24, 0xe1, true }, 404 { "L2_RQSTS.ALL_RFO", 0x24, 0xe2, true }, 405 { "L2_RQSTS.ALL_CODE_RD", 0x24, 0xe4, true }, 406 { "L2_RQSTS.ALL_DEMAND_REFERENCES", 0x24, 0xe7, true }, 407 { "L2_RQSTS.ALL_PF", 0x24, 0xf8, true }, 408 { "L2_RQSTS.REFERENCES", 0x24, 0xff, true }, 409 { "SW_PREFETCH_ACCESS.NTA", 0x32, 0x01, true }, 410 { "SW_PREFETCH_ACCESS.T0", 0x32, 0x02, true }, 411 { "SW_PREFETCH_ACCESS.T1_T2", 0x32, 0x04, true }, 412 { "SW_PREFETCH_ACCESS.PREFETCHW", 0x32, 0x08, true }, 413 { "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE", 0x3c, 0x02, true }, 414 { "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE", 0x3c, 0x02, true }, 415 { "L1D_PEND_MISS.PENDING", 0x48, 0x01, true }, 416 { "L1D_PEND_MISS.FB_FULL", 0x48, 0x02, true }, 417 { "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK", 0x49, 0x01, true }, 418 { "DTLB_STORE_MISSES.WALK_COMPLETED_4K", 0x49, 0x02, true }, 419 { "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M", 0x49, 0x04, true }, 420 { "DTLB_STORE_MISSES.WALK_COMPLETED_1G", 0x49, 0x08, true }, 421 { "DTLB_STORE_MISSES.WALK_COMPLETED", 0x49, 0x0e, true }, 422 { "DTLB_STORE_MISSES.WALK_PENDING", 0x49, 0x10, true }, 423 { "DTLB_STORE_MISSES.STLB_HIT", 0x49, 0x20, true }, 424 { "LOAD_HIT_PRE.SW_PF", 0x4c, 0x01, true }, 425 { "EPT.WALK_PENDING", 0x4f, 0x10, true }, 426 { "L1D.REPLACEMENT", 0x51, 0x01, true }, 427 { "RS_EVENTS.EMPTY_CYCLES", 0x5e, 0x01, true }, 428 { "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD", 0x60, 0x01, true }, 429 { "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD", 0x60, 0x02, true }, 430 { "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO", 0x60, 0x04, true }, 431 { "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD", 0x60, 0x08, true }, 432 { "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD", 433 0x60, 0x10, true }, 434 { "IDQ.MITE_UOPS", 0x79, 0x04, true }, 435 { "IDQ.DSB_UOPS", 0x79, 0x08, true }, 436 { "IDQ.MS_MITE_UOPS", 0x79, 0x20, true }, 437 { "IDQ.MS_UOPS", 0x79, 0x30, true }, 438 { "ICACHE_16B.IFDATA_STALL", 0x80, 0x04, true }, 439 { "ICACHE_64B.IFTAG_HIT", 0x83, 0x01, true }, 440 { "ICACHE_64B.IFTAG_MISS", 0x83, 0x02, true }, 441 { "ICACHE_64B.IFTAG_STALL", 0x83, 0x04, true }, 442 { "ITLB_MISSES.MISS_CAUSES_A_WALK", 0x85, 0x01, true }, 443 { "ITLB_MISSES.WALK_COMPLETED_4K", 0x85, 0x02, true }, 444 { "ITLB_MISSES.WALK_COMPLETED_2M_4M", 0x85, 0x04, true }, 445 { "ITLB_MISSES.WALK_COMPLETED_1G", 0x85, 0x08, true }, 446 { "ITLB_MISSES.WALK_COMPLETED", 0x85, 0x0e, true }, 447 { "ITLB_MISSES.WALK_PENDING", 0x85, 0x10, true }, 448 { "ITLB_MISSES.STLB_HIT", 0x85, 0x20, true }, 449 { "ILD_STALL.LCP", 0x87, 0x01, true }, 450 { "IDQ_UOPS_NOT_DELIVERED.CORE", 0x9c, 0x01, true }, 451 { "RESOURCE_STALLS.ANY", 0xa2, 0x01, true }, 452 { "RESOURCE_STALLS.SB", 0xa2, 0x08, true }, 453 { "EXE_ACTIVITY.EXE_BOUND_0_PORTS", 0xa6, 0x01, true }, 454 { "EXE_ACTIVITY.1_PORTS_UTIL", 0xa6, 0x02, true }, 455 { "EXE_ACTIVITY.2_PORTS_UTIL", 0xa6, 0x04, true }, 456 { "EXE_ACTIVITY.3_PORTS_UTIL", 0xa6, 0x08, true }, 457 { "EXE_ACTIVITY.4_PORTS_UTIL", 0xa6, 0x10, true }, 458 { "EXE_ACTIVITY.BOUND_ON_STORES", 0xa6, 0x40, true }, 459 { "LSD.UOPS", 0xa8, 0x01, true }, 460 { "DSB2MITE_SWITCHES.PENALTY_CYCLES", 0xab, 0x02, true }, 461 { "ITLB.ITLB_FLUSH", 0xae, 0x01, true }, 462 { "OFFCORE_REQUESTS.DEMAND_DATA_RD", 0xb0, 0x01, true }, 463 { "OFFCORE_REQUESTS.DEMAND_CODE_RD", 0xb0, 0x02, true }, 464 { "OFFCORE_REQUESTS.DEMAND_RFO", 0xb0, 0x04, true }, 465 { "OFFCORE_REQUESTS.ALL_DATA_RD", 0xb0, 0x08, true }, 466 { "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD", 0xb0, 0x10, true }, 467 { "OFFCORE_REQUESTS.ALL_REQUESTS", 0xb0, 0x80, true }, 468 { "UOPS_EXECUTED.THREAD", 0xb1, 0x01, true }, 469 { "UOPS_EXECUTED.CORE", 0xb1, 0x02, true }, 470 { "UOPS_EXECUTED.X87", 0xb1, 0x10, true }, 471 { "OFFCORE_REQUESTS_BUFFER.SQ_FULL", 0xb2, 0x01, true }, 472 { "TLB_FLUSH.DTLB_THREAD", 0xbd, 0x01, true }, 473 { "TLB_FLUSH.STLB_ANY", 0xbd, 0x20, true }, 474 { "INST_RETIRED.PREC_DIST", 0xc0, 0x01, true }, 475 { "OTHER_ASSISTS.ANY", 0xc1, 0x3f, true }, 476 { "UOPS_RETIRED.RETIRE_SLOTS", 0xc2, 0x02, true }, 477 { "MACHINE_CLEARS.MEMORY_ORDERING", 0xc3, 0x02, true }, 478 { "MACHINE_CLEARS.SMC", 0xc3, 0x04, true }, 479 { "BR_INST_RETIRED.CONDITIONAL", 0xc4, 0x01, true }, 480 { "BR_INST_RETIRED.NEAR_CALL", 0xc4, 0x02, true }, 481 { "BR_INST_RETIRED.NEAR_RETURN", 0xc4, 0x08, true }, 482 { "BR_INST_RETIRED.NOT_TAKEN", 0xc4, 0x10, true }, 483 { "BR_INST_RETIRED.NEAR_TAKEN", 0xc4, 0x20, true }, 484 { "BR_INST_RETIRED.FAR_BRANCH", 0xc4, 0x40, true }, 485 { "BR_MISP_RETIRED.CONDITIONAL", 0xc5, 0x01, true }, 486 { "BR_MISP_RETIRED.NEAR_CALL", 0xc5, 0x02, true }, 487 { "BR_MISP_RETIRED.NEAR_TAKEN", 0xc5, 0x20, true }, 488 { "HW_INTERRUPTS.RECEIVED", 0xcb, 0x01, true }, 489 { "MEM_INST_RETIRED.STLB_MISS_LOADS", 0xd0, 0x11, true }, 490 { "MEM_INST_RETIRED.STLB_MISS_STORES", 0xd0, 0x12, true }, 491 { "MEM_INST_RETIRED.LOCK_LOADS", 0xd0, 0x21, true }, 492 { "MEM_INST_RETIRED.SPLIT_LOADS", 0xd0, 0x41, true }, 493 { "MEM_INST_RETIRED.SPLIT_STORES", 0xd0, 0x42, true }, 494 { "MEM_INST_RETIRED.ALL_LOADS", 0xd0, 0x81, true }, 495 { "MEM_INST_RETIRED.ALL_STORES", 0xd0, 0x82, true }, 496 { "MEM_LOAD_RETIRED.L1_HIT", 0xd1, 0x01, true }, 497 { "MEM_LOAD_RETIRED.L2_HIT", 0xd1, 0x02, true }, 498 { "MEM_LOAD_RETIRED.L3_HIT", 0xd1, 0x04, true }, 499 { "MEM_LOAD_RETIRED.L1_MISS", 0xd1, 0x08, true }, 500 { "MEM_LOAD_RETIRED.L2_MISS", 0xd1, 0x10, true }, 501 { "MEM_LOAD_RETIRED.L3_MISS", 0xd1, 0x20, true }, 502 { "MEM_LOAD_RETIRED.FB_HIT", 0xd1, 0x40, true }, 503 { "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS", 0xd2, 0x01, true }, 504 { "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT", 0xd2, 0x02, true }, 505 { "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM", 0xd2, 0x04, true }, 506 { "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE", 0xd2, 0x08, true }, 507 { "MEM_LOAD_MISC_RETIRED.UC", 0xd4, 0x04, true }, 508 { "BACLEARS.ANY", 0xe6, 0x01, true }, 509 { "L2_TRANS.L2_WB", 0xf0, 0x40, true }, 510 { "L2_LINES_IN.ALL", 0xf1, 0x1f, true }, 511 { "L2_LINES_OUT.SILENT", 0xf2, 0x01, true }, 512 { "L2_LINES_OUT.NON_SILENT", 0xf2, 0x02, true }, 513 { "L2_LINES_OUT.USELESS_HWPF", 0xf2, 0x04, true }, 514 { "SQ_MISC.SPLIT_LOCK", 0xf4, 0x10, true }, 515 }; 516 517 static struct event_table intel_skylake_kabylake = { 518 .tablename = "Intel Skylake/Kabylake", 519 .names = intel_skylake_kabylake_names, 520 .nevents = sizeof(intel_skylake_kabylake_names) / 521 sizeof(struct name_to_event), 522 .next = NULL 523 }; 524 525 static struct event_table * 526 init_intel_skylake_kabylake(void) 527 { 528 529 return &intel_skylake_kabylake; 530 } 531 532 static struct event_table * 533 init_intel_generic(void) 534 { 535 unsigned int eax, ebx, ecx, edx; 536 struct event_table *table; 537 538 /* 539 * The kernel made sure the Architectural Version 1 PMCs were 540 * present. 541 */ 542 table = init_intel_arch1(); 543 544 /* 545 * Now query the additional (non-architectural) events. They 546 * depend on the CPU model. 547 */ 548 eax = 0x01; 549 ebx = 0; 550 ecx = 0; 551 edx = 0; 552 x86_cpuid(&eax, &ebx, &ecx, &edx); 553 554 if (CPUID_TO_FAMILY(eax) == 6) { 555 switch (CPUID_TO_MODEL(eax)) { 556 case 0x37: /* Silvermont (Bay Trail) */ 557 case 0x4a: /* Silvermont (Tangier) */ 558 case 0x4c: /* Airmont (Braswell, Cherry Trail) */ 559 case 0x4d: /* Silvermont (Avoton, Rangeley) */ 560 case 0x5a: /* Silvermont (Anniedale) */ 561 case 0x5d: /* Silvermont (SoFIA) */ 562 table->next = init_intel_silvermont_airmont(); 563 break; 564 case 0x5c: /* Goldmont (Apollo Lake) */ 565 case 0x5f: /* Goldmont (Denverton) */ 566 table->next = init_intel_goldmont(); 567 break; 568 case 0x7a: /* Goldmont Plus (Gemini Lake) */ 569 table->next = init_intel_goldmontplus(); 570 break; 571 case 0x4e: /* Skylake */ 572 case 0x5e: /* Skylake */ 573 case 0x8e: /* Kabylake */ 574 case 0x9e: /* Kabylake */ 575 case 0xa5: /* Cometlake */ 576 case 0xa6: /* Cometlake */ 577 table->next = init_intel_skylake_kabylake(); 578 break; 579 } 580 } 581 582 return table; 583 } 584 585 /* ------------------------------------------------------------------------- */ 586 587 /* 588 * AMD Family 10h 589 */ 590 static struct name_to_event amd_f10h_names[] = { 591 { "seg-load-all", 0x20, 0x7f, true }, 592 { "seg-load-es", 0x20, 0x01, true }, 593 { "seg-load-cs", 0x20, 0x02, true }, 594 { "seg-load-ss", 0x20, 0x04, true }, 595 { "seg-load-ds", 0x20, 0x08, true }, 596 { "seg-load-fs", 0x20, 0x10, true }, 597 { "seg-load-gs", 0x20, 0x20, true }, 598 { "seg-load-hs", 0x20, 0x40, true }, 599 { "l1cache-access", 0x40, 0x00, true }, 600 { "l1cache-miss", 0x41, 0x00, true }, 601 { "l1cache-refill", 0x42, 0x1f, true }, 602 { "l1cache-refill-invalid", 0x42, 0x01, true }, 603 { "l1cache-refill-shared", 0x42, 0x02, true }, 604 { "l1cache-refill-exclusive", 0x42, 0x04, true }, 605 { "l1cache-refill-owner", 0x42, 0x08, true }, 606 { "l1cache-refill-modified", 0x42, 0x10, true }, 607 { "l1cache-load", 0x43, 0x1f, true }, 608 { "l1cache-load-invalid", 0x43, 0x01, true }, 609 { "l1cache-load-shared", 0x43, 0x02, true }, 610 { "l1cache-load-exclusive", 0x43, 0x04, true }, 611 { "l1cache-load-owner", 0x43, 0x08, true }, 612 { "l1cache-load-modified", 0x43, 0x10, true }, 613 { "l1cache-writeback", 0x44, 0x1f, true }, 614 { "l1cache-writeback-invalid", 0x44, 0x01, true }, 615 { "l1cache-writeback-shared", 0x44, 0x02, true }, 616 { "l1cache-writeback-exclusive",0x44, 0x04, true }, 617 { "l1cache-writeback-owner", 0x44, 0x08, true }, 618 { "l1cache-writeback-modified", 0x44, 0x10, true }, 619 { "l1DTLB-hit-all", 0x4d, 0x07, true }, 620 { "l1DTLB-hit-4Kpage", 0x4d, 0x01, true }, 621 { "l1DTLB-hit-2Mpage", 0x4d, 0x02, true }, 622 { "l1DTLB-hit-1Gpage", 0x4d, 0x04, true }, 623 { "l1DTLB-miss-all", 0x45, 0x07, true }, 624 { "l1DTLB-miss-4Kpage", 0x45, 0x01, true }, 625 { "l1DTLB-miss-2Mpage", 0x45, 0x02, true }, 626 { "l1DTLB-miss-1Gpage", 0x45, 0x04, true }, 627 { "l2DTLB-miss-all", 0x46, 0x03, true }, 628 { "l2DTLB-miss-4Kpage", 0x46, 0x01, true }, 629 { "l2DTLB-miss-2Mpage", 0x46, 0x02, true }, 630 /* l2DTLB-miss-1Gpage: reserved on some revisions, so disabled */ 631 { "l1ITLB-miss", 0x84, 0x00, true }, 632 { "l2ITLB-miss-all", 0x85, 0x03, true }, 633 { "l2ITLB-miss-4Kpage", 0x85, 0x01, true }, 634 { "l2ITLB-miss-2Mpage", 0x85, 0x02, true }, 635 { "mem-misalign-ref", 0x47, 0x00, true }, 636 { "ins-fetch", 0x80, 0x00, true }, 637 { "ins-fetch-miss", 0x81, 0x00, true }, 638 { "ins-refill-l2", 0x82, 0x00, true }, 639 { "ins-refill-sys", 0x83, 0x00, true }, 640 { "ins-fetch-stall", 0x87, 0x00, true }, 641 { "ins-retired", 0xc0, 0x00, true }, 642 { "ins-empty", 0xd0, 0x00, true }, 643 { "ops-retired", 0xc1, 0x00, true }, 644 { "branch-retired", 0xc2, 0x00, true }, 645 { "branch-miss-retired", 0xc3, 0x00, true }, 646 { "branch-taken-retired", 0xc4, 0x00, true }, 647 { "branch-taken-miss-retired", 0xc5, 0x00, true }, 648 { "branch-far-retired", 0xc6, 0x00, true }, 649 { "branch-resync-retired", 0xc7, 0x00, true }, 650 { "branch-near-retired", 0xc8, 0x00, true }, 651 { "branch-near-miss-retired", 0xc9, 0x00, true }, 652 { "branch-indirect-miss-retired", 0xca, 0x00, true }, 653 { "int-hw", 0xcf, 0x00, true }, 654 { "int-cycles-masked", 0xcd, 0x00, true }, 655 { "int-cycles-masked-pending", 0xce, 0x00, true }, 656 { "fpu-exceptions", 0xdb, 0x00, true }, 657 { "break-match0", 0xdc, 0x00, true }, 658 { "break-match1", 0xdd, 0x00, true }, 659 { "break-match2", 0xde, 0x00, true }, 660 { "break-match3", 0xdf, 0x00, true }, 661 }; 662 663 static struct event_table amd_f10h = { 664 .tablename = "AMD Family 10h", 665 .names = amd_f10h_names, 666 .nevents = sizeof(amd_f10h_names) / 667 sizeof(struct name_to_event), 668 .next = NULL 669 }; 670 671 /* 672 * AMD Family 15h 673 */ 674 static struct name_to_event amd_f15h_names[] = { 675 { "FpPipeAssignment", 0x000, 0x77, true }, 676 { "FpSchedulerEmpty", 0x001, 0x00, true }, 677 { "FpRetSseAvxOps", 0x003, 0xff, true }, 678 { "FpNumMovElim", 0x004, 0x0f, true }, 679 { "FpRetiredSerOps", 0x005, 0x0f, true }, 680 { "LsSegRegLoads", 0x020, 0x7f, true }, 681 { "LsPipeRestartSelfMod", 0x021, 0x00, true }, 682 { "LsPipeRestartVarious", 0x022, 0x1f, true }, 683 { "LsLoadQueueStoreQFull", 0x023, 0x03, true }, 684 { "LsLockedOps", 0x024, 0x00, true }, 685 { "LsRetClflushInstr", 0x026, 0x00, true }, 686 { "LsRetCpuidInstr", 0x027, 0x00, true }, 687 { "LsDispatch", 0x029, 0x07, true }, 688 { "LsCanStoreToLoadFwOps", 0x02a, 0x03, true }, 689 { "LsSmisReceived", 0x02b, 0x00, true }, 690 { "LsExecClflushInstr", 0x030, 0x00, true }, 691 { "LsMisalignStore", 0x032, 0x00, true }, 692 { "LsFpLoadBufStall", 0x034, 0x00, true }, 693 { "LsStlf", 0x035, 0x00, true }, 694 { "DcCacheAccess", 0x040, 0x00, true }, 695 { "DcCacheMiss", 0x041, 0x00, true }, 696 { "DcCacheFillL2Sys", 0x042, 0x1f, true }, 697 { "DcCacheFillSys", 0x043, 0x00, true }, 698 { "DcUnifiedTlbHit", 0x045, 0x77, true }, 699 { "DcUnifiedTlbMiss", 0x046, 0x77, true }, 700 { "DcMisalignAccess", 0x047, 0x00, true }, 701 { "DcPrefetchInstrDisp", 0x04b, 0x07, true }, 702 { "DcIneffSwPrefetch", 0x052, 0x09, true }, 703 { "CuCmdVictimBuf", 0x060, 0x98, true }, 704 { "CuCmdMaskedOps", 0x061, 0x65, true }, 705 { "CuCmdReadBlkOps", 0x062, 0x77, true }, 706 { "CuCmdChgDirtyOps", 0x063, 0x08, true }, 707 { "CuDramSysReq", 0x064, 0x00, true }, 708 { "CuMemReqByType", 0x065, 0x83, true }, 709 { "CuDataCachePrefetch", 0x067, 0x03, true }, 710 { "CuMabReq", 0x068, 0xff, true }, 711 { "CuMabWaitCyc", 0x069, 0xff, true }, 712 { "CuSysRespCacheFill", 0x06c, 0x3f, true }, 713 { "CuOctwordsWritten", 0x06d, 0x01, true }, 714 { "CuCacheXInv", 0x075, 0x0f, true }, 715 { "CuCpuClkNotHalted", 0x076, 0x00, true }, 716 { "CuL2Req", 0x07d, 0x5f, true }, 717 { "CuL2Miss", 0x07e, 0x17, true }, 718 { "CuL2FillWb", 0x07f, 0x07, true }, 719 { "CuPageSplintering", 0x165, 0x07, true }, 720 { "CuL2PrefetchTrigEv", 0x16c, 0x03, true }, 721 { "CuXabAllocStall", 0x177, 0x03, true }, 722 { "CuFreeXabEntries", 0x17f, 0x01, true }, 723 { "IcCacheFetch", 0x080, 0x00, true }, 724 { "IcCacheMiss", 0x081, 0x00, true }, 725 { "IcCacheFillL2", 0x082, 0x00, true }, 726 { "IcCacheFillSys", 0x083, 0x00, true }, 727 { "IcL1TlbMissL2Hit", 0x084, 0x00, true }, 728 { "IcL1TlbMissL2Miss", 0x085, 0x07, true }, 729 { "IcPipeRestartInstrStrProbe", 0x086, 0x00, true }, 730 { "IcFetchStall", 0x087, 0x00, true }, 731 { "IcRetStackHits", 0x088, 0x00, true }, 732 { "IcRetStackOver", 0x089, 0x00, true }, 733 { "IcCacheVictims", 0x08b, 0x00, true }, 734 { "IcCacheLinesInv", 0x08c, 0x0f, true }, 735 { "IcTlbReload", 0x099, 0x00, true }, 736 { "IcTlbReloadAbort", 0x09a, 0x00, true }, 737 { "IcUopsDispatched", 0x186, 0x01, true }, 738 { "ExRetInstr", 0x0c0, 0x00, true }, 739 { "ExRetCops", 0x0c1, 0x00, true }, 740 { "ExRetBrn", 0x0c2, 0x00, true }, 741 { "ExRetBrnMisp", 0x0c3, 0x00, true }, 742 { "ExRetBrnTkn", 0x0c4, 0x00, true }, 743 { "ExRetBrnTknMisp", 0x0c5, 0x00, true }, 744 { "ExRetBrnFar", 0x0c6, 0x00, true }, 745 { "ExRetBrnResync", 0x0c7, 0x00, true }, 746 { "ExRetNearRet", 0x0c8, 0x00, true }, 747 { "ExRetNearRetMispred", 0x0c9, 0x00, true }, 748 { "ExRetBrnIndMisp", 0x0ca, 0x00, true }, 749 { "ExRetMmxFpInstr@X87", 0x0cb, 0x01, true }, 750 { "ExRetMmxFpInstr@Mmx", 0x0cb, 0x02, true }, 751 { "ExRetMmxFpInstr@Sse", 0x0cb, 0x04, true }, 752 { "ExIntMaskedCyc", 0x0cd, 0x00, true }, 753 { "ExIntMaskedCycIntPend", 0x0ce, 0x00, true }, 754 { "ExIntTaken", 0x0cf, 0x00, true }, 755 { "ExDecEmpty", 0x0d0, 0x00, true }, 756 { "ExDispStall", 0x0d1, 0x00, true }, 757 { "ExUseqStallSer", 0x0d2, 0x00, true }, 758 { "ExDispStallInstrRetQFull", 0x0d5, 0x00, true }, 759 { "ExDispStallIntSchedQFull", 0x0d6, 0x00, true }, 760 { "ExDispStallFpSchedQFull", 0x0d7, 0x00, true }, 761 { "ExDispStallLdqFull", 0x0d8, 0x00, true }, 762 { "ExUseqStallAllQuiet", 0x0d9, 0x00, true }, 763 { "ExFpuEx", 0x0db, 0x1f, true }, 764 { "ExBpDr0", 0x0dc, 0x8f, true }, 765 { "ExBpDr1", 0x0dd, 0x8f, true }, 766 { "ExBpDr2", 0x0de, 0x8f, true }, 767 { "ExBpDr3", 0x0df, 0x8f, true }, 768 { "ExRetx87FpOps", 0x1c0, 0x07, true }, 769 { "ExTaggedIbsOps", 0x1cf, 0x07, true }, 770 { "ExRetFusBrInstr", 0x1d0, 0x00, true }, 771 { "ExDispStallStqFull", 0x1d8, 0x00, true }, 772 { "ExCycNoDispIntPrfTok", 0x1dd, 0x00, true }, 773 { "ExCycNoDispfpPrfTok", 0x1de, 0x00, true }, 774 { "ExFpDispContention", 0x1df, 0x0f, true }, 775 }; 776 777 static struct event_table amd_f15h = { 778 .tablename = "AMD Family 15h", 779 .names = amd_f15h_names, 780 .nevents = sizeof(amd_f15h_names) / 781 sizeof(struct name_to_event), 782 .next = NULL 783 }; 784 785 /* 786 * AMD Family 17h 787 */ 788 static struct name_to_event amd_f17h_names[] = { 789 { "FpRetx87FpOps", 0x02, __BITS(2,0), true }, 790 { "FpRetSseAvxOps", 0x03, __BITS(7,0), true }, 791 { "FpRetiredSerOps", 0x05, __BITS(3,0), true }, 792 { "LsL1DTlbMiss", 0x45, __BITS(7,0), true }, 793 { "LsTableWalker", 0x46, __BITS(3,0), true }, 794 { "LsMisalAccesses", 0x47, 0x00, true }, 795 { "LsInefSwPref", 0x52, __BITS(1,0), true }, 796 { "LsNotHaltedCyc", 0x76, 0x00, true }, 797 { "IcFw32", 0x80, 0x00, true }, 798 { "IcFw32Miss", 0x81, 0x00, true }, 799 { "IcCacheFillL2", 0x82, 0x00, true }, 800 { "IcCacheFillSys", 0x83, 0x00, true }, 801 { "IcFetchStall", 0x87, __BITS(2,0), true }, 802 { "IcCacheInval", 0x8c, __BITS(1,0), true }, 803 { "BpL1TlbMissL2Hit", 0x84, 0x00, true }, 804 { "BpL1TlbMissL2Miss", 0x85, 0x00, true }, 805 { "BpSnpReSync", 0x86, 0x00, true }, 806 { "BpL1BTBCorrect", 0x8a, 0x00, true }, 807 { "BpL2BTBCorrect", 0x8b, 0x00, true }, 808 { "BpTlbRel", 0x99, 0x00, true }, 809 { "ExRetInstr", 0xc0, 0x00, true }, 810 { "ExRetCops", 0xc1, 0x00, true }, 811 { "ExRetBrn", 0xc2, 0x00, true }, 812 { "ExRetBrnMisp", 0xc3, 0x00, true }, 813 { "ExRetBrnTkn", 0xc4, 0x00, true }, 814 { "ExRetBrnTknMisp", 0xc5, 0x00, true }, 815 { "ExRetBrnFar", 0xc6, 0x00, true }, 816 { "ExRetBrnResync", 0xc7, 0x00, true }, 817 { "ExRetBrnIndMisp", 0xca, 0x00, true }, 818 { "ExRetNearRet", 0xc8, 0x00, true }, 819 { "ExRetNearRetMispred", 0xc9, 0x00, true }, 820 { "ExRetMmxFpInstr@X87", 0xcb, __BIT(0), true }, 821 { "ExRetMmxFpInstr@Mmx", 0xcb, __BIT(1), true }, 822 { "ExRetMmxFpInstr@Sse", 0xcb, __BIT(2), true }, 823 { "ExRetCond", 0xd1, 0x00, true }, 824 { "ExRetCondMisp", 0xd2, 0x00, true }, 825 { "ExDivBusy", 0xd3, 0x00, true }, 826 { "ExDivCount", 0xd4, 0x00, true }, 827 }; 828 829 static struct event_table amd_f17h = { 830 .tablename = "AMD Family 17h", 831 .names = amd_f17h_names, 832 .nevents = sizeof(amd_f17h_names) / 833 sizeof(struct name_to_event), 834 .next = NULL 835 }; 836 837 /* 838 * AMD Family 19h 839 * From PPR: 840 * - f19h model 01h B1 (zen3) 841 * - f19h model 11h B1 (zen4) 842 * - f19h model 21h B1 (zen3) 843 * - f19h model 51h A1 (zen3) 844 */ 845 static struct name_to_event amd_f19h_names[] = { 846 /* Model 1x only */ 847 { "FpRetx87FpOps", 0x02, __BITS(2,0), true }, 848 849 /* Only model 1x has bit 4 */ 850 { "FpRetSseAvxOps", 0x03, __BITS(4,0), true }, 851 852 { "FpRetiredSerOps", 0x05, __BITS(3,0), true }, 853 854 /* Model 1x only */ 855 { "FpOpsRetiredByWidth", 0x08, __BITS(5,0), true }, 856 { "FpOpsRetiredByType", 0x0a, __BITS(7,0), true }, 857 { "SseAvxOpsRetired", 0x0b, __BITS(7,0), true }, 858 { "FpPackOpsRetired", 0x0c, __BITS(7,0), true }, 859 { "PackedIntOpType", 0x0d, __BITS(7,0), true }, 860 861 { "FpDispFaults", 0x0e, __BITS(3,0), true }, 862 { "LsBadStatus2", 0x24, __BIT(1), true }, 863 { "LsLocks", 0x25, __BIT(0), true }, 864 { "LsRetClClush", 0x26, 0x00, true }, 865 { "LsRetCpuid", 0x27, 0x00, true }, 866 { "LsDispatch", 0x29, __BITS(2,0), true }, 867 { "LsSmiRx", 0x2b, 0x00, true }, 868 { "LsIntTaken", 0x2c, 0x00, true }, 869 { "LsSTLF", 0x35, 0x00, true }, 870 { "LsStCommitCancel2", 0x37, __BIT(0), true }, 871 { "LsMabAlloc-ls", 0x41, 0x3f, true }, 872 { "LsMabAlloc-hp", 0x41, 0x40, true }, 873 { "LsMabAlloc-all", 0x41, 0x7f, true }, 874 { "LsDmndFillsFromSys", 0x43, 0x5f, true }, 875 876 /* Only model 1x has bit 7 */ 877 { "LsAnyFillsFromSys", 0x44, 0xdf, true }, 878 879 { "LsL1DTlbMiss", 0x45, __BITS(7,0), true }, 880 { "LsMisalLoads-MA64", 0x47, __BIT(0), true }, 881 { "LsMisalLoads-MA4K", 0x47, __BIT(1), true }, 882 { "LsMisalLoads-all", 0x47, __BITS(1,0), true }, 883 { "LsPrefInstrDisp", 0x4b, __BITS(2,0), true }, 884 { "LsInefSwPref", 0x52, __BITS(1,0), true }, 885 886 /* Only model 1x has bit 7 */ 887 { "LsSwPfDcFills", 0x59, 0xdf, true }, 888 { "LsHwPfDcFills", 0x5a, 0xdf, true }, 889 890 { "LsAllocMabCount", 0x5f, 0x00, true }, 891 { "LsNotHaltedCyc", 0x76, 0x00, true }, 892 893 /* Model 0x, 1x and 2x only */ 894 { "LsTlbFlush", 0x78, 0xff, true }, 895 896 /* Model 1x only */ 897 { "LsNotHaltedP0Cyc", 0x120, __BIT(0), true }, 898 899 { "IcCacheFillL2", 0x82, 0x00, true }, 900 { "IcCacheFillSys", 0x83, 0x00, true }, 901 { "BpL1TlbMissL2TlbHit", 0x84, 0x00, true }, 902 { "BpL1TlbMissL2TlbMiss-IF4K", 0x85, __BIT(0), true }, 903 { "BpL1TlbMissL2TlbMiss-IF2M", 0x85, __BIT(1), true }, 904 { "BpL1TlbMissL2TlbMiss-IF1G", 0x85, __BIT(2), true }, 905 { "BpL1TlbMissL2TlbMiss-Coalesced4K", 0x85, __BIT(3), true }, 906 { "BpL1TlbMissL2TlbMiss-all", 0x85, __BITS(3,0), true }, 907 908 { "BpL2BTBCorrect", 0x8b, 0x00, true }, 909 { "BpDynIndPred", 0x8e, 0x00, true }, 910 { "BpDeReDirect", 0x91, 0x00, true }, 911 { "BpL1TlbFetchHit-IF4K", 0x94, __BIT(0), true }, 912 { "BpL1TlbFetchHit-IF2M", 0x94, __BIT(1), true }, 913 { "BpL1TlbFetchHit-IF1G", 0x94, __BIT(2), true }, 914 { "BpL1TlbFetchHit-all", 0x94, __BITS(2,0), true }, 915 916 /* Model 1x only */ 917 { "ResyncsOrNcRedirects", 0x96, 0x00, true }, 918 919 { "IcTagHitMiss-hit", 0x18e, 0x07, true }, 920 { "IcTagHitMiss-miss", 0x18e, 0x18, true }, 921 { "IcTagHitMiss-all", 0x18e, 0x1f, true }, 922 { "OpCacheHitMiss-hit", 0x28f, 0x03, true }, 923 { "OpCacheHitMiss-miss", 0x28f, 0x04, true }, 924 { "OpCacheHitMiss-all", 0x28f, 0x07, true }, 925 { "DeOpQueueEmpty", 0xa9, 0x00, true }, 926 927 /* 928 * Model 0x and 1x only. 929 * Only model 1x has bit 2. 930 */ 931 { "DeSrcOpDisp", 0xaa, __BITS(2,0), true }, 932 933 { "DeDisOpsFromDecoder-Fp-Ibs", 0xab, 0x04, true }, 934 { "DeDisOpsFromDecoder-Int-Ibs", 0xab, 0x08, true }, 935 936 /* Model 0x, 2x and newer */ 937 { "DeDisOpsFromDecoder-Fp-Ret", 0xab, 0x84, true }, 938 { "DeDisOpsFromDecoder-Int-Ret", 0xab, 0x88, true }, 939 940 { "DeDisDispatchTokenStalls1", 0xae, 0xf7, true }, 941 { "DeDisDispatchTokenStalls2", 0xaf, 0x2f, true }, 942 943 /* Model 1x only */ 944 { "DeNoDispatchPerSolt-empty", 0x1a0, 0x01, true }, 945 { "DeNoDispatchPerSolt-backend", 0x1a0, 0x1e, true }, 946 { "DeNoDispatchPerSolt-otherSMT", 0x1a0, 0x60, true }, 947 { "DeAdditionalResourceStalls", 0x1a2, 0x30, true }, 948 949 { "ExRetInstr", 0xc0, 0x00, true }, 950 { "ExRetCops", 0xc1, 0x00, true }, 951 { "ExRetBrn", 0xc2, 0x00, true }, 952 { "ExRetBrnMisp", 0xc3, 0x00, true }, 953 { "ExRetBrnTkn", 0xc4, 0x00, true }, 954 { "ExRetBrnTknMisp", 0xc5, 0x00, true }, 955 { "ExRetBrnFar", 0xc6, 0x00, true }, 956 { "ExRetBrnIndMisp", 0xca, 0x00, true }, 957 { "ExRetNearRet", 0xc8, 0x00, true }, 958 { "ExRetNearRetMispred", 0xc9, 0x00, true }, 959 { "ExRetMmxFpInstr@X87", 0xcb, __BIT(0), true }, 960 { "ExRetMmxFpInstr@Mmx", 0xcb, __BIT(1), true }, 961 { "ExRetMmxFpInstr@Sse", 0xcb, __BIT(2), true }, 962 { "ExRetIndBrchInstr", 0xcc, 0x00, true }, 963 { "ExRetCond", 0xd1, 0x00, true }, 964 { "ExDivBusy", 0xd3, 0x00, true }, 965 { "ExDivCount", 0xd4, 0x00, true }, 966 967 /* Model 1x only */ 968 { "ExDivCount-LoadAndALU", 0xd6, 0x1f, true }, 969 { "ExDivCount-Load", 0xd6, 0xbf, true }, 970 { "ExRetUcodeInstr", 0x1c1, 0x00, true }, 971 { "ExRetUcodeOps", 0x1c2, 0x00, true }, 972 973 { "ExRetMsprdBrnchInstrDirMsmtch", 0x1c7, 0x00, true }, 974 975 /* Model 1x only */ 976 { "ExRetUncondBrnchInstrMspred", 0x1c8, 0x00, true }, 977 { "ExRetUncondBrnchInstr", 0x1c8, 0x00, true }, 978 979 { "ExTaggedIbsOps", 0x1cf, __BITS(2,0), true }, 980 { "ExRetFusedInstr", 0x1d0, 0x00, true }, 981 982 /* Only model 1x has bit 0 */ 983 { "L2RequestG1", 0x60, __BITS(7,1), true }, 984 985 { "L2CacheReqStart", 0x64, __BITS(7,0), true }, 986 { "L2PfHitL2-L2", 0x70, __BITS(4,0), true }, 987 { "L2PfHitL2-L1", 0x70, __BITS(7,5), true }, 988 { "L2PfHitL2-all", 0x70, __BITS(7,0), true }, 989 { "L2PfMissL2HitL3-L2", 0x71, __BITS(4,0), true }, 990 { "L2PfMissL2HitL3-L1", 0x71, __BITS(7,5), true }, 991 { "L2PfMIssL2HitL3-all", 0x71, __BITS(7,0), true }, 992 { "L2PfMissL2L3-L2", 0x72, __BITS(4,0), true }, 993 { "L2PfMissL2L3-L1", 0x72, __BITS(7,5), true }, 994 { "L2PfMIssL2L3-all", 0x72, __BITS(7,0), true }, 995 996 { "L3LookupState-L3Miss", 0x04, __BIT(0), true }, 997 { "L3LookupState-L3Hit", 0x04, __BITS(7,1), true }, 998 { "L3LookupState-all", 0x04, __BITS(7,0), true }, 999 1000 /* Model 0x, 2x and newer */ 1001 { "XiSysFillLatency", 0x90, 0x00, true }, 1002 { "XiCcxSdpReq1", 0x9a, 0x00, true }, 1003 1004 /* Model 1x only */ 1005 { "XiSampledLatency", 0xac, 0x00, true }, 1006 { "XiSampledLatencyRequests", 0xad, 0x00, true }, 1007 }; 1008 1009 static struct event_table amd_f19h = { 1010 .tablename = "AMD Family 19h", 1011 .names = amd_f19h_names, 1012 .nevents = sizeof(amd_f19h_names) / 1013 sizeof(struct name_to_event), 1014 .next = NULL 1015 }; 1016 1017 static struct event_table * 1018 init_amd_generic(void) 1019 { 1020 unsigned int eax, ebx, ecx, edx; 1021 1022 eax = 0x01; 1023 ebx = 0; 1024 ecx = 0; 1025 edx = 0; 1026 x86_cpuid(&eax, &ebx, &ecx, &edx); 1027 1028 switch (CPUID_TO_FAMILY(eax)) { 1029 case 0x10: 1030 return &amd_f10h; 1031 case 0x15: 1032 return &amd_f15h; 1033 case 0x17: 1034 return &amd_f17h; 1035 case 0x19: 1036 return &amd_f19h; 1037 } 1038 1039 return NULL; 1040 } 1041 1042 /* ------------------------------------------------------------------------- */ 1043 1044 int 1045 tprof_event_init(uint32_t ident) 1046 { 1047 1048 switch (ident) { 1049 case TPROF_IDENT_NONE: 1050 return -1; 1051 case TPROF_IDENT_INTEL_GENERIC: 1052 cpuevents = init_intel_generic(); 1053 break; 1054 case TPROF_IDENT_AMD_GENERIC: 1055 cpuevents = init_amd_generic(); 1056 break; 1057 } 1058 return (cpuevents == NULL) ? -1 : 0; 1059 } 1060 1061 static void 1062 recursive_event_list(struct event_table *table) 1063 { 1064 size_t i; 1065 1066 printf("%s:\n", table->tablename); 1067 for (i = 0; i < table->nevents; i++) { 1068 if (!table->names[i].enabled) 1069 continue; 1070 printf("\t%s\n", table->names[i].name); 1071 } 1072 1073 if (table->next != NULL) 1074 recursive_event_list(table->next); 1075 } 1076 1077 void 1078 tprof_event_list(void) 1079 { 1080 1081 recursive_event_list(cpuevents); 1082 } 1083 1084 static void 1085 recursive_event_lookup(struct event_table *table, const char *name, 1086 struct tprof_param *param) 1087 { 1088 size_t i; 1089 1090 for (i = 0; i < table->nevents; i++) { 1091 if (!table->names[i].enabled) 1092 continue; 1093 if (!strcmp(table->names[i].name, name)) { 1094 param->p_event = table->names[i].event; 1095 param->p_unit = table->names[i].unit; 1096 return; 1097 } 1098 } 1099 1100 if (table->next != NULL) 1101 recursive_event_lookup(table->next, name, param); 1102 else 1103 errx(EXIT_FAILURE, "event '%s' unknown", name); 1104 } 1105 1106 void 1107 tprof_event_lookup(const char *name, struct tprof_param *param) 1108 { 1109 1110 recursive_event_lookup(cpuevents, name, param); 1111 } 1112