Annotation of src/usr.sbin/tprof/arch/tprof_x86.c, Revision 1.7
1.7 ! knakahar 1: /* $NetBSD: tprof_x86.c,v 1.6 2018/11/26 07:45:47 knakahara Exp $ */
1.1 maxv 2:
3: /*
4: * Copyright (c) 2018 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: /*
1.5 knakahar 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: /*
1.6 knakahar 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: /*
1.7 ! knakahar 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: /*
1.4 maxv 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.*
1.1 maxv 365: */
366: static struct name_to_event intel_skylake_kabylake_names[] = {
367: /* Event Name - Event Select - UMask */
1.4 maxv 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 },
1.1 maxv 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:
1.3 maxv 542: if (CPUID_TO_FAMILY(eax) == 6) {
543: switch (CPUID_TO_MODEL(eax)) {
1.5 knakahar 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;
1.6 knakahar 552: case 0x5C: /* Goldmont (Apollo Lake) */
553: case 0x5F: /* Goldmont (Denvertion) */
554: table->next = init_intel_goldmont();
555: break;
1.7 ! knakahar 556: case 0x7A: /* Goldmont Plus (Gemini Lake) */
! 557: table->next = init_intel_goldmontplus();
! 558: break;
1.3 maxv 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: }
1.1 maxv 566: }
567:
568: return table;
569: }
570:
571: /* -------------------------------------------------------------------------- */
572:
573: /*
574: * AMD Family 10h
575: */
576: static struct name_to_event amd_f10h_names[] = {
1.2 maxv 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 },
1.1 maxv 616: /* l2DTLB-miss-1Gpage: reserved on some revisions, so disabled */
1.2 maxv 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 },
1.1 maxv 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: static struct event_table *
658: init_amd_f10h(void)
659: {
660: return &amd_f10h;
661: }
662:
663: static struct event_table *
664: init_amd_generic(void)
665: {
666: unsigned int eax, ebx, ecx, edx;
667:
668: eax = 0x01;
669: ebx = 0;
670: ecx = 0;
671: edx = 0;
672: x86_cpuid(&eax, &ebx, &ecx, &edx);
673:
674: switch (CPUID_TO_FAMILY(eax)) {
675: case 0x10:
676: return init_amd_f10h();
677: }
678:
679: return NULL;
680: }
681:
682: /* -------------------------------------------------------------------------- */
683:
684: int
685: tprof_event_init(uint32_t ident)
686: {
687: switch (ident) {
688: case TPROF_IDENT_NONE:
689: return -1;
690: case TPROF_IDENT_INTEL_GENERIC:
691: cpuevents = init_intel_generic();
692: break;
693: case TPROF_IDENT_AMD_GENERIC:
694: cpuevents = init_amd_generic();
695: break;
696: }
697: return (cpuevents == NULL) ? -1 : 0;
698: }
699:
700: static void
701: recursive_event_list(struct event_table *table)
702: {
703: size_t i;
704:
705: printf("%s:\n", table->tablename);
706: for (i = 0; i < table->nevents; i++) {
707: if (!table->names[i].enabled)
708: continue;
709: printf("\t%s\n", table->names[i].name);
710: }
711:
712: if (table->next != NULL) {
713: recursive_event_list(table->next);
714: }
715: }
716:
717: void
718: tprof_event_list(void)
719: {
720: recursive_event_list(cpuevents);
721: }
722:
723: static void
724: recursive_event_lookup(struct event_table *table, const char *name,
725: struct tprof_param *param)
726: {
727: size_t i;
728:
729: for (i = 0; i < table->nevents; i++) {
730: if (!table->names[i].enabled)
731: continue;
732: if (!strcmp(table->names[i].name, name)) {
733: param->p_event = table->names[i].event;
734: param->p_unit = table->names[i].unit;
735: return;
736: }
737: }
738:
739: if (table->next != NULL) {
740: recursive_event_lookup(table->next, name, param);
741: } else {
742: errx(EXIT_FAILURE, "event '%s' unknown", name);
743: }
744: }
745:
746: void
747: tprof_event_lookup(const char *name, struct tprof_param *param)
748: {
749: recursive_event_lookup(cpuevents, name, param);
750: }
CVSweb <webmaster@jp.NetBSD.org>