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