2 * Copyright (c) 2003-2008 Joseph Koshy
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/types.h>
31 #include <sys/module.h>
33 #include <sys/syscall.h>
45 /* Function prototypes */
47 static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
48 struct pmc_op_pmcallocate *_pmc_config);
50 #if defined(__amd64__) || defined(__i386__)
51 static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
52 struct pmc_op_pmcallocate *_pmc_config);
53 static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
54 struct pmc_op_pmcallocate *_pmc_config);
57 static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
58 struct pmc_op_pmcallocate *_pmc_config);
59 static int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
60 struct pmc_op_pmcallocate *_pmc_config);
63 #define PMC_CALL(cmd, params) \
64 syscall(pmc_syscall, PMC_OP_##cmd, (params))
67 * Event aliases provide a way for the user to ask for generic events
68 * like "cache-misses", or "instructions-retired". These aliases are
69 * mapped to the appropriate canonical event descriptions using a
72 struct pmc_event_alias {
77 static const struct pmc_event_alias *pmc_mdep_event_aliases;
80 * The pmc_event_descr table maps symbolic names known to the user
81 * to integer codes used by the PMC KLD.
83 struct pmc_event_descr {
84 const char *pm_ev_name;
85 enum pmc_event pm_ev_code;
86 enum pmc_class pm_ev_class;
89 static const struct pmc_event_descr
93 #define __PMC_EV(C,N,EV) { #EV, PMC_EV_ ## C ## _ ## N, PMC_CLASS_ ## C },
98 * Mapping tables, mapping enumeration values to human readable
102 static const char * pmc_capability_names[] = {
104 #define __PMC_CAP(N,V,D) #N ,
108 static const char * pmc_class_names[] = {
110 #define __PMC_CLASS(C) #C ,
114 static const char * pmc_cputype_names[] = {
116 #define __PMC_CPU(S, D) #S ,
120 static const char * pmc_disposition_names[] = {
122 #define __PMC_DISP(D) #D ,
126 static const char * pmc_mode_names[] = {
128 #define __PMC_MODE(M,N) #M ,
132 static const char * pmc_state_names[] = {
134 #define __PMC_STATE(S) #S ,
138 static int pmc_syscall = -1; /* filled in by pmc_init() */
140 static struct pmc_cpuinfo cpu_info; /* filled in by pmc_init() */
143 /* Architecture dependent event parsing */
144 static int (*pmc_mdep_allocate_pmc)(enum pmc_event _pe, char *_ctrspec,
145 struct pmc_op_pmcallocate *_pmc_config);
147 /* Event masks for events */
150 const uint32_t pm_value;
152 #define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) }
153 #define NULLMASK PMCMASK(NULL,0)
155 #if defined(__amd64__) || defined(__i386__)
157 pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint32_t *evmask)
159 const struct pmc_masks *pm;
163 if (pmask == NULL) /* no mask keywords */
165 q = strchr(p, '='); /* skip '=' */
166 if (*++q == '\0') /* no more data */
168 c = 0; /* count of mask keywords seen */
169 while ((r = strsep(&q, "+")) != NULL) {
170 for (pm = pmask; pm->pm_name && strcmp(r, pm->pm_name); pm++)
172 if (pm->pm_name == NULL) /* not found */
174 *evmask |= pm->pm_value;
181 #define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0)
182 #define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0)
183 #define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S }
185 #if defined(__i386__)
188 * AMD K7 (Athlon) CPUs.
191 static struct pmc_event_alias k7_aliases[] = {
192 EV_ALIAS("branches", "k7-retired-branches"),
193 EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"),
194 EV_ALIAS("cycles", "tsc"),
195 EV_ALIAS("dc-misses", "k7-dc-misses,mask=moesi"),
196 EV_ALIAS("ic-misses", "k7-ic-misses"),
197 EV_ALIAS("instructions", "k7-retired-instructions"),
198 EV_ALIAS("interrupts", "k7-hardware-interrupts"),
202 #define K7_KW_COUNT "count"
203 #define K7_KW_EDGE "edge"
204 #define K7_KW_INV "inv"
205 #define K7_KW_OS "os"
206 #define K7_KW_UNITMASK "unitmask"
207 #define K7_KW_USR "usr"
210 k7_allocate_pmc(enum pmc_event pe, char *ctrspec,
211 struct pmc_op_pmcallocate *pmc_config)
215 uint32_t count, unitmask;
217 pmc_config->pm_md.pm_amd.pm_amd_config = 0;
218 pmc_config->pm_caps |= PMC_CAP_READ;
220 if (pe == PMC_EV_TSC_TSC) {
221 /* TSC events must be unqualified. */
222 if (ctrspec && *ctrspec != '\0')
227 if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 ||
228 pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM ||
229 pe == PMC_EV_K7_DC_WRITEBACKS) {
231 unitmask = AMD_PMC_UNITMASK_MOESI;
233 unitmask = has_unitmask = 0;
235 pmc_config->pm_caps |= PMC_CAP_WRITE;
237 while ((p = strsep(&ctrspec, ",")) != NULL) {
238 if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) {
240 if (*++q == '\0') /* skip '=' */
243 count = strtol(q, &e, 0);
244 if (e == q || *e != '\0')
247 pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
248 pmc_config->pm_md.pm_amd.pm_amd_config |=
249 AMD_PMC_TO_COUNTER(count);
251 } else if (KWMATCH(p, K7_KW_EDGE)) {
252 pmc_config->pm_caps |= PMC_CAP_EDGE;
253 } else if (KWMATCH(p, K7_KW_INV)) {
254 pmc_config->pm_caps |= PMC_CAP_INVERT;
255 } else if (KWMATCH(p, K7_KW_OS)) {
256 pmc_config->pm_caps |= PMC_CAP_SYSTEM;
257 } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) {
258 if (has_unitmask == 0)
262 if (*++q == '\0') /* skip '=' */
265 while ((c = tolower(*q++)) != 0)
267 unitmask |= AMD_PMC_UNITMASK_M;
269 unitmask |= AMD_PMC_UNITMASK_O;
271 unitmask |= AMD_PMC_UNITMASK_E;
273 unitmask |= AMD_PMC_UNITMASK_S;
275 unitmask |= AMD_PMC_UNITMASK_I;
284 } else if (KWMATCH(p, K7_KW_USR)) {
285 pmc_config->pm_caps |= PMC_CAP_USER;
291 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
292 pmc_config->pm_md.pm_amd.pm_amd_config |=
293 AMD_PMC_TO_UNITMASK(unitmask);
302 #if defined(__amd64__) || defined(__i386__)
307 * These are very similar to AMD K7 PMCs, but support more kinds of
311 static struct pmc_event_alias k8_aliases[] = {
312 EV_ALIAS("branches", "k8-fr-retired-taken-branches"),
313 EV_ALIAS("branch-mispredicts",
314 "k8-fr-retired-taken-branches-mispredicted"),
315 EV_ALIAS("cycles", "tsc"),
316 EV_ALIAS("dc-misses", "k8-dc-miss"),
317 EV_ALIAS("ic-misses", "k8-ic-miss"),
318 EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"),
319 EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"),
320 EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"),
324 #define __K8MASK(N,V) PMCMASK(N,(1 << (V)))
330 /* fp dispatched fpu ops */
331 static const struct pmc_masks k8_mask_fdfo[] = {
332 __K8MASK(add-pipe-excluding-junk-ops, 0),
333 __K8MASK(multiply-pipe-excluding-junk-ops, 1),
334 __K8MASK(store-pipe-excluding-junk-ops, 2),
335 __K8MASK(add-pipe-junk-ops, 3),
336 __K8MASK(multiply-pipe-junk-ops, 4),
337 __K8MASK(store-pipe-junk-ops, 5),
341 /* ls segment register loads */
342 static const struct pmc_masks k8_mask_lsrl[] = {
353 /* ls locked operation */
354 static const struct pmc_masks k8_mask_llo[] = {
355 __K8MASK(locked-instructions, 0),
356 __K8MASK(cycles-in-request, 1),
357 __K8MASK(cycles-to-complete, 2),
361 /* dc refill from {l2,system} and dc copyback */
362 static const struct pmc_masks k8_mask_dc[] = {
363 __K8MASK(invalid, 0),
365 __K8MASK(exclusive, 2),
367 __K8MASK(modified, 4),
371 /* dc one bit ecc error */
372 static const struct pmc_masks k8_mask_dobee[] = {
373 __K8MASK(scrubber, 0),
374 __K8MASK(piggyback, 1),
378 /* dc dispatched prefetch instructions */
379 static const struct pmc_masks k8_mask_ddpi[] = {
386 /* dc dcache accesses by locks */
387 static const struct pmc_masks k8_mask_dabl[] = {
388 __K8MASK(accesses, 0),
393 /* bu internal l2 request */
394 static const struct pmc_masks k8_mask_bilr[] = {
395 __K8MASK(ic-fill, 0),
396 __K8MASK(dc-fill, 1),
397 __K8MASK(tlb-reload, 2),
398 __K8MASK(tag-snoop, 3),
399 __K8MASK(cancelled, 4),
403 /* bu fill request l2 miss */
404 static const struct pmc_masks k8_mask_bfrlm[] = {
405 __K8MASK(ic-fill, 0),
406 __K8MASK(dc-fill, 1),
407 __K8MASK(tlb-reload, 2),
411 /* bu fill into l2 */
412 static const struct pmc_masks k8_mask_bfil[] = {
413 __K8MASK(dirty-l2-victim, 0),
414 __K8MASK(victim-from-l2, 1),
418 /* fr retired fpu instructions */
419 static const struct pmc_masks k8_mask_frfi[] = {
421 __K8MASK(mmx-3dnow, 1),
422 __K8MASK(packed-sse-sse2, 2),
423 __K8MASK(scalar-sse-sse2, 3),
427 /* fr retired fastpath double op instructions */
428 static const struct pmc_masks k8_mask_frfdoi[] = {
429 __K8MASK(low-op-pos-0, 0),
430 __K8MASK(low-op-pos-1, 1),
431 __K8MASK(low-op-pos-2, 2),
435 /* fr fpu exceptions */
436 static const struct pmc_masks k8_mask_ffe[] = {
437 __K8MASK(x87-reclass-microfaults, 0),
438 __K8MASK(sse-retype-microfaults, 1),
439 __K8MASK(sse-reclass-microfaults, 2),
440 __K8MASK(sse-and-x87-microtraps, 3),
444 /* nb memory controller page access event */
445 static const struct pmc_masks k8_mask_nmcpae[] = {
446 __K8MASK(page-hit, 0),
447 __K8MASK(page-miss, 1),
448 __K8MASK(page-conflict, 2),
452 /* nb memory controller turnaround */
453 static const struct pmc_masks k8_mask_nmct[] = {
454 __K8MASK(dimm-turnaround, 0),
455 __K8MASK(read-to-write-turnaround, 1),
456 __K8MASK(write-to-read-turnaround, 2),
460 /* nb memory controller bypass saturation */
461 static const struct pmc_masks k8_mask_nmcbs[] = {
462 __K8MASK(memory-controller-hi-pri-bypass, 0),
463 __K8MASK(memory-controller-lo-pri-bypass, 1),
464 __K8MASK(dram-controller-interface-bypass, 2),
465 __K8MASK(dram-controller-queue-bypass, 3),
469 /* nb sized commands */
470 static const struct pmc_masks k8_mask_nsc[] = {
471 __K8MASK(nonpostwrszbyte, 0),
472 __K8MASK(nonpostwrszdword, 1),
473 __K8MASK(postwrszbyte, 2),
474 __K8MASK(postwrszdword, 3),
475 __K8MASK(rdszbyte, 4),
476 __K8MASK(rdszdword, 5),
477 __K8MASK(rdmodwr, 6),
481 /* nb probe result */
482 static const struct pmc_masks k8_mask_npr[] = {
483 __K8MASK(probe-miss, 0),
484 __K8MASK(probe-hit, 1),
485 __K8MASK(probe-hit-dirty-no-memory-cancel, 2),
486 __K8MASK(probe-hit-dirty-with-memory-cancel, 3),
490 /* nb hypertransport bus bandwidth */
491 static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */
492 __K8MASK(command, 0),
494 __K8MASK(buffer-release, 2),
501 #define K8_KW_COUNT "count"
502 #define K8_KW_EDGE "edge"
503 #define K8_KW_INV "inv"
504 #define K8_KW_MASK "mask"
505 #define K8_KW_OS "os"
506 #define K8_KW_USR "usr"
509 k8_allocate_pmc(enum pmc_event pe, char *ctrspec,
510 struct pmc_op_pmcallocate *pmc_config)
514 uint32_t count, evmask;
515 const struct pmc_masks *pm, *pmask;
517 pmc_config->pm_caps |= PMC_CAP_READ;
518 pmc_config->pm_md.pm_amd.pm_amd_config = 0;
520 if (pe == PMC_EV_TSC_TSC) {
521 /* TSC events must be unqualified. */
522 if (ctrspec && *ctrspec != '\0')
530 #define __K8SETMASK(M) pmask = k8_mask_##M
532 /* setup parsing tables */
534 case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
537 case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD:
540 case PMC_EV_K8_LS_LOCKED_OPERATION:
543 case PMC_EV_K8_DC_REFILL_FROM_L2:
544 case PMC_EV_K8_DC_REFILL_FROM_SYSTEM:
545 case PMC_EV_K8_DC_COPYBACK:
548 case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR:
551 case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS:
554 case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
557 case PMC_EV_K8_BU_INTERNAL_L2_REQUEST:
560 case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS:
563 case PMC_EV_K8_BU_FILL_INTO_L2:
566 case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
569 case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
572 case PMC_EV_K8_FR_FPU_EXCEPTIONS:
575 case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT:
578 case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND:
581 case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION:
584 case PMC_EV_K8_NB_SIZED_COMMANDS:
587 case PMC_EV_K8_NB_PROBE_RESULT:
590 case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH:
591 case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH:
592 case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH:
597 break; /* no options defined */
600 pmc_config->pm_caps |= PMC_CAP_WRITE;
602 while ((p = strsep(&ctrspec, ",")) != NULL) {
603 if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) {
605 if (*++q == '\0') /* skip '=' */
608 count = strtol(q, &e, 0);
609 if (e == q || *e != '\0')
612 pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
613 pmc_config->pm_md.pm_amd.pm_amd_config |=
614 AMD_PMC_TO_COUNTER(count);
616 } else if (KWMATCH(p, K8_KW_EDGE)) {
617 pmc_config->pm_caps |= PMC_CAP_EDGE;
618 } else if (KWMATCH(p, K8_KW_INV)) {
619 pmc_config->pm_caps |= PMC_CAP_INVERT;
620 } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) {
621 if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
623 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
624 } else if (KWMATCH(p, K8_KW_OS)) {
625 pmc_config->pm_caps |= PMC_CAP_SYSTEM;
626 } else if (KWMATCH(p, K8_KW_USR)) {
627 pmc_config->pm_caps |= PMC_CAP_USER;
632 /* other post processing */
634 case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
635 case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED:
636 case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS:
637 case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
638 case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
639 case PMC_EV_K8_FR_FPU_EXCEPTIONS:
640 /* XXX only available in rev B and later */
642 case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
643 /* XXX only available in rev C and later */
645 case PMC_EV_K8_LS_LOCKED_OPERATION:
646 /* XXX CPU Rev A,B evmask is to be zero */
647 if (evmask & (evmask - 1)) /* > 1 bit set */
650 evmask = 0x01; /* Rev C and later: #instrs */
651 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
655 if (evmask == 0 && pmask != NULL) {
656 for (pm = pmask; pm->pm_name; pm++)
657 evmask |= pm->pm_value;
658 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
662 if (pmc_config->pm_caps & PMC_CAP_QUALIFIER)
663 pmc_config->pm_md.pm_amd.pm_amd_config =
664 AMD_PMC_TO_UNITMASK(evmask);
671 #if defined(__amd64__) || defined(__i386__)
677 static struct pmc_event_alias p4_aliases[] = {
678 EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"),
679 EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"),
680 EV_ALIAS("cycles", "tsc"),
681 EV_ALIAS("instructions",
682 "p4-instr-retired,mask=nbogusntag+nbogustag"),
683 EV_ALIAS("unhalted-cycles", "p4-global-power-events"),
687 #define P4_KW_ACTIVE "active"
688 #define P4_KW_ACTIVE_ANY "any"
689 #define P4_KW_ACTIVE_BOTH "both"
690 #define P4_KW_ACTIVE_NONE "none"
691 #define P4_KW_ACTIVE_SINGLE "single"
692 #define P4_KW_BUSREQTYPE "busreqtype"
693 #define P4_KW_CASCADE "cascade"
694 #define P4_KW_EDGE "edge"
695 #define P4_KW_INV "complement"
696 #define P4_KW_OS "os"
697 #define P4_KW_MASK "mask"
698 #define P4_KW_PRECISE "precise"
699 #define P4_KW_TAG "tag"
700 #define P4_KW_THRESHOLD "threshold"
701 #define P4_KW_USR "usr"
703 #define __P4MASK(N,V) PMCMASK(N, (1 << (V)))
705 static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */
717 static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */
722 static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */
729 static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */
730 __P4MASK(st-rb-full, 2),
731 __P4MASK(64k-conf, 3),
735 static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */
741 static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */
742 __P4MASK(split-ld, 1),
746 static const struct pmc_masks p4_mask_spr[] = { /* store port replay */
747 __P4MASK(split-st, 1),
751 static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */
754 __P4MASK(partial-data, 4),
755 __P4MASK(unalgn-addr, 5),
759 static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */
765 static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */
766 __P4MASK(rd-2ndl-hits, 0),
767 __P4MASK(rd-2ndl-hite, 1),
768 __P4MASK(rd-2ndl-hitm, 2),
769 __P4MASK(rd-3rdl-hits, 3),
770 __P4MASK(rd-3rdl-hite, 4),
771 __P4MASK(rd-3rdl-hitm, 5),
772 __P4MASK(rd-2ndl-miss, 8),
773 __P4MASK(rd-3rdl-miss, 9),
774 __P4MASK(wr-2ndl-miss, 10),
778 static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */
779 __P4MASK(all-read, 5),
780 __P4MASK(all-write, 6),
784 __P4MASK(mem-wp, 10),
785 __P4MASK(mem-wb, 11),
788 __P4MASK(prefetch, 15),
792 static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */
793 __P4MASK(all-read, 5),
794 __P4MASK(all-write, 6),
798 __P4MASK(mem-wp, 10),
799 __P4MASK(mem-wb, 11),
802 __P4MASK(prefetch, 15),
806 static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */
807 __P4MASK(drdy-drv, 0),
808 __P4MASK(drdy-own, 1),
809 __P4MASK(drdy-other, 2),
810 __P4MASK(dbsy-drv, 3),
811 __P4MASK(dbsy-own, 4),
812 __P4MASK(dbsy-other, 5),
816 static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */
817 __P4MASK(req-type0, 0),
818 __P4MASK(req-type1, 1),
819 __P4MASK(req-len0, 2),
820 __P4MASK(req-len1, 3),
821 __P4MASK(req-io-type, 5),
822 __P4MASK(req-lock-type, 6),
823 __P4MASK(req-cache-type, 7),
824 __P4MASK(req-split-type, 8),
825 __P4MASK(req-dem-type, 9),
826 __P4MASK(req-ord-type, 10),
827 __P4MASK(mem-type0, 11),
828 __P4MASK(mem-type1, 12),
829 __P4MASK(mem-type2, 13),
833 static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */
838 static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */
843 static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */
848 static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */
853 static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */
858 static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */
863 static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */
868 static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */
873 static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */
879 static const struct pmc_masks p4_mask_gpe[] = { /* global power events */
880 __P4MASK(running, 0),
884 static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */
889 static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */
890 __P4MASK(from-tc-build, 0),
891 __P4MASK(from-tc-deliver, 1),
892 __P4MASK(from-rom, 2),
896 static const struct pmc_masks p4_mask_rmbt[] = {
897 /* retired mispred branch type */
898 __P4MASK(conditional, 1),
901 __P4MASK(indirect, 4),
905 static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */
906 __P4MASK(conditional, 1),
908 __P4MASK(retired, 3),
909 __P4MASK(indirect, 4),
913 static const struct pmc_masks p4_mask_rs[] = { /* resource stall */
918 static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */
919 __P4MASK(wcb-evicts, 0),
920 __P4MASK(wcb-full-evict, 1),
924 static const struct pmc_masks p4_mask_fee[] = { /* front end event */
930 static const struct pmc_masks p4_mask_ee[] = { /* execution event */
931 __P4MASK(nbogus0, 0),
932 __P4MASK(nbogus1, 1),
933 __P4MASK(nbogus2, 2),
934 __P4MASK(nbogus3, 3),
942 static const struct pmc_masks p4_mask_re[] = { /* replay event */
948 static const struct pmc_masks p4_mask_insret[] = { /* instr retired */
949 __P4MASK(nbogusntag, 0),
950 __P4MASK(nbogustag, 1),
951 __P4MASK(bogusntag, 2),
952 __P4MASK(bogustag, 3),
956 static const struct pmc_masks p4_mask_ur[] = { /* uops retired */
962 static const struct pmc_masks p4_mask_ut[] = { /* uop type */
963 __P4MASK(tagloads, 1),
964 __P4MASK(tagstores, 2),
968 static const struct pmc_masks p4_mask_br[] = { /* branch retired */
976 static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */
981 static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */
990 static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */
992 __P4MASK(moclear, 2),
993 __P4MASK(smclear, 3),
997 /* P4 event parser */
999 p4_allocate_pmc(enum pmc_event pe, char *ctrspec,
1000 struct pmc_op_pmcallocate *pmc_config)
1004 int count, has_tag, has_busreqtype, n;
1005 uint32_t evmask, cccractivemask;
1006 const struct pmc_masks *pm, *pmask;
1008 pmc_config->pm_caps |= PMC_CAP_READ;
1009 pmc_config->pm_md.pm_p4.pm_p4_cccrconfig =
1010 pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0;
1012 if (pe == PMC_EV_TSC_TSC) {
1013 /* TSC must not be further qualified */
1014 if (ctrspec && *ctrspec != '\0')
1021 cccractivemask = 0x3;
1022 has_tag = has_busreqtype = 0;
1023 pmc_config->pm_caps |= PMC_CAP_WRITE;
1025 #define __P4SETMASK(M) do { \
1026 pmask = p4_mask_##M; \
1030 case PMC_EV_P4_TC_DELIVER_MODE:
1033 case PMC_EV_P4_BPU_FETCH_REQUEST:
1036 case PMC_EV_P4_ITLB_REFERENCE:
1039 case PMC_EV_P4_MEMORY_CANCEL:
1040 __P4SETMASK(memcan);
1042 case PMC_EV_P4_MEMORY_COMPLETE:
1043 __P4SETMASK(memcomp);
1045 case PMC_EV_P4_LOAD_PORT_REPLAY:
1048 case PMC_EV_P4_STORE_PORT_REPLAY:
1051 case PMC_EV_P4_MOB_LOAD_REPLAY:
1054 case PMC_EV_P4_PAGE_WALK_TYPE:
1057 case PMC_EV_P4_BSQ_CACHE_REFERENCE:
1060 case PMC_EV_P4_IOQ_ALLOCATION:
1064 case PMC_EV_P4_IOQ_ACTIVE_ENTRIES:
1068 case PMC_EV_P4_FSB_DATA_ACTIVITY:
1071 case PMC_EV_P4_BSQ_ALLOCATION:
1074 case PMC_EV_P4_SSE_INPUT_ASSIST:
1077 case PMC_EV_P4_PACKED_SP_UOP:
1080 case PMC_EV_P4_PACKED_DP_UOP:
1083 case PMC_EV_P4_SCALAR_SP_UOP:
1086 case PMC_EV_P4_SCALAR_DP_UOP:
1089 case PMC_EV_P4_64BIT_MMX_UOP:
1092 case PMC_EV_P4_128BIT_MMX_UOP:
1093 __P4SETMASK(128bmu);
1095 case PMC_EV_P4_X87_FP_UOP:
1098 case PMC_EV_P4_X87_SIMD_MOVES_UOP:
1101 case PMC_EV_P4_GLOBAL_POWER_EVENTS:
1104 case PMC_EV_P4_TC_MS_XFER:
1107 case PMC_EV_P4_UOP_QUEUE_WRITES:
1110 case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE:
1113 case PMC_EV_P4_RETIRED_BRANCH_TYPE:
1116 case PMC_EV_P4_RESOURCE_STALL:
1119 case PMC_EV_P4_WC_BUFFER:
1122 case PMC_EV_P4_BSQ_ACTIVE_ENTRIES:
1123 case PMC_EV_P4_B2B_CYCLES:
1125 case PMC_EV_P4_SNOOP:
1126 case PMC_EV_P4_RESPONSE:
1128 case PMC_EV_P4_FRONT_END_EVENT:
1131 case PMC_EV_P4_EXECUTION_EVENT:
1134 case PMC_EV_P4_REPLAY_EVENT:
1137 case PMC_EV_P4_INSTR_RETIRED:
1138 __P4SETMASK(insret);
1140 case PMC_EV_P4_UOPS_RETIRED:
1143 case PMC_EV_P4_UOP_TYPE:
1146 case PMC_EV_P4_BRANCH_RETIRED:
1149 case PMC_EV_P4_MISPRED_BRANCH_RETIRED:
1152 case PMC_EV_P4_X87_ASSIST:
1155 case PMC_EV_P4_MACHINE_CLEAR:
1156 __P4SETMASK(machclr);
1162 /* process additional flags */
1163 while ((p = strsep(&ctrspec, ",")) != NULL) {
1164 if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) {
1166 if (*++q == '\0') /* skip '=' */
1169 if (strcmp(q, P4_KW_ACTIVE_NONE) == 0)
1170 cccractivemask = 0x0;
1171 else if (strcmp(q, P4_KW_ACTIVE_SINGLE) == 0)
1172 cccractivemask = 0x1;
1173 else if (strcmp(q, P4_KW_ACTIVE_BOTH) == 0)
1174 cccractivemask = 0x2;
1175 else if (strcmp(q, P4_KW_ACTIVE_ANY) == 0)
1176 cccractivemask = 0x3;
1180 } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) {
1181 if (has_busreqtype == 0)
1185 if (*++q == '\0') /* skip '=' */
1188 count = strtol(q, &e, 0);
1189 if (e == q || *e != '\0')
1191 evmask = (evmask & ~0x1F) | (count & 0x1F);
1192 } else if (KWMATCH(p, P4_KW_CASCADE))
1193 pmc_config->pm_caps |= PMC_CAP_CASCADE;
1194 else if (KWMATCH(p, P4_KW_EDGE))
1195 pmc_config->pm_caps |= PMC_CAP_EDGE;
1196 else if (KWMATCH(p, P4_KW_INV))
1197 pmc_config->pm_caps |= PMC_CAP_INVERT;
1198 else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) {
1199 if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
1201 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1202 } else if (KWMATCH(p, P4_KW_OS))
1203 pmc_config->pm_caps |= PMC_CAP_SYSTEM;
1204 else if (KWMATCH(p, P4_KW_PRECISE))
1205 pmc_config->pm_caps |= PMC_CAP_PRECISE;
1206 else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) {
1211 if (*++q == '\0') /* skip '=' */
1214 count = strtol(q, &e, 0);
1215 if (e == q || *e != '\0')
1218 pmc_config->pm_caps |= PMC_CAP_TAGGING;
1219 pmc_config->pm_md.pm_p4.pm_p4_escrconfig |=
1220 P4_ESCR_TO_TAG_VALUE(count);
1221 } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) {
1223 if (*++q == '\0') /* skip '=' */
1226 count = strtol(q, &e, 0);
1227 if (e == q || *e != '\0')
1230 pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
1231 pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &=
1232 ~P4_CCCR_THRESHOLD_MASK;
1233 pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |=
1234 P4_CCCR_TO_THRESHOLD(count);
1235 } else if (KWMATCH(p, P4_KW_USR))
1236 pmc_config->pm_caps |= PMC_CAP_USER;
1241 /* other post processing */
1242 if (pe == PMC_EV_P4_IOQ_ALLOCATION ||
1243 pe == PMC_EV_P4_FSB_DATA_ACTIVITY ||
1244 pe == PMC_EV_P4_BSQ_ALLOCATION)
1245 pmc_config->pm_caps |= PMC_CAP_EDGE;
1247 /* fill in thread activity mask */
1248 pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |=
1249 P4_CCCR_TO_ACTIVE_THREAD(cccractivemask);
1252 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1255 case PMC_EV_P4_FSB_DATA_ACTIVITY:
1256 if ((evmask & 0x06) == 0x06 ||
1257 (evmask & 0x18) == 0x18)
1258 return (-1); /* can't have own+other bits together */
1259 if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */
1262 case PMC_EV_P4_MACHINE_CLEAR:
1263 /* only one bit is allowed to be set */
1264 if ((evmask & (evmask - 1)) != 0)
1267 evmask = 0x1; /* 'CLEAR' */
1268 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1272 if (evmask == 0 && pmask) {
1273 for (pm = pmask; pm->pm_name; pm++)
1274 evmask |= pm->pm_value;
1275 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1279 pmc_config->pm_md.pm_p4.pm_p4_escrconfig =
1280 P4_ESCR_TO_EVENT_MASK(evmask);
1287 #if defined(__i386__)
1290 * Pentium style PMCs
1293 static struct pmc_event_alias p5_aliases[] = {
1294 EV_ALIAS("cycles", "tsc"),
1295 EV_ALIAS(NULL, NULL)
1299 p5_allocate_pmc(enum pmc_event pe, char *ctrspec,
1300 struct pmc_op_pmcallocate *pmc_config)
1302 return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */
1306 * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III,
1307 * and Pentium M CPUs.
1310 static struct pmc_event_alias p6_aliases[] = {
1311 EV_ALIAS("branches", "p6-br-inst-retired"),
1312 EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"),
1313 EV_ALIAS("cycles", "tsc"),
1314 EV_ALIAS("dc-misses", "p6-dcu-lines-in"),
1315 EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"),
1316 EV_ALIAS("instructions", "p6-inst-retired"),
1317 EV_ALIAS("interrupts", "p6-hw-int-rx"),
1318 EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"),
1319 EV_ALIAS(NULL, NULL)
1322 #define P6_KW_CMASK "cmask"
1323 #define P6_KW_EDGE "edge"
1324 #define P6_KW_INV "inv"
1325 #define P6_KW_OS "os"
1326 #define P6_KW_UMASK "umask"
1327 #define P6_KW_USR "usr"
1329 static struct pmc_masks p6_mask_mesi[] = {
1337 static struct pmc_masks p6_mask_mesihw[] = {
1342 PMCMASK(nonhw, 0x00),
1344 PMCMASK(both, 0x30),
1348 static struct pmc_masks p6_mask_hw[] = {
1349 PMCMASK(nonhw, 0x00),
1351 PMCMASK(both, 0x30),
1355 static struct pmc_masks p6_mask_any[] = {
1356 PMCMASK(self, 0x00),
1361 static struct pmc_masks p6_mask_ekp[] = {
1369 static struct pmc_masks p6_mask_pps[] = {
1370 PMCMASK(packed-and-scalar, 0x00),
1371 PMCMASK(scalar, 0x01),
1375 static struct pmc_masks p6_mask_mite[] = {
1376 PMCMASK(packed-multiply, 0x01),
1377 PMCMASK(packed-shift, 0x02),
1378 PMCMASK(pack, 0x04),
1379 PMCMASK(unpack, 0x08),
1380 PMCMASK(packed-logical, 0x10),
1381 PMCMASK(packed-arithmetic, 0x20),
1385 static struct pmc_masks p6_mask_fmt[] = {
1386 PMCMASK(mmxtofp, 0x00),
1387 PMCMASK(fptommx, 0x01),
1391 static struct pmc_masks p6_mask_sr[] = {
1399 static struct pmc_masks p6_mask_eet[] = {
1401 PMCMASK(freq, 0x02),
1405 static struct pmc_masks p6_mask_efur[] = {
1407 PMCMASK(loadop, 0x01),
1408 PMCMASK(stdsta, 0x02),
1412 static struct pmc_masks p6_mask_essir[] = {
1413 PMCMASK(sse-packed-single, 0x00),
1414 PMCMASK(sse-packed-single-scalar-single, 0x01),
1415 PMCMASK(sse2-packed-double, 0x02),
1416 PMCMASK(sse2-scalar-double, 0x03),
1420 static struct pmc_masks p6_mask_esscir[] = {
1421 PMCMASK(sse-packed-single, 0x00),
1422 PMCMASK(sse-scalar-single, 0x01),
1423 PMCMASK(sse2-packed-double, 0x02),
1424 PMCMASK(sse2-scalar-double, 0x03),
1428 /* P6 event parser */
1430 p6_allocate_pmc(enum pmc_event pe, char *ctrspec,
1431 struct pmc_op_pmcallocate *pmc_config)
1436 const struct pmc_masks *pm, *pmask;
1438 pmc_config->pm_caps |= PMC_CAP_READ;
1439 pmc_config->pm_md.pm_ppro.pm_ppro_config = 0;
1441 if (pe == PMC_EV_TSC_TSC) {
1442 if (ctrspec && *ctrspec != '\0')
1447 pmc_config->pm_caps |= PMC_CAP_WRITE;
1450 #define P6MASKSET(M) pmask = p6_mask_ ## M
1453 case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break;
1454 case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break;
1455 case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break;
1456 case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break;
1457 case PMC_EV_P6_BUS_DRDY_CLOCKS:
1458 case PMC_EV_P6_BUS_LOCK_CLOCKS:
1459 case PMC_EV_P6_BUS_TRAN_BRD:
1460 case PMC_EV_P6_BUS_TRAN_RFO:
1461 case PMC_EV_P6_BUS_TRANS_WB:
1462 case PMC_EV_P6_BUS_TRAN_IFETCH:
1463 case PMC_EV_P6_BUS_TRAN_INVAL:
1464 case PMC_EV_P6_BUS_TRAN_PWR:
1465 case PMC_EV_P6_BUS_TRANS_P:
1466 case PMC_EV_P6_BUS_TRANS_IO:
1467 case PMC_EV_P6_BUS_TRAN_DEF:
1468 case PMC_EV_P6_BUS_TRAN_BURST:
1469 case PMC_EV_P6_BUS_TRAN_ANY:
1470 case PMC_EV_P6_BUS_TRAN_MEM:
1471 P6MASKSET(any); break;
1472 case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED:
1473 case PMC_EV_P6_EMON_KNI_PREF_MISS:
1474 P6MASKSET(ekp); break;
1475 case PMC_EV_P6_EMON_KNI_INST_RETIRED:
1476 case PMC_EV_P6_EMON_KNI_COMP_INST_RET:
1477 P6MASKSET(pps); break;
1478 case PMC_EV_P6_MMX_INSTR_TYPE_EXEC:
1479 P6MASKSET(mite); break;
1480 case PMC_EV_P6_FP_MMX_TRANS:
1481 P6MASKSET(fmt); break;
1482 case PMC_EV_P6_SEG_RENAME_STALLS:
1483 case PMC_EV_P6_SEG_REG_RENAMES:
1484 P6MASKSET(sr); break;
1485 case PMC_EV_P6_EMON_EST_TRANS:
1486 P6MASKSET(eet); break;
1487 case PMC_EV_P6_EMON_FUSED_UOPS_RET:
1488 P6MASKSET(efur); break;
1489 case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED:
1490 P6MASKSET(essir); break;
1491 case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED:
1492 P6MASKSET(esscir); break;
1498 /* Pentium M PMCs have a few events with different semantics */
1499 if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) {
1500 if (pe == PMC_EV_P6_L2_LD ||
1501 pe == PMC_EV_P6_L2_LINES_IN ||
1502 pe == PMC_EV_P6_L2_LINES_OUT)
1504 else if (pe == PMC_EV_P6_L2_M_LINES_OUTM)
1508 /* Parse additional modifiers if present */
1509 while ((p = strsep(&ctrspec, ",")) != NULL) {
1510 if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) {
1512 if (*++q == '\0') /* skip '=' */
1514 count = strtol(q, &e, 0);
1515 if (e == q || *e != '\0')
1517 pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
1518 pmc_config->pm_md.pm_ppro.pm_ppro_config |=
1519 P6_EVSEL_TO_CMASK(count);
1520 } else if (KWMATCH(p, P6_KW_EDGE)) {
1521 pmc_config->pm_caps |= PMC_CAP_EDGE;
1522 } else if (KWMATCH(p, P6_KW_INV)) {
1523 pmc_config->pm_caps |= PMC_CAP_INVERT;
1524 } else if (KWMATCH(p, P6_KW_OS)) {
1525 pmc_config->pm_caps |= PMC_CAP_SYSTEM;
1526 } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) {
1528 if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
1530 if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS ||
1531 pe == PMC_EV_P6_BUS_LOCK_CLOCKS ||
1532 pe == PMC_EV_P6_BUS_TRAN_BRD ||
1533 pe == PMC_EV_P6_BUS_TRAN_RFO ||
1534 pe == PMC_EV_P6_BUS_TRAN_IFETCH ||
1535 pe == PMC_EV_P6_BUS_TRAN_INVAL ||
1536 pe == PMC_EV_P6_BUS_TRAN_PWR ||
1537 pe == PMC_EV_P6_BUS_TRAN_DEF ||
1538 pe == PMC_EV_P6_BUS_TRAN_BURST ||
1539 pe == PMC_EV_P6_BUS_TRAN_ANY ||
1540 pe == PMC_EV_P6_BUS_TRAN_MEM ||
1541 pe == PMC_EV_P6_BUS_TRANS_IO ||
1542 pe == PMC_EV_P6_BUS_TRANS_P ||
1543 pe == PMC_EV_P6_BUS_TRANS_WB ||
1544 pe == PMC_EV_P6_EMON_EST_TRANS ||
1545 pe == PMC_EV_P6_EMON_FUSED_UOPS_RET ||
1546 pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET ||
1547 pe == PMC_EV_P6_EMON_KNI_INST_RETIRED ||
1548 pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED ||
1549 pe == PMC_EV_P6_EMON_KNI_PREF_MISS ||
1550 pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED ||
1551 pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED ||
1552 pe == PMC_EV_P6_FP_MMX_TRANS)
1553 && (n > 1)) /* Only one mask keyword is allowed. */
1555 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1556 } else if (KWMATCH(p, P6_KW_USR)) {
1557 pmc_config->pm_caps |= PMC_CAP_USER;
1562 /* post processing */
1566 * The following events default to an evmask of 0
1569 /* default => 'self' */
1570 case PMC_EV_P6_BUS_DRDY_CLOCKS:
1571 case PMC_EV_P6_BUS_LOCK_CLOCKS:
1572 case PMC_EV_P6_BUS_TRAN_BRD:
1573 case PMC_EV_P6_BUS_TRAN_RFO:
1574 case PMC_EV_P6_BUS_TRANS_WB:
1575 case PMC_EV_P6_BUS_TRAN_IFETCH:
1576 case PMC_EV_P6_BUS_TRAN_INVAL:
1577 case PMC_EV_P6_BUS_TRAN_PWR:
1578 case PMC_EV_P6_BUS_TRANS_P:
1579 case PMC_EV_P6_BUS_TRANS_IO:
1580 case PMC_EV_P6_BUS_TRAN_DEF:
1581 case PMC_EV_P6_BUS_TRAN_BURST:
1582 case PMC_EV_P6_BUS_TRAN_ANY:
1583 case PMC_EV_P6_BUS_TRAN_MEM:
1585 /* default => 'nta' */
1586 case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED:
1587 case PMC_EV_P6_EMON_KNI_PREF_MISS:
1589 /* default => 'packed and scalar' */
1590 case PMC_EV_P6_EMON_KNI_INST_RETIRED:
1591 case PMC_EV_P6_EMON_KNI_COMP_INST_RET:
1593 /* default => 'mmx to fp transitions' */
1594 case PMC_EV_P6_FP_MMX_TRANS:
1596 /* default => 'SSE Packed Single' */
1597 case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED:
1598 case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED:
1600 /* default => 'all fused micro-ops' */
1601 case PMC_EV_P6_EMON_FUSED_UOPS_RET:
1603 /* default => 'all transitions' */
1604 case PMC_EV_P6_EMON_EST_TRANS:
1607 case PMC_EV_P6_MMX_UOPS_EXEC:
1608 evmask = 0x0F; /* only value allowed */
1613 * For all other events, set the default event mask
1614 * to a logical OR of all the allowed event mask bits.
1616 if (evmask == 0 && pmask) {
1617 for (pm = pmask; pm->pm_name; pm++)
1618 evmask |= pm->pm_value;
1619 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1625 if (pmc_config->pm_caps & PMC_CAP_QUALIFIER)
1626 pmc_config->pm_md.pm_ppro.pm_ppro_config |=
1627 P6_EVSEL_TO_UMASK(evmask);
1639 pmc_allocate(const char *ctrspec, enum pmc_mode mode,
1640 uint32_t flags, int cpu, pmc_id_t *pmcid)
1644 char *r, *spec_copy;
1645 const char *ctrname;
1646 const struct pmc_event_alias *p;
1647 struct pmc_op_pmcallocate pmc_config;
1652 if (mode != PMC_MODE_SS && mode != PMC_MODE_TS &&
1653 mode != PMC_MODE_SC && mode != PMC_MODE_TC) {
1658 /* replace an event alias with the canonical event specifier */
1659 if (pmc_mdep_event_aliases)
1660 for (p = pmc_mdep_event_aliases; p->pm_alias; p++)
1661 if (!strcmp(ctrspec, p->pm_alias)) {
1662 spec_copy = strdup(p->pm_spec);
1666 if (spec_copy == NULL)
1667 spec_copy = strdup(ctrspec);
1670 ctrname = strsep(&r, ",");
1672 /* look for the given counter name */
1673 for (pe = PMC_EVENT_FIRST; pe < (PMC_EVENT_LAST+1); pe++)
1674 if (!strcmp(ctrname, pmc_event_table[pe].pm_ev_name))
1677 if (pe > PMC_EVENT_LAST) {
1682 bzero(&pmc_config, sizeof(pmc_config));
1683 pmc_config.pm_ev = pmc_event_table[pe].pm_ev_code;
1684 pmc_config.pm_class = pmc_event_table[pe].pm_ev_class;
1685 pmc_config.pm_cpu = cpu;
1686 pmc_config.pm_mode = mode;
1687 pmc_config.pm_flags = flags;
1689 if (PMC_IS_SAMPLING_MODE(mode))
1690 pmc_config.pm_caps |= PMC_CAP_INTERRUPT;
1692 if (pmc_mdep_allocate_pmc(pe, r, &pmc_config) < 0) {
1697 if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0)
1700 *pmcid = pmc_config.pm_pmcid;
1712 pmc_attach(pmc_id_t pmc, pid_t pid)
1714 struct pmc_op_pmcattach pmc_attach_args;
1716 pmc_attach_args.pm_pmc = pmc;
1717 pmc_attach_args.pm_pid = pid;
1719 return (PMC_CALL(PMCATTACH, &pmc_attach_args));
1723 pmc_capabilities(pmc_id_t pmcid, uint32_t *caps)
1728 cl = PMC_ID_TO_CLASS(pmcid);
1729 for (i = 0; i < cpu_info.pm_nclass; i++)
1730 if (cpu_info.pm_classes[i].pm_class == cl) {
1731 *caps = cpu_info.pm_classes[i].pm_caps;
1739 pmc_configure_logfile(int fd)
1741 struct pmc_op_configurelog cla;
1744 if (PMC_CALL(CONFIGURELOG, &cla) < 0)
1750 pmc_cpuinfo(const struct pmc_cpuinfo **pci)
1752 if (pmc_syscall == -1) {
1762 pmc_detach(pmc_id_t pmc, pid_t pid)
1764 struct pmc_op_pmcattach pmc_detach_args;
1766 pmc_detach_args.pm_pmc = pmc;
1767 pmc_detach_args.pm_pid = pid;
1768 return (PMC_CALL(PMCDETACH, &pmc_detach_args));
1772 pmc_disable(int cpu, int pmc)
1774 struct pmc_op_pmcadmin ssa;
1778 ssa.pm_state = PMC_STATE_DISABLED;
1779 return (PMC_CALL(PMCADMIN, &ssa));
1783 pmc_enable(int cpu, int pmc)
1785 struct pmc_op_pmcadmin ssa;
1789 ssa.pm_state = PMC_STATE_FREE;
1790 return (PMC_CALL(PMCADMIN, &ssa));
1794 * Return a list of events known to a given PMC class. 'cl' is the
1795 * PMC class identifier, 'eventnames' is the returned list of 'const
1796 * char *' pointers pointing to the names of the events. 'nevents' is
1797 * the number of event name pointers returned.
1799 * The space for 'eventnames' is allocated using malloc(3). The caller
1800 * is responsible for freeing this space when done.
1803 pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
1808 const struct pmc_event_descr *ev;
1813 ev = &pmc_event_table[PMC_EV_TSC_TSC];
1817 ev = &pmc_event_table[PMC_EV_K7_FIRST];
1818 count = PMC_EV_K7_LAST - PMC_EV_K7_FIRST + 1;
1821 ev = &pmc_event_table[PMC_EV_K8_FIRST];
1822 count = PMC_EV_K8_LAST - PMC_EV_K8_FIRST + 1;
1825 ev = &pmc_event_table[PMC_EV_P5_FIRST];
1826 count = PMC_EV_P5_LAST - PMC_EV_P5_FIRST + 1;
1829 ev = &pmc_event_table[PMC_EV_P6_FIRST];
1830 count = PMC_EV_P6_LAST - PMC_EV_P6_FIRST + 1;
1833 ev = &pmc_event_table[PMC_EV_P4_FIRST];
1834 count = PMC_EV_P4_LAST - PMC_EV_P4_FIRST + 1;
1841 if ((names = malloc(count * sizeof(const char *))) == NULL)
1844 *eventnames = names;
1847 for (;count--; ev++, names++)
1848 *names = ev->pm_ev_name;
1853 pmc_flush_logfile(void)
1855 return (PMC_CALL(FLUSHLOG,0));
1859 pmc_get_driver_stats(struct pmc_driverstats *ds)
1861 struct pmc_op_getdriverstats gms;
1863 if (PMC_CALL(GETDRIVERSTATS, &gms) < 0)
1866 /* copy out fields in the current userland<->library interface */
1867 ds->pm_intr_ignored = gms.pm_intr_ignored;
1868 ds->pm_intr_processed = gms.pm_intr_processed;
1869 ds->pm_intr_bufferfull = gms.pm_intr_bufferfull;
1870 ds->pm_syscalls = gms.pm_syscalls;
1871 ds->pm_syscall_errors = gms.pm_syscall_errors;
1872 ds->pm_buffer_requests = gms.pm_buffer_requests;
1873 ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed;
1874 ds->pm_log_sweeps = gms.pm_log_sweeps;
1879 pmc_get_msr(pmc_id_t pmc, uint32_t *msr)
1881 struct pmc_op_getmsr gm;
1884 if (PMC_CALL(PMCGETMSR, &gm) < 0)
1893 int error, pmc_mod_id;
1895 uint32_t abi_version;
1896 struct module_stat pmc_modstat;
1897 struct pmc_op_getcpuinfo op_cpu_info;
1899 if (pmc_syscall != -1) /* already inited */
1902 /* retrieve the system call number from the KLD */
1903 if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0)
1906 pmc_modstat.version = sizeof(struct module_stat);
1907 if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0)
1910 pmc_syscall = pmc_modstat.data.intval;
1912 /* check the kernel module's ABI against our compiled-in version */
1913 abi_version = PMC_VERSION;
1914 if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0)
1915 return (pmc_syscall = -1);
1917 /* ignore patch & minor numbers for the comparision */
1918 if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) {
1919 errno = EPROGMISMATCH;
1920 return (pmc_syscall = -1);
1923 if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0)
1924 return (pmc_syscall = -1);
1926 cpu_info.pm_cputype = op_cpu_info.pm_cputype;
1927 cpu_info.pm_ncpu = op_cpu_info.pm_ncpu;
1928 cpu_info.pm_npmc = op_cpu_info.pm_npmc;
1929 cpu_info.pm_nclass = op_cpu_info.pm_nclass;
1930 for (n = 0; n < cpu_info.pm_nclass; n++)
1931 cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n];
1933 /* set parser pointer */
1934 switch (cpu_info.pm_cputype) {
1935 #if defined(__i386__)
1936 case PMC_CPU_AMD_K7:
1937 pmc_mdep_event_aliases = k7_aliases;
1938 pmc_mdep_allocate_pmc = k7_allocate_pmc;
1940 case PMC_CPU_INTEL_P5:
1941 pmc_mdep_event_aliases = p5_aliases;
1942 pmc_mdep_allocate_pmc = p5_allocate_pmc;
1944 case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */
1945 case PMC_CPU_INTEL_PII: /* similar PMCs. */
1946 case PMC_CPU_INTEL_PIII:
1947 case PMC_CPU_INTEL_PM:
1948 pmc_mdep_event_aliases = p6_aliases;
1949 pmc_mdep_allocate_pmc = p6_allocate_pmc;
1952 #if defined(__amd64__) || defined(__i386__)
1953 case PMC_CPU_INTEL_PIV:
1954 pmc_mdep_event_aliases = p4_aliases;
1955 pmc_mdep_allocate_pmc = p4_allocate_pmc;
1957 case PMC_CPU_AMD_K8:
1958 pmc_mdep_event_aliases = k8_aliases;
1959 pmc_mdep_allocate_pmc = k8_allocate_pmc;
1965 * Some kind of CPU this version of the library knows nothing
1966 * about. This shouldn't happen since the abi version check
1967 * should have caught this.
1970 return (pmc_syscall = -1);
1977 pmc_name_of_capability(enum pmc_caps cap)
1982 * 'cap' should have a single bit set and should be in
1985 if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST ||
1986 cap > PMC_CAP_LAST) {
1992 return (pmc_capability_names[i - 1]);
1996 pmc_name_of_class(enum pmc_class pc)
1998 if ((int) pc >= PMC_CLASS_FIRST &&
1999 pc <= PMC_CLASS_LAST)
2000 return (pmc_class_names[pc]);
2007 pmc_name_of_cputype(enum pmc_cputype cp)
2009 if ((int) cp >= PMC_CPU_FIRST &&
2011 return (pmc_cputype_names[cp]);
2017 pmc_name_of_disposition(enum pmc_disp pd)
2019 if ((int) pd >= PMC_DISP_FIRST &&
2020 pd <= PMC_DISP_LAST)
2021 return (pmc_disposition_names[pd]);
2028 pmc_name_of_event(enum pmc_event pe)
2030 if ((int) pe >= PMC_EVENT_FIRST &&
2031 pe <= PMC_EVENT_LAST)
2032 return (pmc_event_table[pe].pm_ev_name);
2039 pmc_name_of_mode(enum pmc_mode pm)
2041 if ((int) pm >= PMC_MODE_FIRST &&
2042 pm <= PMC_MODE_LAST)
2043 return (pmc_mode_names[pm]);
2050 pmc_name_of_state(enum pmc_state ps)
2052 if ((int) ps >= PMC_STATE_FIRST &&
2053 ps <= PMC_STATE_LAST)
2054 return (pmc_state_names[ps]);
2063 if (pmc_syscall == -1) {
2068 return (cpu_info.pm_ncpu);
2074 if (pmc_syscall == -1) {
2079 if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) {
2084 return (cpu_info.pm_npmc);
2088 pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci)
2091 struct pmc_op_getpmcinfo *pmci;
2093 if ((npmc = pmc_npmc(cpu)) < 0)
2096 nbytes = sizeof(struct pmc_op_getpmcinfo) +
2097 npmc * sizeof(struct pmc_info);
2099 if ((pmci = calloc(1, nbytes)) == NULL)
2104 if (PMC_CALL(GETPMCINFO, pmci) < 0) {
2109 /* kernel<->library, library<->userland interfaces are identical */
2110 *ppmci = (struct pmc_pmcinfo *) pmci;
2115 pmc_read(pmc_id_t pmc, pmc_value_t *value)
2117 struct pmc_op_pmcrw pmc_read_op;
2119 pmc_read_op.pm_pmcid = pmc;
2120 pmc_read_op.pm_flags = PMC_F_OLDVALUE;
2121 pmc_read_op.pm_value = -1;
2123 if (PMC_CALL(PMCRW, &pmc_read_op) < 0)
2126 *value = pmc_read_op.pm_value;
2131 pmc_release(pmc_id_t pmc)
2133 struct pmc_op_simple pmc_release_args;
2135 pmc_release_args.pm_pmcid = pmc;
2136 return (PMC_CALL(PMCRELEASE, &pmc_release_args));
2140 pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep)
2142 struct pmc_op_pmcrw pmc_rw_op;
2144 pmc_rw_op.pm_pmcid = pmc;
2145 pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE;
2146 pmc_rw_op.pm_value = newvalue;
2148 if (PMC_CALL(PMCRW, &pmc_rw_op) < 0)
2151 *oldvaluep = pmc_rw_op.pm_value;
2156 pmc_set(pmc_id_t pmc, pmc_value_t value)
2158 struct pmc_op_pmcsetcount sc;
2161 sc.pm_count = value;
2163 if (PMC_CALL(PMCSETCOUNT, &sc) < 0)
2169 pmc_start(pmc_id_t pmc)
2171 struct pmc_op_simple pmc_start_args;
2173 pmc_start_args.pm_pmcid = pmc;
2174 return (PMC_CALL(PMCSTART, &pmc_start_args));
2178 pmc_stop(pmc_id_t pmc)
2180 struct pmc_op_simple pmc_stop_args;
2182 pmc_stop_args.pm_pmcid = pmc;
2183 return (PMC_CALL(PMCSTOP, &pmc_stop_args));
2187 pmc_width(pmc_id_t pmcid, uint32_t *width)
2192 cl = PMC_ID_TO_CLASS(pmcid);
2193 for (i = 0; i < cpu_info.pm_nclass; i++)
2194 if (cpu_info.pm_classes[i].pm_class == cl) {
2195 *width = cpu_info.pm_classes[i].pm_width;
2203 pmc_write(pmc_id_t pmc, pmc_value_t value)
2205 struct pmc_op_pmcrw pmc_write_op;
2207 pmc_write_op.pm_pmcid = pmc;
2208 pmc_write_op.pm_flags = PMC_F_NEWVALUE;
2209 pmc_write_op.pm_value = value;
2210 return (PMC_CALL(PMCRW, &pmc_write_op));
2214 pmc_writelog(uint32_t userdata)
2216 struct pmc_op_writelog wl;
2218 wl.pm_userdata = userdata;
2219 return (PMC_CALL(WRITELOG, &wl));