1 /* $NetBSD: tprof_x86.c,v 1.11 2022/06/13 07:40:58 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 x86_cpuid(unsigned int *eax, unsigned int *ebx, 64 unsigned int *ecx, unsigned int *edx) 65 { 66 asm volatile("cpuid" 67 : "=a" (*eax), 68 "=b" (*ebx), 69 "=c" (*ecx), 70 "=d" (*edx) 71 : "0" (*eax), "2" (*ecx)); 72 } 73 74 /* -------------------------------------------------------------------------- */ 75 76 /* 77 * Intel Architectural Version 1. 78 */ 79 static struct name_to_event intel_arch1_names[] = { 80 /* Event Name - Event Select - UMask */ 81 { "unhalted-core-cycles", 0x3C, 0x00, true }, 82 { "instruction-retired", 0xC0, 0x00, true }, 83 { "unhalted-reference-cycles", 0x3C, 0x01, true }, 84 { "llc-reference", 0x2E, 0x4F, true }, 85 { "llc-misses", 0x2E, 0x41, true }, 86 { "branch-instruction-retired", 0xC4, 0x00, true }, 87 { "branch-misses-retired", 0xC5, 0x00, true }, 88 { "topdown-slots", 0xA4, 0x01, true }, 89 }; 90 91 static struct event_table intel_arch1 = { 92 .tablename = "Intel Architectural Version 1", 93 .names = intel_arch1_names, 94 .nevents = sizeof(intel_arch1_names) / 95 sizeof(struct name_to_event), 96 .next = NULL 97 }; 98 99 static struct event_table * 100 init_intel_arch1(void) 101 { 102 unsigned int eax, ebx, ecx, edx; 103 struct event_table *table; 104 size_t i; 105 106 eax = 0x0A; 107 ebx = 0; 108 ecx = 0; 109 edx = 0; 110 x86_cpuid(&eax, &ebx, &ecx, &edx); 111 112 table = &intel_arch1; 113 for (i = 0; i < table->nevents; i++) { 114 /* Disable the unsupported events. */ 115 if ((ebx & (i << 1)) != 0) 116 table->names[i].enabled = false; 117 } 118 119 return table; 120 } 121 122 /* 123 * Intel Silvermont/Airmont. 124 */ 125 static struct name_to_event intel_silvermont_airmont_names[] = { 126 { "REHABQ.LD_BLOCK_ST_FORWARD", 0x03, 0x01, true }, 127 { "REHABQ.LD_BLOCK_STD_NOTREADY", 0x03, 0x02, true }, 128 { "REHABQ.ST_SPLITS", 0x03, 0x04, true }, 129 { "REHABQ.LD_SPLITS", 0x03, 0x08, true }, 130 { "REHABQ.LOCK", 0x03, 0x10, true }, 131 { "REHABQ.STA_FULL", 0x03, 0x20, true }, 132 { "REHABQ.ANY_LD", 0x03, 0x40, true }, 133 { "REHABQ.ANY_ST", 0x03, 0x80, true }, 134 { "MEM_UOPS_RETIRED.L1_MISS_LOADS", 0x04, 0x01, true }, 135 { "MEM_UOPS_RETIRED.L2_HIT_LOADS", 0x04, 0x02, true }, 136 { "MEM_UOPS_RETIRED.L2_MISS_LOADS", 0x04, 0x04, true }, 137 { "MEM_UOPS_RETIRED.DTLB_MISS_LOADS", 0x04, 0x08, true }, 138 { "MEM_UOPS_RETIRED.UTLB_MISS", 0x04, 0x10, true }, 139 { "MEM_UOPS_RETIRED.HITM", 0x04, 0x20, true }, 140 { "MEM_UOPS_RETIRED.ALL_LOADS", 0x04, 0x40, true }, 141 { "MEM_UOP_RETIRED.ALL_STORES", 0x04, 0x80, true }, 142 { "PAGE_WALKS.D_SIDE_CYCLES", 0x05, 0x01, true }, 143 { "PAGE_WALKS.I_SIDE_CYCLES", 0x05, 0x02, true }, 144 { "PAGE_WALKS.WALKS", 0x05, 0x03, true }, 145 { "LONGEST_LAT_CACHE.MISS", 0x2E, 0x41, true }, 146 { "LONGEST_LAT_CACHE.REFERENCE", 0x2E, 0x4F, true }, 147 { "L2_REJECT_XQ.ALL", 0x30, 0x00, true }, 148 { "CORE_REJECT_L2Q.ALL", 0x31, 0x00, true }, 149 { "CPU_CLK_UNHALTED.CORE_P", 0x3C, 0x00, true }, 150 { "CPU_CLK_UNHALTED.REF_P", 0x3C, 0x01, true }, 151 { "ICACHE.HIT", 0x80, 0x01, true }, 152 { "ICACHE.MISSES", 0x80, 0x02, true }, 153 { "ICACHE.ACCESSES", 0x80, 0x03, true }, 154 { "OFFCORE_RESPONSE_0", 0xB7, 0x01, true }, 155 { "OFFCORE_RESPONSE_1", 0xB7, 0x02, true }, 156 { "INST_RETIRED.ANY_P", 0xC0, 0x00, true }, 157 { "UOPS_RETIRED.MS", 0xC2, 0x01, true }, 158 { "UOPS_RETIRED.ALL", 0xC2, 0x10, true }, 159 { "MACHINE_CLEARS.SMC", 0xC3, 0x01, true }, 160 { "MACHINE_CLEARS.MEMORY_ORDERING", 0xC3, 0x02, true }, 161 { "MACHINE_CLEARS.FP_ASSIST", 0xC3, 0x04, true }, 162 { "MACHINE_CLEARS.ALL", 0xC3, 0x08, true }, 163 { "BR_INST_RETIRED.ALL_BRANCHES", 0xC4, 0x00, true }, 164 { "BR_INST_RETIRED.JCC", 0xC4, 0x7E, true }, 165 { "BR_INST_RETIRED.FAR_BRANCH", 0xC4, 0xBF, true }, 166 { "BR_INST_RETIRED.NON_RETURN_IND", 0xC4, 0xEB, true }, 167 { "BR_INST_RETIRED.RETURN", 0xC4, 0xF7, true }, 168 { "BR_INST_RETIRED.CALL", 0xC4, 0xF9, true }, 169 { "BR_INST_RETIRED.IND_CALL", 0xC4, 0xFB, true }, 170 { "BR_INST_RETIRED.REL_CALL", 0xC4, 0xFD, true }, 171 { "BR_INST_RETIRED.TAKEN_JCC", 0xC4, 0xFE, true }, 172 { "BR_MISP_RETIRED.ALL_BRANCHES", 0xC5, 0x00, true }, 173 { "BR_MISP_RETIRED.JCC", 0xC5, 0x7E, true }, 174 { "BR_MISP_RETIRED.FAR", 0xC5, 0xBF, true }, 175 { "BR_MISP_RETIRED.NON_RETURN_IND", 0xC5, 0xEB, true }, 176 { "BR_MISP_RETIRED.RETURN", 0xC5, 0xF7, true }, 177 { "BR_MISP_RETIRED.CALL", 0xC5, 0xF9, true }, 178 { "BR_MISP_RETIRED.IND_CALL", 0xC5, 0xFB, true }, 179 { "BR_MISP_RETIRED.REL_CALL", 0xC5, 0xFD, true }, 180 { "BR_MISP_RETIRED.TAKEN_JCC", 0xC5, 0xFE, true }, 181 { "NO_ALLOC_CYCLES.ROB_FULL", 0xCA, 0x01, true }, 182 { "NO_ALLOC_CYCLES.RAT_STALL", 0xCA, 0x20, true }, 183 { "NO_ALLOC_CYCLES.ALL", 0xCA, 0x3F, true }, 184 { "NO_ALLOC_CYCLES.NOT_DELIVERED", 0xCA, 0x50, true }, 185 { "RS_FULL_STALL.MEC", 0xCB, 0x01, true }, 186 { "RS_FULL_STALL.ALL", 0xCB, 0x1F, true }, 187 { "CYCLES_DIV_BUSY.ANY", 0xCD, 0x01, true }, 188 { "BACLEARS.ALL", 0xE6, 0x01, true }, 189 { "BACLEARS.RETURN", 0xE6, 0x08, true }, 190 { "BACLEARS.COND", 0xE6, 0x10, true }, 191 { "MS_DECODED.MS_ENTRY", 0xE7, 0x01, true }, 192 }; 193 194 static struct event_table intel_silvermont_airmont = { 195 .tablename = "Intel Silvermont/Airmont", 196 .names = intel_silvermont_airmont_names, 197 .nevents = sizeof(intel_silvermont_airmont_names) / 198 sizeof(struct name_to_event), 199 .next = NULL 200 }; 201 202 static struct event_table * 203 init_intel_silvermont_airmont(void) 204 { 205 206 return &intel_silvermont_airmont; 207 } 208 209 /* 210 * Intel Goldmont 211 */ 212 static struct name_to_event intel_goldmont_names[] = { 213 { "LD_BLOCKS.ALL_BLOCK", 0x03, 0x10, true }, 214 { "LD_BLOCKS.UTLB_MISS", 0x03, 0x08, true }, 215 { "LD_BLOCKS.STORE_FORWARD", 0x03, 0x02, true }, 216 { "LD_BLOCKS.DATA_UNKNOWN", 0x03, 0x01, true }, 217 { "LD_BLOCKS.4K_ALIAS", 0x03, 0x04, true }, 218 { "PAGE_WALKS.D_SIDE_CYCLES", 0x05, 0x01, true }, 219 { "PAGE_WALKS.I_SIDE_CYCLES", 0x05, 0x02, true }, 220 { "PAGE_WALKS.CYCLES", 0x05, 0x03, true }, 221 { "UOPS_ISSUED.ANY", 0x0E, 0x00, true }, 222 { "MISALIGN_MEM_REF.LOAD_PAGE_SPLIT", 0x13, 0x02, true }, 223 { "MISALIGN_MEM_REF.STORE_PAGE_SPLIT", 0x13, 0x04, true }, 224 { "LONGEST_LAT_CACHE.REFERENCE", 0x2E, 0x4F, true }, 225 { "LONGEST_LAT_CACHE.MISS", 0x2E, 0x41, true }, 226 { "L2_REJECT_XQ.ALL", 0x30, 0x00, true }, 227 { "CORE_REJECT_L2Q.ALL", 0x31, 0x00, true }, 228 { "CPU_CLK_UNHALTED.CORE_P", 0x3C, 0x00, true }, 229 { "CPU_CLK_UNHALTED.REF", 0x3C, 0x01, true }, 230 { "DL1.DIRTY_EVICTION", 0x51, 0x01, true }, 231 { "ICACHE.HIT", 0x80, 0x01, true }, 232 { "ICACHE.MISSES", 0x80, 0x02, true }, 233 { "ICACHE.ACCESSES", 0x80, 0x03, true }, 234 { "ITLB.MISS", 0x81, 0x04, true }, 235 { "FETCH_STALL.ALL", 0x86, 0x00, true }, 236 { "FETCH_STALL.ITLB_FILL_PENDING_CYCLES", 0x86, 0x01, true }, 237 { "FETCH_STALL.ICACHE_FILL_PENDING_CYCLES", 0x86, 0x02, true }, 238 { "UOPS_NOT_DELIVERED.ANY", 0x9C, 0x00, true }, 239 { "OFFCORE_RESPONSE.0", 0xB7, 0x01, true }, 240 { "OFFCORE_RESPONSE.1", 0xB7, 0x02, true }, 241 { "INST_RETIRED.ANY_P", 0xC0, 0x00, true }, 242 { "UOPS_RETIRED.ANY", 0xC2, 0x00, true }, 243 { "UOPS_RETIRED.MS", 0xC2, 0x01, true }, 244 { "UOPS_RETIRED.FPDIV", 0xC2, 0x08, true }, 245 { "UOPS_RETIRED.IDIV", 0xC2, 0x10, true }, 246 { "MACHINE_CLEARS.SMC", 0xC3, 0x01, true }, 247 { "MACHINE_CLEARS.MEMORY_ORDERING", 0xC3, 0x02, true }, 248 { "MACHINE_CLEARS.FP_ASSIST", 0xC3, 0x04, true }, 249 { "MACHINE_CLEARS.DISAMBIGUATION", 0xC3, 0x08, true }, 250 { "MACHINE_CLEARS.ALL", 0xC3, 0x00, true }, 251 { "BR_INST_RETIRED.ALL_BRANCHES", 0xC4, 0x00, true }, 252 { "BR_INST_RETIRED.JCC", 0xC4, 0x7E, true }, 253 { "BR_INST_RETIRED.ALL_TAKEN_BRANCHES", 0xC4, 0x80, true }, 254 { "BR_INST_RETIRED.TAKEN_JCC", 0xC4, 0xFE, true }, 255 { "BR_INST_RETIRED.CALL", 0xC4, 0xF9, true }, 256 { "BR_INST_RETIRED.REL_CALL", 0xC4, 0xFD, true }, 257 { "BR_INST_RETIRED.IND_CALL", 0xC4, 0xFB, true }, 258 { "BR_INST_RETIRED.RETURN", 0xC4, 0xF7, true }, 259 { "BR_INST_RETIRED.NON_RETURN_IND", 0xC4, 0xEB, true }, 260 { "BR_INST_RETIRED.FAR_BRANCH", 0xC4, 0xBF, true }, 261 { "BR_MISP_RETIRED.ALL_BRANCHES", 0xC5, 0x00, true }, 262 { "BR_MISP_RETIRED.JCC", 0xC5, 0x7E, true }, 263 { "BR_MISP_RETIRED.TAKEN_JCC", 0xC5, 0xFE, true }, 264 { "BR_MISP_RETIRED.IND_CALL", 0xC5, 0xFB, true }, 265 { "BR_MISP_RETIRED.RETURN", 0xC5, 0xF7, true }, 266 { "BR_MISP_RETIRED.NON_RETURN_IND", 0xC5, 0xEB, true }, 267 { "ISSUE_SLOTS_NOT_CONSUMED.RESOURCE_FULL", 0xCA, 0x01, true }, 268 { "ISSUE_SLOTS_NOT_CONSUMED.RECOVERY", 0xCA, 0x02, true }, 269 { "ISSUE_SLOTS_NOT_CONSUMED.ANY", 0xCA, 0x00, true }, 270 { "HW_INTERRUPTS.RECEIVED", 0xCB, 0x01, true }, 271 { "HW_INTERRUPTS.MASKED", 0xCB, 0x02, true }, 272 { "HW_INTERRUPTS.PENDING_AND_MASKED", 0xCB, 0x04, true }, 273 { "CYCLES_DIV_BUSY.ALL", 0xCD, 0x00, true }, 274 { "CYCLES_DIV_BUSY.IDIV", 0xCD, 0x01, true }, 275 { "CYCLES_DIV_BUSY.FPDIV", 0xCD, 0x02, true }, 276 { "MEM_UOPS_RETIRED.ALL_LOADS", 0xD0, 0x81, true }, 277 { "MEM_UOPS_RETIRED.ALL_STORES", 0xD0, 0x82, true }, 278 { "MEM_UOPS_RETIRED.ALL", 0xD0, 0x83, true }, 279 { "MEM_UOPS_RETIRED.DTLB_MISS_LOADS", 0xD0, 0x11, true }, 280 { "MEM_UOPS_RETIRED.DTLB_MISS_STORES", 0xD0, 0x12, true }, 281 { "MEM_UOPS_RETIRED.DTLB_MISS", 0xD0, 0x13, true }, 282 { "MEM_UOPS_RETIRED.LOCK_LOADS", 0xD0, 0x21, true }, 283 { "MEM_UOPS_RETIRED.SPLIT_LOADS", 0xD0, 0x41, true }, 284 { "MEM_UOPS_RETIRED.SPLIT_STORES", 0xD0, 0x42, true }, 285 { "MEM_UOPS_RETIRED.SPLIT", 0xD0, 0x43, true }, 286 { "MEM_LOAD_UOPS_RETIRED.L1_HIT", 0xD1, 0x01, true }, 287 { "MEM_LOAD_UOPS_RETIRED.L1_MISS", 0xD1, 0x08, true }, 288 { "MEM_LOAD_UOPS_RETIRED.L2_HIT", 0xD1, 0x02, true }, 289 { "MEM_LOAD_UOPS_RETIRED.L2_MISS", 0xD1, 0x10, true }, 290 { "MEM_LOAD_UOPS_RETIRED.HITM", 0xD1, 0x20, true }, 291 { "MEM_LOAD_UOPS_RETIRED.WCB_HIT", 0xD1, 0x40, true }, 292 { "MEM_LOAD_UOPS_RETIRED.DRAM_HIT", 0xD1, 0x80, true }, 293 { "BACLEARS.ALL", 0xE6, 0x01, true }, 294 { "BACLEARS.RETURN", 0xE6, 0x08, true }, 295 { "BACLEAR.CONDS", 0xE6, 0x10, true }, 296 { "MS_DECODED.MS_ENTRY", 0xE7, 0x01, true }, 297 { "DECODED_RESTRICTION.PREDECODE_WRONG", 0xE9, 0x01, true }, 298 }; 299 300 static struct event_table intel_goldmont = { 301 .tablename = "Intel Goldmont", 302 .names = intel_goldmont_names, 303 .nevents = sizeof(intel_goldmont_names) / 304 sizeof(struct name_to_event), 305 .next = NULL 306 }; 307 308 static struct event_table * 309 init_intel_goldmont(void) 310 { 311 312 return &intel_goldmont; 313 } 314 315 /* 316 * Intel Goldmont Plus (Additions from Goldmont) 317 */ 318 static struct name_to_event intel_goldmontplus_names[] = { 319 { "INST_RETIRED.ANY", 0x00, 0x01, true }, 320 { "DTLB_LOAD_MISSES.WALK_COMPLETED_4K", 0x08, 0x02, true }, 321 { "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M", 0x08, 0x04, true }, 322 { "DTLB_LOAD_MISSES.WALK_COMPLETED_1GB", 0x08, 0x08, true }, 323 { "DTLB_LOAD_MISSES.WALK_PENDING", 0x08, 0x10, true }, 324 { "DTLB_STORE_MISSES.WALK_COMPLETED_4K", 0x49, 0x02, true }, 325 { "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M", 0x49, 0x04, true }, 326 { "DTLB_STORE_MISSES.WALK_COMPLETED_1GB", 0x49, 0x08, true }, 327 { "DTLB_STORE_MISSES.WALK_PENDING", 0x49, 0x10, true }, 328 { "EPT.WALK_PENDING", 0x4F, 0x10, true }, 329 { "ITLB_MISSES.WALK_COMPLETED_4K", 0x85, 0x08, true }, 330 { "ITLB_MISSES.WALK_COMPLETED_2M_4M", 0x85, 0x04, true }, 331 { "ITLB_MISSES.WALK_COMPLETED_1GB", 0x85, 0x08, true }, 332 { "ITLB_MISSES.WALK_PENDING", 0x85, 0x10, true }, 333 { "TLB_FLUSHES.STLB_ANY", 0xBD, 0x20, true }, 334 { "MACHINE_CLEARS.PAGE_FAULT", 0xC3, 0x20, true }, 335 }; 336 337 static struct event_table intel_goldmontplus = { 338 .tablename = "Intel Goldmont Plus", 339 .names = intel_goldmontplus_names, 340 .nevents = sizeof(intel_goldmontplus_names) / 341 sizeof(struct name_to_event), 342 .next = NULL 343 }; 344 345 static struct event_table * 346 init_intel_goldmontplus(void) 347 { 348 349 intel_goldmont.next = &intel_goldmontplus; 350 351 return &intel_goldmont; 352 } 353 354 /* 355 * Intel Skylake/Kabylake. 356 * 357 * The events that are not listed, because they are of little interest or 358 * require extra configuration: 359 * TX_* 360 * FRONTEND_RETIRED.* 361 * FP_ARITH_INST_RETIRED.* 362 * HLE_RETIRED.* 363 * RTM_RETIRED.* 364 * MEM_TRANS_RETIRED.* 365 * UOPS_DISPATCHED_PORT.* 366 */ 367 static struct name_to_event intel_skylake_kabylake_names[] = { 368 /* Event Name - Event Select - UMask */ 369 { "LD_BLOCKS.STORE_FORWARD", 0x03, 0x02, true }, 370 { "LD_BLOCKS.NO_SR", 0x03, 0x08, true }, 371 { "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS", 0x07, 0x01, true }, 372 { "DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK", 0x08, 0x01, true }, 373 { "DTLB_LOAD_MISSES.WALK_COMPLETED_4K", 0x08, 0x02, true }, 374 { "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M", 0x08, 0x04, true }, 375 { "DTLB_LOAD_MISSES.WALK_COMPLETED_1G", 0x08, 0x08, true }, 376 { "DTLB_LOAD_MISSES.WALK_COMPLETED", 0x08, 0x0E, true }, 377 { "DTLB_LOAD_MISSES.WALK_PENDING", 0x08, 0x10, true }, 378 { "DTLB_LOAD_MISSES.STLB_HIT", 0x08, 0x20, true }, 379 { "INT_MISC.RECOVERY_CYCLES", 0x0D, 0x01, true }, 380 { "INT_MISC.CLEAR_RESTEER_CYCLES", 0x0D, 0x80, true }, 381 { "UOPS_ISSUED.ANY", 0x0E, 0x01, true }, 382 { "UOPS_ISSUED.VECTOR_WIDTH_MISMATCH", 0x0E, 0x02, true }, 383 { "UOPS_ISSUED.SLOW_LEA", 0x0E, 0x20, true }, 384 { "L2_RQSTS.DEMAND_DATA_RD_MISS", 0x24, 0x21, true }, 385 { "L2_RQSTS.RFO_MISS", 0x24, 0x22, true }, 386 { "L2_RQSTS.CODE_RD_MISS", 0x24, 0x24, true }, 387 { "L2_RQSTS.ALL_DEMAND_MISS", 0x24, 0x27, true }, 388 { "L2_RQSTS.PF_MISS", 0x24, 0x38, true }, 389 { "L2_RQSTS.MISS", 0x24, 0x3F, true }, 390 { "L2_RQSTS.DEMAND_DATA_RD_HIT", 0x24, 0x41, true }, 391 { "L2_RQSTS.RFO_HIT", 0x24, 0x42, true }, 392 { "L2_RQSTS.CODE_RD_HIT", 0x24, 0x44, true }, 393 { "L2_RQSTS.PF_HIT", 0x24, 0xD8, true }, 394 { "L2_RQSTS.ALL_DEMAND_DATA_RD", 0x24, 0xE1, true }, 395 { "L2_RQSTS.ALL_RFO", 0x24, 0xE2, true }, 396 { "L2_RQSTS.ALL_CODE_RD", 0x24, 0xE4, true }, 397 { "L2_RQSTS.ALL_DEMAND_REFERENCES", 0x24, 0xE7, true }, 398 { "L2_RQSTS.ALL_PF", 0x24, 0xF8, true }, 399 { "L2_RQSTS.REFERENCES", 0x24, 0xFF, true }, 400 { "SW_PREFETCH_ACCESS.NTA", 0x32, 0x01, true }, 401 { "SW_PREFETCH_ACCESS.T0", 0x32, 0x02, true }, 402 { "SW_PREFETCH_ACCESS.T1_T2", 0x32, 0x04, true }, 403 { "SW_PREFETCH_ACCESS.PREFETCHW", 0x32, 0x08, true }, 404 { "CPU_CLK_THREAD_UNHALTED.ONE_THREAD_ACTIVE", 0x3C, 0x02, true }, 405 { "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE", 0x3C, 0x02, true }, 406 { "L1D_PEND_MISS.PENDING", 0x48, 0x01, true }, 407 { "L1D_PEND_MISS.FB_FULL", 0x48, 0x02, true }, 408 { "DTLB_STORE_MISSES.MISS_CAUSES_A_WALK", 0x49, 0x01, true }, 409 { "DTLB_STORE_MISSES.WALK_COMPLETED_4K", 0x49, 0x02, true }, 410 { "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M", 0x49, 0x04, true }, 411 { "DTLB_STORE_MISSES.WALK_COMPLETED_1G", 0x49, 0x08, true }, 412 { "DTLB_STORE_MISSES.WALK_COMPLETED", 0x49, 0x0E, true }, 413 { "DTLB_STORE_MISSES.WALK_PENDING", 0x49, 0x10, true }, 414 { "DTLB_STORE_MISSES.STLB_HIT", 0x49, 0x20, true }, 415 { "LOAD_HIT_PRE.SW_PF", 0x4C, 0x01, true }, 416 { "EPT.WALK_PENDING", 0x4F, 0x10, true }, 417 { "L1D.REPLACEMENT", 0x51, 0x01, true }, 418 { "RS_EVENTS.EMPTY_CYCLES", 0x5E, 0x01, true }, 419 { "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD", 0x60, 0x01, true }, 420 { "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD", 0x60, 0x02, true }, 421 { "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO", 0x60, 0x04, true }, 422 { "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD", 0x60, 0x08, true }, 423 { "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD", 0x60, 0x10, true }, 424 { "IDQ.MITE_UOPS", 0x79, 0x04, true }, 425 { "IDQ.DSB_UOPS", 0x79, 0x08, true }, 426 { "IDQ.MS_MITE_UOPS", 0x79, 0x20, true }, 427 { "IDQ.MS_UOPS", 0x79, 0x30, true }, 428 { "ICACHE_16B.IFDATA_STALL", 0x80, 0x04, true }, 429 { "ICACHE_64B.IFTAG_HIT", 0x83, 0x01, true }, 430 { "ICACHE_64B.IFTAG_MISS", 0x83, 0x02, true }, 431 { "ICACHE_64B.IFTAG_STALL", 0x83, 0x04, true }, 432 { "ITLB_MISSES.MISS_CAUSES_A_WALK", 0x85, 0x01, true }, 433 { "ITLB_MISSES.WALK_COMPLETED_4K", 0x85, 0x02, true }, 434 { "ITLB_MISSES.WALK_COMPLETED_2M_4M", 0x85, 0x04, true }, 435 { "ITLB_MISSES.WALK_COMPLETED_1G", 0x85, 0x08, true }, 436 { "ITLB_MISSES.WALK_COMPLETED", 0x85, 0x0E, true }, 437 { "ITLB_MISSES.WALK_PENDING", 0x85, 0x10, true }, 438 { "ITLB_MISSES.STLB_HIT", 0x85, 0x20, true }, 439 { "ILD_STALL.LCP", 0x87, 0x01, true }, 440 { "IDQ_UOPS_NOT_DELIVERED.CORE", 0x9C, 0x01, true }, 441 { "RESOURCE_STALLS.ANY", 0xA2, 0x01, true }, 442 { "RESOURCE_STALLS.SB", 0xA2, 0x08, true }, 443 { "EXE_ACTIVITY.EXE_BOUND_0_PORTS", 0xA6, 0x01, true }, 444 { "EXE_ACTIVITY.1_PORTS_UTIL", 0xA6, 0x02, true }, 445 { "EXE_ACTIVITY.2_PORTS_UTIL", 0xA6, 0x04, true }, 446 { "EXE_ACTIVITY.3_PORTS_UTIL", 0xA6, 0x08, true }, 447 { "EXE_ACTIVITY.4_PORTS_UTIL", 0xA6, 0x10, true }, 448 { "EXE_ACTIVITY.BOUND_ON_STORES", 0xA6, 0x40, true }, 449 { "LSD.UOPS", 0xA8, 0x01, true }, 450 { "DSB2MITE_SWITCHES.PENALTY_CYCLES", 0xAB, 0x02, true }, 451 { "ITLB.ITLB_FLUSH", 0xAE, 0x01, true }, 452 { "OFFCORE_REQUESTS.DEMAND_DATA_RD", 0xB0, 0x01, true }, 453 { "OFFCORE_REQUESTS.DEMAND_CODE_RD", 0xB0, 0x02, true }, 454 { "OFFCORE_REQUESTS.DEMAND_RFO", 0xB0, 0x04, true }, 455 { "OFFCORE_REQUESTS.ALL_DATA_RD", 0xB0, 0x08, true }, 456 { "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD", 0xB0, 0x10, true }, 457 { "OFFCORE_REQUESTS.ALL_REQUESTS", 0xB0, 0x80, true }, 458 { "UOPS_EXECUTED.THREAD", 0xB1, 0x01, true }, 459 { "UOPS_EXECUTED.CORE", 0xB1, 0x02, true }, 460 { "UOPS_EXECUTED.X87", 0xB1, 0x10, true }, 461 { "OFFCORE_REQUESTS_BUFFER.SQ_FULL", 0xB2, 0x01, true }, 462 { "TLB_FLUSH.DTLB_THREAD", 0xBD, 0x01, true }, 463 { "TLB_FLUSH.STLB_ANY", 0xBD, 0x20, true }, 464 { "INST_RETIRED.PREC_DIST", 0xC0, 0x01, true }, 465 { "OTHER_ASSISTS.ANY", 0xC1, 0x3F, true }, 466 { "UOPS_RETIRED.RETIRE_SLOTS", 0xC2, 0x02, true }, 467 { "MACHINE_CLEARS.MEMORY_ORDERING", 0xC3, 0x02, true }, 468 { "MACHINE_CLEARS.SMC", 0xC3, 0x04, true }, 469 { "BR_INST_RETIRED.CONDITIONAL", 0xC4, 0x01, true }, 470 { "BR_INST_RETIRED.NEAR_CALL", 0xC4, 0x02, true }, 471 { "BR_INST_RETIRED.NEAR_RETURN", 0xC4, 0x08, true }, 472 { "BR_INST_RETIRED.NOT_TAKEN", 0xC4, 0x10, true }, 473 { "BR_INST_RETIRED.NEAR_TAKEN", 0xC4, 0x20, true }, 474 { "BR_INST_RETIRED.FAR_BRANCH", 0xC4, 0x40, true }, 475 { "BR_MISP_RETIRED.CONDITIONAL", 0xC5, 0x01, true }, 476 { "BR_MISP_RETIRED.NEAR_CALL", 0xC5, 0x02, true }, 477 { "BR_MISP_RETIRED.NEAR_TAKEN", 0xC5, 0x20, true }, 478 { "HW_INTERRUPTS.RECEIVED", 0xCB, 0x01, true }, 479 { "MEM_INST_RETIRED.STLB_MISS_LOADS", 0xD0, 0x11, true }, 480 { "MEM_INST_RETIRED.STLB_MISS_STORES", 0xD0, 0x12, true }, 481 { "MEM_INST_RETIRED.LOCK_LOADS", 0xD0, 0x21, true }, 482 { "MEM_INST_RETIRED.SPLIT_LOADS", 0xD0, 0x41, true }, 483 { "MEM_INST_RETIRED.SPLIT_STORES", 0xD0, 0x42, true }, 484 { "MEM_INST_RETIRED.ALL_LOADS", 0xD0, 0x81, true }, 485 { "MEM_INST_RETIRED.ALL_STORES", 0xD0, 0x82, true }, 486 { "MEM_LOAD_RETIRED.L1_HIT", 0xD1, 0x01, true }, 487 { "MEM_LOAD_RETIRED.L2_HIT", 0xD1, 0x02, true }, 488 { "MEM_LOAD_RETIRED.L3_HIT", 0xD1, 0x04, true }, 489 { "MEM_LOAD_RETIRED.L1_MISS", 0xD1, 0x08, true }, 490 { "MEM_LOAD_RETIRED.L2_MISS", 0xD1, 0x10, true }, 491 { "MEM_LOAD_RETIRED.L3_MISS", 0xD1, 0x20, true }, 492 { "MEM_LOAD_RETIRED.FB_HIT", 0xD1, 0x40, true }, 493 { "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS", 0xD2, 0x01, true }, 494 { "MEM_LOAD_L3_HIT_RETIRED.XSNP_HIT", 0xD2, 0x02, true }, 495 { "MEM_LOAD_L3_HIT_RETIRED.XSNP_HITM", 0xD2, 0x04, true }, 496 { "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE", 0xD2, 0x08, true }, 497 { "MEM_LOAD_MISC_RETIRED.UC", 0xD4, 0x04, true }, 498 { "BACLEARS.ANY", 0xE6, 0x01, true }, 499 { "L2_TRANS.L2_WB", 0xF0, 0x40, true }, 500 { "L2_LINES_IN.ALL", 0xF1, 0x1F, true }, 501 { "L2_LINES_OUT.SILENT", 0xF2, 0x01, true }, 502 { "L2_LINES_OUT.NON_SILENT", 0xF2, 0x02, true }, 503 { "L2_LINES_OUT.USELESS_HWPF", 0xF2, 0x04, true }, 504 { "SQ_MISC.SPLIT_LOCK", 0xF4, 0x10, true }, 505 }; 506 507 static struct event_table intel_skylake_kabylake = { 508 .tablename = "Intel Skylake/Kabylake", 509 .names = intel_skylake_kabylake_names, 510 .nevents = sizeof(intel_skylake_kabylake_names) / 511 sizeof(struct name_to_event), 512 .next = NULL 513 }; 514 515 static struct event_table * 516 init_intel_skylake_kabylake(void) 517 { 518 return &intel_skylake_kabylake; 519 } 520 521 static struct event_table * 522 init_intel_generic(void) 523 { 524 unsigned int eax, ebx, ecx, edx; 525 struct event_table *table; 526 527 /* 528 * The kernel made sure the Architectural Version 1 PMCs were 529 * present. 530 */ 531 table = init_intel_arch1(); 532 533 /* 534 * Now query the additional (non-architectural) events. They 535 * depend on the CPU model. 536 */ 537 eax = 0x01; 538 ebx = 0; 539 ecx = 0; 540 edx = 0; 541 x86_cpuid(&eax, &ebx, &ecx, &edx); 542 543 if (CPUID_TO_FAMILY(eax) == 6) { 544 switch (CPUID_TO_MODEL(eax)) { 545 case 0x37: /* Silvermont (Bay Trail) */ 546 case 0x4A: /* Silvermont (Tangier) */ 547 case 0x4C: /* Airmont (Braswell, Cherry Trail) */ 548 case 0x4D: /* Silvermont (Avoton, Rangeley) */ 549 case 0x5A: /* Silvermont (Anniedale) */ 550 case 0x5D: /* Silvermont (SoFIA) */ 551 table->next = init_intel_silvermont_airmont(); 552 break; 553 case 0x5C: /* Goldmont (Apollo Lake) */ 554 case 0x5F: /* Goldmont (Denverton) */ 555 table->next = init_intel_goldmont(); 556 break; 557 case 0x7A: /* Goldmont Plus (Gemini Lake) */ 558 table->next = init_intel_goldmontplus(); 559 break; 560 case 0x4E: /* Skylake */ 561 case 0x5E: /* Skylake */ 562 case 0x8E: /* Kabylake */ 563 case 0x9E: /* Kabylake */ 564 table->next = init_intel_skylake_kabylake(); 565 break; 566 } 567 } 568 569 return table; 570 } 571 572 /* -------------------------------------------------------------------------- */ 573 574 /* 575 * AMD Family 10h 576 */ 577 static struct name_to_event amd_f10h_names[] = { 578 { "seg-load-all", 0x20, 0x7f, true }, 579 { "seg-load-es", 0x20, 0x01, true }, 580 { "seg-load-cs", 0x20, 0x02, true }, 581 { "seg-load-ss", 0x20, 0x04, true }, 582 { "seg-load-ds", 0x20, 0x08, true }, 583 { "seg-load-fs", 0x20, 0x10, true }, 584 { "seg-load-gs", 0x20, 0x20, true }, 585 { "seg-load-hs", 0x20, 0x40, true }, 586 { "l1cache-access", 0x40, 0x00, true }, 587 { "l1cache-miss", 0x41, 0x00, true }, 588 { "l1cache-refill", 0x42, 0x1f, true }, 589 { "l1cache-refill-invalid", 0x42, 0x01, true }, 590 { "l1cache-refill-shared", 0x42, 0x02, true }, 591 { "l1cache-refill-exclusive", 0x42, 0x04, true }, 592 { "l1cache-refill-owner", 0x42, 0x08, true }, 593 { "l1cache-refill-modified", 0x42, 0x10, true }, 594 { "l1cache-load", 0x43, 0x1f, true }, 595 { "l1cache-load-invalid", 0x43, 0x01, true }, 596 { "l1cache-load-shared", 0x43, 0x02, true }, 597 { "l1cache-load-exclusive", 0x43, 0x04, true }, 598 { "l1cache-load-owner", 0x43, 0x08, true }, 599 { "l1cache-load-modified", 0x43, 0x10, true }, 600 { "l1cache-writeback", 0x44, 0x1f, true }, 601 { "l1cache-writeback-invalid", 0x44, 0x01, true }, 602 { "l1cache-writeback-shared", 0x44, 0x02, true }, 603 { "l1cache-writeback-exclusive",0x44, 0x04, true }, 604 { "l1cache-writeback-owner", 0x44, 0x08, true }, 605 { "l1cache-writeback-modified", 0x44, 0x10, true }, 606 { "l1DTLB-hit-all", 0x4D, 0x07, true }, 607 { "l1DTLB-hit-4Kpage", 0x4D, 0x01, true }, 608 { "l1DTLB-hit-2Mpage", 0x4D, 0x02, true }, 609 { "l1DTLB-hit-1Gpage", 0x4D, 0x04, true }, 610 { "l1DTLB-miss-all", 0x45, 0x07, true }, 611 { "l1DTLB-miss-4Kpage", 0x45, 0x01, true }, 612 { "l1DTLB-miss-2Mpage", 0x45, 0x02, true }, 613 { "l1DTLB-miss-1Gpage", 0x45, 0x04, true }, 614 { "l2DTLB-miss-all", 0x46, 0x03, true }, 615 { "l2DTLB-miss-4Kpage", 0x46, 0x01, true }, 616 { "l2DTLB-miss-2Mpage", 0x46, 0x02, true }, 617 /* l2DTLB-miss-1Gpage: reserved on some revisions, so disabled */ 618 { "l1ITLB-miss", 0x84, 0x00, true }, 619 { "l2ITLB-miss-all", 0x85, 0x03, true }, 620 { "l2ITLB-miss-4Kpage", 0x85, 0x01, true }, 621 { "l2ITLB-miss-2Mpage", 0x85, 0x02, true }, 622 { "mem-misalign-ref", 0x47, 0x00, true }, 623 { "ins-fetch", 0x80, 0x00, true }, 624 { "ins-fetch-miss", 0x81, 0x00, true }, 625 { "ins-refill-l2", 0x82, 0x00, true }, 626 { "ins-refill-sys", 0x83, 0x00, true }, 627 { "ins-fetch-stall", 0x87, 0x00, true }, 628 { "ins-retired", 0xC0, 0x00, true }, 629 { "ins-empty", 0xD0, 0x00, true }, 630 { "ops-retired", 0xC1, 0x00, true }, 631 { "branch-retired", 0xC2, 0x00, true }, 632 { "branch-miss-retired", 0xC3, 0x00, true }, 633 { "branch-taken-retired", 0xC4, 0x00, true }, 634 { "branch-taken-miss-retired", 0xC5, 0x00, true }, 635 { "branch-far-retired", 0xC6, 0x00, true }, 636 { "branch-resync-retired", 0xC7, 0x00, true }, 637 { "branch-near-retired", 0xC8, 0x00, true }, 638 { "branch-near-miss-retired", 0xC9, 0x00, true }, 639 { "branch-indirect-miss-retired", 0xCA, 0x00, true }, 640 { "int-hw", 0xCF, 0x00, true }, 641 { "int-cycles-masked", 0xCD, 0x00, true }, 642 { "int-cycles-masked-pending", 0xCE, 0x00, true }, 643 { "fpu-exceptions", 0xDB, 0x00, true }, 644 { "break-match0", 0xDC, 0x00, true }, 645 { "break-match1", 0xDD, 0x00, true }, 646 { "break-match2", 0xDE, 0x00, true }, 647 { "break-match3", 0xDF, 0x00, true }, 648 }; 649 650 static struct event_table amd_f10h = { 651 .tablename = "AMD Family 10h", 652 .names = amd_f10h_names, 653 .nevents = sizeof(amd_f10h_names) / 654 sizeof(struct name_to_event), 655 .next = NULL 656 }; 657 658 /* 659 * AMD Family 15h 660 */ 661 static struct name_to_event amd_f15h_names[] = { 662 { "FpPipeAssignment", 0x000, 0x77, true }, 663 { "FpSchedulerEmpty", 0x001, 0x00, true }, 664 { "FpRetSseAvxOps", 0x003, 0xff, true }, 665 { "FpNumMovElim", 0x004, 0x0f, true }, 666 { "FpRetiredSerOps", 0x005, 0x0f, true }, 667 { "LsSegRegLoads", 0x020, 0x7f, true }, 668 { "LsPipeRestartSelfMod", 0x021, 0x00, true }, 669 { "LsPipeRestartVarious", 0x022, 0x1f, true }, 670 { "LsLoadQueueStoreQFull", 0x023, 0x03, true }, 671 { "LsLockedOps", 0x024, 0x00, true }, 672 { "LsRetClflushInstr", 0x026, 0x00, true }, 673 { "LsRetCpuidInstr", 0x027, 0x00, true }, 674 { "LsDispatch", 0x029, 0x07, true }, 675 { "LsCanStoreToLoadFwOps", 0x02a, 0x03, true }, 676 { "LsSmisReceived", 0x02b, 0x00, true }, 677 { "LsExecClflushInstr", 0x030, 0x00, true }, 678 { "LsMisalignStore", 0x032, 0x00, true }, 679 { "LsFpLoadBufStall", 0x034, 0x00, true }, 680 { "LsStlf", 0x035, 0x00, true }, 681 { "DcCacheAccess", 0x040, 0x00, true }, 682 { "DcCacheMiss", 0x041, 0x00, true }, 683 { "DcCacheFillL2Sys", 0x042, 0x1f, true }, 684 { "DcCacheFillSys", 0x043, 0x00, true }, 685 { "DcUnifiedTlbHit", 0x045, 0x77, true }, 686 { "DcUnifiedTlbMiss", 0x046, 0x77, true }, 687 { "DcMisalignAccess", 0x047, 0x00, true }, 688 { "DcPrefetchInstrDisp", 0x04b, 0x07, true }, 689 { "DcIneffSwPrefetch", 0x052, 0x09, true }, 690 { "CuCmdVictimBuf", 0x060, 0x98, true }, 691 { "CuCmdMaskedOps", 0x061, 0x65, true }, 692 { "CuCmdReadBlkOps", 0x062, 0x77, true }, 693 { "CuCmdChgDirtyOps", 0x063, 0x08, true }, 694 { "CuDramSysReq", 0x064, 0x00, true }, 695 { "CuMemReqByType", 0x065, 0x83, true }, 696 { "CuDataCachePrefetch", 0x067, 0x03, true }, 697 { "CuMabReq", 0x068, 0xff, true }, 698 { "CuMabWaitCyc", 0x069, 0xff, true }, 699 { "CuSysRespCacheFill", 0x06c, 0x3f, true }, 700 { "CuOctwordsWritten", 0x06d, 0x01, true }, 701 { "CuCacheXInv", 0x075, 0x0f, true }, 702 { "CuCpuClkNotHalted", 0x076, 0x00, true }, 703 { "CuL2Req", 0x07d, 0x5f, true }, 704 { "CuL2Miss", 0x07e, 0x17, true }, 705 { "CuL2FillWb", 0x07f, 0x07, true }, 706 { "CuPageSplintering", 0x165, 0x07, true }, 707 { "CuL2PrefetchTrigEv", 0x16c, 0x03, true }, 708 { "CuXabAllocStall", 0x177, 0x03, true }, 709 { "CuFreeXabEntries", 0x17f, 0x01, true }, 710 { "IcCacheFetch", 0x080, 0x00, true }, 711 { "IcCacheMiss", 0x081, 0x00, true }, 712 { "IcCacheFillL2", 0x082, 0x00, true }, 713 { "IcCacheFillSys", 0x083, 0x00, true }, 714 { "IcL1TlbMissL2Hit", 0x084, 0x00, true }, 715 { "IcL1TlbMissL2Miss", 0x085, 0x07, true }, 716 { "IcPipeRestartInstrStrProbe", 0x086, 0x00, true }, 717 { "IcFetchStall", 0x087, 0x00, true }, 718 { "IcRetStackHits", 0x088, 0x00, true }, 719 { "IcRetStackOver", 0x089, 0x00, true }, 720 { "IcCacheVictims", 0x08b, 0x00, true }, 721 { "IcCacheLinesInv", 0x08c, 0x0f, true }, 722 { "IcTlbReload", 0x099, 0x00, true }, 723 { "IcTlbReloadAbort", 0x09a, 0x00, true }, 724 { "IcUopsDispatched", 0x186, 0x01, true }, 725 { "ExRetInstr", 0x0c0, 0x00, true }, 726 { "ExRetCops", 0x0c1, 0x00, true }, 727 { "ExRetBrn", 0x0c2, 0x00, true }, 728 { "ExRetBrnMisp", 0x0c3, 0x00, true }, 729 { "ExRetBrnTkn", 0x0c4, 0x00, true }, 730 { "ExRetBrnTknMisp", 0x0c5, 0x00, true }, 731 { "ExRetBrnFar", 0x0c6, 0x00, true }, 732 { "ExRetBrnResync", 0x0c7, 0x00, true }, 733 { "ExRetNearRet", 0x0c8, 0x00, true }, 734 { "ExRetNearRetMispred", 0x0c9, 0x00, true }, 735 { "ExRetBrnIndMisp", 0x0ca, 0x00, true }, 736 { "ExRetMmxFpInstr@X87", 0x0cb, 0x01, true }, 737 { "ExRetMmxFpInstr@Mmx", 0x0cb, 0x02, true }, 738 { "ExRetMmxFpInstr@Sse", 0x0cb, 0x04, true }, 739 { "ExIntMaskedCyc", 0x0cd, 0x00, true }, 740 { "ExIntMaskedCycIntPend", 0x0ce, 0x00, true }, 741 { "ExIntTaken", 0x0cf, 0x00, true }, 742 { "ExDecEmpty", 0x0d0, 0x00, true }, 743 { "ExDispStall", 0x0d1, 0x00, true }, 744 { "ExUseqStallSer", 0x0d2, 0x00, true }, 745 { "ExDispStallInstrRetQFull", 0x0d5, 0x00, true }, 746 { "ExDispStallIntSchedQFull", 0x0d6, 0x00, true }, 747 { "ExDispStallFpSchedQFull", 0x0d7, 0x00, true }, 748 { "ExDispStallLdqFull", 0x0d8, 0x00, true }, 749 { "ExUseqStallAllQuiet", 0x0d9, 0x00, true }, 750 { "ExFpuEx", 0x0db, 0x1f, true }, 751 { "ExBpDr0", 0x0dc, 0x8f, true }, 752 { "ExBpDr1", 0x0dd, 0x8f, true }, 753 { "ExBpDr2", 0x0de, 0x8f, true }, 754 { "ExBpDr3", 0x0df, 0x8f, true }, 755 { "ExRetx87FpOps", 0x1c0, 0x07, true }, 756 { "ExTaggedIbsOps", 0x1cf, 0x07, true }, 757 { "ExRetFusBrInstr", 0x1d0, 0x00, true }, 758 { "ExDispStallStqFull", 0x1d8, 0x00, true }, 759 { "ExCycNoDispIntPrfTok", 0x1dd, 0x00, true }, 760 { "ExCycNoDispfpPrfTok", 0x1de, 0x00, true }, 761 { "ExFpDispContention", 0x1df, 0x0f, true }, 762 }; 763 764 static struct event_table amd_f15h = { 765 .tablename = "AMD Family 15h", 766 .names = amd_f15h_names, 767 .nevents = sizeof(amd_f15h_names) / 768 sizeof(struct name_to_event), 769 .next = NULL 770 }; 771 772 /* 773 * AMD Family 17h 774 */ 775 static struct name_to_event amd_f17h_names[] = { 776 { "FpRetx87FpOps", 0x02, __BITS(2,0), true }, 777 { "FpRetSseAvxOps", 0x03, __BITS(7,0), true }, 778 { "FpRetiredSerOps", 0x05, __BITS(3,0), true }, 779 { "LsL1DTlbMiss", 0x45, __BITS(7,0), true }, 780 { "LsTableWalker", 0x46, __BITS(3,0), true }, 781 { "LsMisalAccesses", 0x47, 0x00, true }, 782 { "LsInefSwPref", 0x52, __BITS(1,0), true }, 783 { "LsNotHaltedCyc", 0x76, 0x00, true }, 784 { "IcFw32", 0x80, 0x00, true }, 785 { "IcFw32Miss", 0x81, 0x00, true }, 786 { "IcCacheFillL2", 0x82, 0x00, true }, 787 { "IcCacheFillSys", 0x83, 0x00, true }, 788 { "IcFetchStall", 0x87, __BITS(2,0), true }, 789 { "IcCacheInval", 0x8C, __BITS(1,0), true }, 790 { "BpL1TlbMissL2Hit", 0x84, 0x00, true }, 791 { "BpL1TlbMissL2Miss", 0x85, 0x00, true }, 792 { "BpSnpReSync", 0x86, 0x00, true }, 793 { "BpL1BTBCorrect", 0x8A, 0x00, true }, 794 { "BpL2BTBCorrect", 0x8B, 0x00, true }, 795 { "BpTlbRel", 0x99, 0x00, true }, 796 { "ExRetInstr", 0xC0, 0x00, true }, 797 { "ExRetCops", 0xC1, 0x00, true }, 798 { "ExRetBrn", 0xC2, 0x00, true }, 799 { "ExRetBrnMisp", 0xC3, 0x00, true }, 800 { "ExRetBrnTkn", 0xC4, 0x00, true }, 801 { "ExRetBrnTknMisp", 0xC5, 0x00, true }, 802 { "ExRetBrnFar", 0xC6, 0x00, true }, 803 { "ExRetBrnResync", 0xC7, 0x00, true }, 804 { "ExRetBrnIndMisp", 0xCA, 0x00, true }, 805 { "ExRetNearRet", 0xC8, 0x00, true }, 806 { "ExRetNearRetMispred", 0xC9, 0x00, true }, 807 { "ExRetMmxFpInstr@X87", 0xCB, __BIT(0), true }, 808 { "ExRetMmxFpInstr@Mmx", 0xCB, __BIT(1), true }, 809 { "ExRetMmxFpInstr@Sse", 0xCB, __BIT(2), true }, 810 { "ExRetCond", 0xD1, 0x00, true }, 811 { "ExRetCondMisp", 0xD2, 0x00, true }, 812 { "ExDivBusy", 0xD3, 0x00, true }, 813 { "ExDivCount", 0xD4, 0x00, true }, 814 }; 815 816 static struct event_table amd_f17h = { 817 .tablename = "AMD Family 17h", 818 .names = amd_f17h_names, 819 .nevents = sizeof(amd_f17h_names) / 820 sizeof(struct name_to_event), 821 .next = NULL 822 }; 823 824 static struct event_table * 825 init_amd_generic(void) 826 { 827 unsigned int eax, ebx, ecx, edx; 828 829 eax = 0x01; 830 ebx = 0; 831 ecx = 0; 832 edx = 0; 833 x86_cpuid(&eax, &ebx, &ecx, &edx); 834 835 switch (CPUID_TO_FAMILY(eax)) { 836 case 0x10: 837 return &amd_f10h; 838 case 0x15: 839 return &amd_f15h; 840 case 0x17: 841 return &amd_f17h; 842 } 843 844 return NULL; 845 } 846 847 /* -------------------------------------------------------------------------- */ 848 849 int 850 tprof_event_init(uint32_t ident) 851 { 852 switch (ident) { 853 case TPROF_IDENT_NONE: 854 return -1; 855 case TPROF_IDENT_INTEL_GENERIC: 856 cpuevents = init_intel_generic(); 857 break; 858 case TPROF_IDENT_AMD_GENERIC: 859 cpuevents = init_amd_generic(); 860 break; 861 } 862 return (cpuevents == NULL) ? -1 : 0; 863 } 864 865 static void 866 recursive_event_list(struct event_table *table) 867 { 868 size_t i; 869 870 printf("%s:\n", table->tablename); 871 for (i = 0; i < table->nevents; i++) { 872 if (!table->names[i].enabled) 873 continue; 874 printf("\t%s\n", table->names[i].name); 875 } 876 877 if (table->next != NULL) { 878 recursive_event_list(table->next); 879 } 880 } 881 882 void 883 tprof_event_list(void) 884 { 885 recursive_event_list(cpuevents); 886 } 887 888 static void 889 recursive_event_lookup(struct event_table *table, const char *name, 890 struct tprof_param *param) 891 { 892 size_t i; 893 894 for (i = 0; i < table->nevents; i++) { 895 if (!table->names[i].enabled) 896 continue; 897 if (!strcmp(table->names[i].name, name)) { 898 param->p_event = table->names[i].event; 899 param->p_unit = table->names[i].unit; 900 return; 901 } 902 } 903 904 if (table->next != NULL) { 905 recursive_event_lookup(table->next, name, param); 906 } else { 907 errx(EXIT_FAILURE, "event '%s' unknown", name); 908 } 909 } 910 911 void 912 tprof_event_lookup(const char *name, struct tprof_param *param) 913 { 914 recursive_event_lookup(cpuevents, name, param); 915 } 916