|
Packit Service |
a1973e |
/* $Id: x86.c,v 1.1.2.6 2010/06/08 20:48:56 mikpe Exp $
|
|
Packit Service |
a1973e |
* x86-specific code.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* Copyright (C) 1999-2010 Mikael Pettersson
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
#include <stdio.h>
|
|
Packit Service |
a1973e |
#include <stdlib.h>
|
|
Packit Service |
a1973e |
#include "libperfctr.h"
|
|
Packit Service |
a1973e |
#include "arch.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int info_is_p4(const struct perfctr_info *info)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
switch (info->cpu_type) {
|
|
Packit Service |
a1973e |
#if !defined(__x86_64__)
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_P4:
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_P4M2:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
case PERFCTR_X86_INTEL_P4M3:
|
|
Packit Service |
a1973e |
return 1;
|
|
Packit Service |
a1973e |
default:
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
void do_print(FILE *resfile,
|
|
Packit Service |
a1973e |
const struct perfctr_info *info,
|
|
Packit Service |
a1973e |
const struct perfctr_cpu_control *cpu_control,
|
|
Packit Service |
a1973e |
const struct perfctr_sum_ctrs *sum)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
unsigned int nrctrs, i;
|
|
Packit Service |
a1973e |
int is_p4;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
is_p4 = info_is_p4(info);
|
|
Packit Service |
a1973e |
if (cpu_control->tsc_on)
|
|
Packit Service |
a1973e |
fprintf(resfile, "tsc\t\t\t\t%19lld\n", sum->tsc);
|
|
Packit Service |
a1973e |
nrctrs = cpu_control->nractrs;
|
|
Packit Service |
a1973e |
for(i = 0; i < nrctrs; ++i) {
|
|
Packit Service |
a1973e |
fprintf(resfile, "event 0x%08X",
|
|
Packit Service |
a1973e |
cpu_control->evntsel[i]);
|
|
Packit Service |
a1973e |
/* p4.escr[] overlaps evntsel_high[], but the output syntax
|
|
Packit Service |
a1973e |
is the same regardless of whether is_p4 is true or not */
|
|
Packit Service |
a1973e |
if (cpu_control->p4.escr[i])
|
|
Packit Service |
a1973e |
fprintf(resfile, "/0x%08X",
|
|
Packit Service |
a1973e |
cpu_control->p4.escr[i]);
|
|
Packit Service |
a1973e |
if (cpu_control->pmc_map[i] >= 18)
|
|
Packit Service |
a1973e |
fprintf(resfile, "@0x%08x\t", cpu_control->pmc_map[i]);
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
fprintf(resfile, "@%u\t\t", cpu_control->pmc_map[i]);
|
|
Packit Service |
a1973e |
fprintf(resfile, "%19lld\n", sum->pmc[i]);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* p4.pebs_{enable,matrix_vert} overlap nhlm.offcore_rsp[],
|
|
Packit Service |
a1973e |
and we want to adjust the output based on is_p4 */
|
|
Packit Service |
a1973e |
if (cpu_control->p4.pebs_enable)
|
|
Packit Service |
a1973e |
fprintf(resfile, "%s 0x%08X\n",
|
|
Packit Service |
a1973e |
is_p4 ? "PEBS_ENABLE" : "NHLM_OFFCORE_RSP_0",
|
|
Packit Service |
a1973e |
cpu_control->p4.pebs_enable);
|
|
Packit Service |
a1973e |
if (cpu_control->p4.pebs_matrix_vert)
|
|
Packit Service |
a1973e |
fprintf(resfile, "%s 0x%08X\n",
|
|
Packit Service |
a1973e |
is_p4 ? "PEBS_MATRIX_VERT" : "NHLM_OFFCORE_RSP_1",
|
|
Packit Service |
a1973e |
cpu_control->p4.pebs_matrix_vert);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
void do_arch_usage(void)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t--nhlm_offcore_rsp_0=<value>\tValue for OFFCORE_RSP_0 (Nehalem only)\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t--nhlm_offcore_rsp_1=<value>\tValue for OFFCORE_RSP_1 (Nehalem only)\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t--p4pe=<value>\t\t\tValue for PEBS_ENABLE (P4 only)\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t--p4_pebs_enable=<value>\tSame as --p4pe=<value>\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t--p4pmv=<value>\t\t\tValue for PEBS_MATRIX_VERT (P4 only)\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t--p4_pebs_matrix_vert=<value>\tSame as --p4pmv=<value>\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "Syntax of event specifiers:\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tevent ::= evntsel[/evntsel2][@pmc]\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tevntsel, evntsel2, and pmc are decimal or hexadecimal numbers.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t/ and @ are literal characters. [...] denotes an optional field.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tevntsel is the primary processor-specific event selection code\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tto use for this counter. This field is mandatory.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tevntsel2 provides auxiliary event selection code to use for this\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tcounter. Currently only used for P4 and AMD Family 10h, on other\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tprocessors this field should be omitted.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tpmc describes which CPU counter to use for this event.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tBy default the events use counters 0 and up in the order listed.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tOn Core2, the fixed-function performance counters are numbered\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t0x40000000 to 0x40000002. To use them, explicit counter assignment\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tvia the @pmc notation is mandatory.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tOn Core2, a fixed-function performance counter has an evntsel\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tjust like a programmable performance counter has, but only the\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tCPL (bits 16 and 17) and Enable (bit 22) fields are relevant.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t(The INT field (bit 20) is also honoured, but perfex cannot set\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tup interrupt-mode counting, so it should not be specified.)\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tAtom is similar to Core2, but appears to only support a single\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t(the first) fixed-function counter.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tOn AMD Family 10h, evntsel is written to the low 32 bits of the\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tcounter's EVNTSEL register, and evntsel2 is written to the high\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\t32 bits of that register. Only a few events require evntsel2.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tOn a P4, evntsel is written to the counter's CCCR register.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tOn a P4, evntsel2 is written to the counter's ESCR register.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tOn P4, each event is compatible with only a small subset of the\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tcounters, and explicit counter assignment via @pmc is mandatory.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tOn P4, bit 31 should be set in pmc to enable 'fast rdpmc'.\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\n");
|
|
Packit Service |
a1973e |
fprintf(stderr, "\tVIA C3 accepts a single event only, but it must use counter 1.\n");
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int parse_event_spec(const char *arg, unsigned int *evntsel,
|
|
Packit Service |
a1973e |
unsigned int *escr, unsigned int *pmc)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
char *endp;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
*evntsel = my_strtoul(arg, &endp);
|
|
Packit Service |
a1973e |
if (endp[0] != '/') {
|
|
Packit Service |
a1973e |
*escr = 0;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
arg = endp + 1;
|
|
Packit Service |
a1973e |
*escr = my_strtoul(arg, &endp);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (endp[0] != '@') {
|
|
Packit Service |
a1973e |
*pmc = (unsigned int)-1;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
arg = endp + 1;
|
|
Packit Service |
a1973e |
*pmc = my_strtoul(arg, &endp);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return endp[0] != '\0';
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
unsigned int do_event_spec(unsigned int n,
|
|
Packit Service |
a1973e |
const char *arg,
|
|
Packit Service |
a1973e |
struct perfctr_cpu_control *cpu_control)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
unsigned int spec_evntsel, spec_escr, spec_pmc;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (parse_event_spec(arg, &spec_evntsel, &spec_escr, &spec_pmc)) {
|
|
Packit Service |
a1973e |
fprintf(stderr, "perfex: invalid event specifier: '%s'\n", arg);
|
|
Packit Service |
a1973e |
exit(1);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (n >= ARRAY_SIZE(cpu_control->evntsel)) {
|
|
Packit Service |
a1973e |
fprintf(stderr, "perfex: too many event specifiers\n");
|
|
Packit Service |
a1973e |
exit(1);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (spec_pmc == (unsigned int)-1)
|
|
Packit Service |
a1973e |
spec_pmc = n;
|
|
Packit Service |
a1973e |
cpu_control->evntsel[n] = spec_evntsel;
|
|
Packit Service |
a1973e |
cpu_control->p4.escr[n] = spec_escr;
|
|
Packit Service |
a1973e |
cpu_control->pmc_map[n] = spec_pmc;
|
|
Packit Service |
a1973e |
cpu_control->nractrs = ++n;
|
|
Packit Service |
a1973e |
return n;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int parse_value(const char *arg, unsigned int *value)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
char *endp;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
*value = my_strtoul(arg, &endp);
|
|
Packit Service |
a1973e |
return endp[0] != '\0';
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int do_arch_option(int ch,
|
|
Packit Service |
a1973e |
const char *arg,
|
|
Packit Service |
a1973e |
struct perfctr_cpu_control *cpu_control)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
unsigned int spec_value;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
switch (ch) {
|
|
Packit Service |
a1973e |
case 1:
|
|
Packit Service |
a1973e |
if (parse_value(arg, &spec_value)) {
|
|
Packit Service |
a1973e |
fprintf(stderr, "perfex: invalid value: '%s'\n", arg);
|
|
Packit Service |
a1973e |
exit(1);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
cpu_control->p4.pebs_enable = spec_value;
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
case 2:
|
|
Packit Service |
a1973e |
if (parse_value(arg, &spec_value)) {
|
|
Packit Service |
a1973e |
fprintf(stderr, "perfex: invalid value: '%s'\n", arg);
|
|
Packit Service |
a1973e |
exit(1);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
cpu_control->p4.pebs_matrix_vert = spec_value;
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return -1;
|
|
Packit Service |
a1973e |
}
|