|
Packit |
577717 |
/* $Id: x86.c,v 1.23 2007/10/06 13:02:07 mikpe Exp $
|
|
Packit |
577717 |
* x86-specific perfctr library procedures.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (C) 1999-2007 Mikael Pettersson
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <errno.h>
|
|
Packit |
577717 |
#include <asm/unistd.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <string.h> /* memset() */
|
|
Packit |
577717 |
#include "libperfctr.h"
|
|
Packit |
577717 |
#include "x86.h"
|
|
Packit |
577717 |
#include "x86_cpuinfo.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static unsigned int __NR_vperfctr_open;
|
|
Packit |
577717 |
#define __NR_vperfctr_control (__NR_vperfctr_open+1)
|
|
Packit |
577717 |
#define __NR_vperfctr_write (__NR_vperfctr_open+2)
|
|
Packit |
577717 |
#define __NR_vperfctr_read (__NR_vperfctr_open+3)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <unistd.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void init_sys_vperfctr(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (!__NR_vperfctr_open) {
|
|
Packit |
577717 |
unsigned int nr;
|
|
Packit |
577717 |
unsigned int kver = perfctr_linux_version_code();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(__x86_64__)
|
|
Packit |
577717 |
if (kver >= PERFCTR_KERNEL_VERSION(2,6,18))
|
|
Packit |
577717 |
nr = 286;
|
|
Packit |
577717 |
else if (kver >= PERFCTR_KERNEL_VERSION(2,6,16))
|
|
Packit |
577717 |
nr = 280;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
nr = 257;
|
|
Packit |
577717 |
#elif defined(__i386__)
|
|
Packit |
577717 |
if (kver >= PERFCTR_KERNEL_VERSION(2,6,18))
|
|
Packit |
577717 |
nr = 325;
|
|
Packit |
577717 |
else if (kver >= PERFCTR_KERNEL_VERSION(2,6,16))
|
|
Packit |
577717 |
nr = 318;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
nr = 296;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
__NR_vperfctr_open = nr;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* The actual syscalls.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int _sys_vperfctr_open(int fd_unused, int tid, int creat)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
init_sys_vperfctr();
|
|
Packit |
577717 |
return syscall(__NR_vperfctr_open, tid, creat);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int _sys_vperfctr_control(int fd, unsigned int cmd)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
init_sys_vperfctr();
|
|
Packit |
577717 |
return syscall(__NR_vperfctr_control, fd, cmd);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int _sys_vperfctr_write(int fd, unsigned int domain, const void *arg, unsigned int argbytes)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
init_sys_vperfctr();
|
|
Packit |
577717 |
return syscall(__NR_vperfctr_write, fd, domain, arg, argbytes);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int _sys_vperfctr_read(int fd, unsigned int domain, void *arg, unsigned int argbytes)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
init_sys_vperfctr();
|
|
Packit |
577717 |
return syscall(__NR_vperfctr_read, fd, domain, arg, argbytes);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Simple syscall wrappers.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int _sys_vperfctr_read_sum(int fd, struct perfctr_sum_ctrs *arg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return _sys_vperfctr_read(fd, VPERFCTR_DOMAIN_SUM, arg, sizeof(*arg));
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int _sys_vperfctr_read_children(int fd, struct perfctr_sum_ctrs *arg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return _sys_vperfctr_read(fd, VPERFCTR_DOMAIN_CHILDREN, arg, sizeof(*arg));
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int _sys_vperfctr_unlink(int fd)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return _sys_vperfctr_control(fd, VPERFCTR_CONTROL_UNLINK);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int _sys_vperfctr_iresume(int fd)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return _sys_vperfctr_control(fd, VPERFCTR_CONTROL_RESUME);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Complex syscall wrappers, for transmitting control data
|
|
Packit |
577717 |
* in CPU family specific formats.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define MSR_P5_CESR 0x11
|
|
Packit |
577717 |
#define MSR_P6_PERFCTR0 0xC1 /* .. 0xC2 */
|
|
Packit |
577717 |
#define MSR_P6_EVNTSEL0 0x186 /* .. 0x187 */
|
|
Packit |
577717 |
#define MSR_K7_EVNTSEL0 0xC0010000 /* .. 0xC0010003 */
|
|
Packit |
577717 |
#define MSR_K7_PERFCTR0 0xC0010004 /* .. 0xC0010007 */
|
|
Packit |
577717 |
#define MSR_P4_PERFCTR0 0x300 /* .. 0x311 */
|
|
Packit |
577717 |
#define MSR_P4_CCCR0 0x360 /* .. 0x371 */
|
|
Packit |
577717 |
#define MSR_P4_ESCR0 0x3A0 /* .. 0x3E1, with some gaps */
|
|
Packit |
577717 |
#define MSR_P4_PEBS_ENABLE 0x3F1
|
|
Packit |
577717 |
#define MSR_P4_PEBS_MATRIX_VERT 0x3F2
|
|
Packit |
577717 |
#define P4_CCCR_ESCR_SELECT(X) (((X) >> 13) & 0x7)
|
|
Packit |
577717 |
#define P4_FAST_RDPMC 0x80000000
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if 0
|
|
Packit |
577717 |
static void show_regs(const struct perfctr_cpu_reg *regs, unsigned int n)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fprintf(stderr, "CPU Register Values:\n");
|
|
Packit |
577717 |
for(i = 0; i < n; ++i)
|
|
Packit |
577717 |
fprintf(stderr, "MSR %#x\t0x%08x\n", regs[i].nr, regs[i].value);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
#define show_regs(regs, n) do{}while(0)
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int read_packet(int fd, unsigned int domain, void *arg, unsigned int argbytes)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = _sys_vperfctr_read(fd, domain, arg, argbytes);
|
|
Packit |
577717 |
if (ret != argbytes && ret >= 0) {
|
|
Packit |
577717 |
errno = EPROTO;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if !defined(__x86_64__)
|
|
Packit |
577717 |
static int p5_write_regs(int fd, const struct perfctr_cpu_control *arg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
struct perfctr_cpu_reg reg;
|
|
Packit |
577717 |
unsigned short cesr_half[2];
|
|
Packit |
577717 |
unsigned int i, pmc;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!arg->nractrs)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
memset(cesr_half, 0, sizeof cesr_half);
|
|
Packit |
577717 |
for(i = 0; i < arg->nractrs; ++i) {
|
|
Packit |
577717 |
pmc = arg->pmc_map[i];
|
|
Packit |
577717 |
if (pmc > 1) {
|
|
Packit |
577717 |
errno = EINVAL;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
cesr_half[pmc] = arg->evntsel[i];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
reg.nr = MSR_P5_CESR;
|
|
Packit |
577717 |
reg.value = (cesr_half[1] << 16) | cesr_half[0];
|
|
Packit |
577717 |
show_regs(®, 1);
|
|
Packit |
577717 |
return _sys_vperfctr_write(fd, PERFCTR_DOMAIN_CPU_REGS, ®, sizeof reg);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int p5_read_regs(int fd, struct perfctr_cpu_control *arg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
struct perfctr_cpu_reg reg;
|
|
Packit |
577717 |
unsigned short cesr_half[2];
|
|
Packit |
577717 |
unsigned int i, pmc;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!arg->nractrs)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
reg.nr = MSR_P5_CESR;
|
|
Packit |
577717 |
ret = read_packet(fd, PERFCTR_DOMAIN_CPU_REGS, ®, sizeof reg);
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
show_regs(®, 1);
|
|
Packit |
577717 |
cesr_half[0] = reg.value & 0xffff;
|
|
Packit |
577717 |
cesr_half[1] = reg.value >> 16;
|
|
Packit |
577717 |
for(i = 0; i < arg->nractrs; ++i) {
|
|
Packit |
577717 |
pmc = arg->pmc_map[i];
|
|
Packit |
577717 |
if (pmc > 1) {
|
|
Packit |
577717 |
errno = EINVAL;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
arg->evntsel[i] = cesr_half[pmc];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int p6_like_read_write_regs(int fd, struct perfctr_cpu_control *control,
|
|
Packit |
577717 |
unsigned int msr_evntsel0, unsigned int msr_perfctr0,
|
|
Packit |
577717 |
int do_write)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
struct perfctr_cpu_reg regs[4+4];
|
|
Packit |
577717 |
unsigned int nrctrs, nractrs, pmc_mask, nr_regs, i, pmc;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
nractrs = control->nractrs;
|
|
Packit |
577717 |
nrctrs = nractrs + control->nrictrs;
|
|
Packit |
577717 |
if (nrctrs < nractrs || nrctrs > 4) {
|
|
Packit |
577717 |
errno = EINVAL;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!nrctrs)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
nr_regs = 0;
|
|
Packit |
577717 |
pmc_mask = 0;
|
|
Packit |
577717 |
for(i = 0; i < nrctrs; ++i) {
|
|
Packit |
577717 |
pmc = control->pmc_map[i];
|
|
Packit |
577717 |
if (pmc >= 4 || (pmc_mask & (1<
|
|
Packit |
577717 |
errno = EINVAL;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pmc_mask |= (1<
|
|
Packit |
577717 |
regs[nr_regs].nr = msr_evntsel0 + pmc;
|
|
Packit |
577717 |
regs[nr_regs].value = control->evntsel[i];
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
if (i >= nractrs) {
|
|
Packit |
577717 |
regs[nr_regs].nr = msr_perfctr0 + pmc;
|
|
Packit |
577717 |
regs[nr_regs].value = control->ireset[i];
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (do_write) {
|
|
Packit |
577717 |
show_regs(regs, nr_regs);
|
|
Packit |
577717 |
return _sys_vperfctr_write(fd, PERFCTR_DOMAIN_CPU_REGS, regs, nr_regs*sizeof(regs[0]));
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
ret = read_packet(fd, PERFCTR_DOMAIN_CPU_REGS, regs, nr_regs*sizeof(regs[0]));
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
show_regs(regs, nr_regs);
|
|
Packit |
577717 |
nr_regs = 0;
|
|
Packit |
577717 |
for(i = 0; i < nrctrs; ++i) {
|
|
Packit |
577717 |
control->evntsel[i] = regs[nr_regs].value;
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
if (i >= nractrs) {
|
|
Packit |
577717 |
control->ireset[i] = regs[nr_regs].value;
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Table 15-4 in the IA32 Volume 3 manual contains a 18x8 entry mapping
|
|
Packit |
577717 |
* from counter/CCCR number (0-17) and ESCR SELECT value (0-7) to the
|
|
Packit |
577717 |
* actual ESCR MSR number. This mapping contains some repeated patterns,
|
|
Packit |
577717 |
* so we can compact it to a 4x8 table of MSR offsets:
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* 1. CCCRs 16 and 17 are mapped just like CCCRs 13 and 14, respectively.
|
|
Packit |
577717 |
* Thus, we only consider the 16 CCCRs 0-15.
|
|
Packit |
577717 |
* 2. The CCCRs are organised in pairs, and both CCCRs in a pair use the
|
|
Packit |
577717 |
* same mapping. Thus, we only consider the 8 pairs 0-7.
|
|
Packit |
577717 |
* 3. In each pair of pairs, the second odd-numbered pair has the same domain
|
|
Packit |
577717 |
* as the first even-numbered pair, and the range is 1+ the range of the
|
|
Packit |
577717 |
* the first even-numbered pair. For example, CCCR(0) and (1) map ESCR
|
|
Packit |
577717 |
* SELECT(7) to 0x3A0, and CCCR(2) and (3) map it to 0x3A1.
|
|
Packit |
577717 |
* The only exception is that pair (7) [CCCRs 14 and 15] does not have
|
|
Packit |
577717 |
* ESCR SELECT(3) in its domain, like pair (6) [CCCRs 12 and 13] has.
|
|
Packit |
577717 |
* NOTE: Revisions of IA32 Volume 3 older than #245472-007 had an error
|
|
Packit |
577717 |
* in this table: CCCRs 12, 13, and 16 had their mappings for ESCR SELECT
|
|
Packit |
577717 |
* values 2 and 3 swapped.
|
|
Packit |
577717 |
* 4. All MSR numbers are on the form 0x3??. Instead of storing these as
|
|
Packit |
577717 |
* 16-bit numbers, the table only stores the 8-bit offsets from 0x300.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static const unsigned char p4_cccr_escr_map[4][8] = {
|
|
Packit |
577717 |
/* 0x00 and 0x01 as is, 0x02 and 0x03 are +1 */
|
|
Packit |
577717 |
[0x00/4] { [7] 0xA0,
|
|
Packit |
577717 |
[6] 0xA2,
|
|
Packit |
577717 |
[2] 0xAA,
|
|
Packit |
577717 |
[4] 0xAC,
|
|
Packit |
577717 |
[0] 0xB2,
|
|
Packit |
577717 |
[1] 0xB4,
|
|
Packit |
577717 |
[3] 0xB6,
|
|
Packit |
577717 |
[5] 0xC8, },
|
|
Packit |
577717 |
/* 0x04 and 0x05 as is, 0x06 and 0x07 are +1 */
|
|
Packit |
577717 |
[0x04/4] { [0] 0xC0,
|
|
Packit |
577717 |
[2] 0xC2,
|
|
Packit |
577717 |
[1] 0xC4, },
|
|
Packit |
577717 |
/* 0x08 and 0x09 as is, 0x0A and 0x0B are +1 */
|
|
Packit |
577717 |
[0x08/4] { [1] 0xA4,
|
|
Packit |
577717 |
[0] 0xA6,
|
|
Packit |
577717 |
[5] 0xA8,
|
|
Packit |
577717 |
[2] 0xAE,
|
|
Packit |
577717 |
[3] 0xB0, },
|
|
Packit |
577717 |
/* 0x0C, 0x0D, and 0x10 as is,
|
|
Packit |
577717 |
0x0E, 0x0F, and 0x11 are +1 except [3] is not in the domain */
|
|
Packit |
577717 |
[0x0C/4] { [4] 0xB8,
|
|
Packit |
577717 |
[5] 0xCC,
|
|
Packit |
577717 |
[6] 0xE0,
|
|
Packit |
577717 |
[0] 0xBA,
|
|
Packit |
577717 |
[2] 0xBC,
|
|
Packit |
577717 |
[3] 0xBE,
|
|
Packit |
577717 |
[1] 0xCA, },
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static unsigned int p4_escr_addr(unsigned int pmc, unsigned int cccr_val)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int escr_select, pair, escr_offset;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
escr_select = P4_CCCR_ESCR_SELECT(cccr_val);
|
|
Packit |
577717 |
if (pmc > 0x11)
|
|
Packit |
577717 |
return 0; /* pmc range error */
|
|
Packit |
577717 |
if (pmc > 0x0F)
|
|
Packit |
577717 |
pmc -= 3; /* 0 <= pmc <= 0x0F */
|
|
Packit |
577717 |
pair = pmc / 2; /* 0 <= pair <= 7 */
|
|
Packit |
577717 |
escr_offset = p4_cccr_escr_map[pair / 2][escr_select];
|
|
Packit |
577717 |
if (!escr_offset || (pair == 7 && escr_select == 3))
|
|
Packit |
577717 |
return 0; /* ESCR SELECT range error */
|
|
Packit |
577717 |
return escr_offset + (pair & 1) + 0x300;
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int p4_read_write_regs(int fd, struct perfctr_cpu_control *control, int do_write)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
struct perfctr_cpu_reg regs[18*3+2];
|
|
Packit |
577717 |
unsigned int nrctrs, nractrs, pmc_mask, nr_regs, i, pmc, escr_addr;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
nractrs = control->nractrs;
|
|
Packit |
577717 |
nrctrs = nractrs + control->nrictrs;
|
|
Packit |
577717 |
if (nrctrs < nractrs || nrctrs > 18) {
|
|
Packit |
577717 |
errno = EINVAL;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!nrctrs)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
nr_regs = 0;
|
|
Packit |
577717 |
pmc_mask = 0;
|
|
Packit |
577717 |
for(i = 0; i < nrctrs; ++i) {
|
|
Packit |
577717 |
pmc = control->pmc_map[i] & ~P4_FAST_RDPMC;
|
|
Packit |
577717 |
if (pmc >= 18 || (pmc_mask & (1<
|
|
Packit |
577717 |
errno = EINVAL;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pmc_mask |= (1<
|
|
Packit |
577717 |
regs[nr_regs].nr = MSR_P4_CCCR0 + pmc;
|
|
Packit |
577717 |
regs[nr_regs].value = control->evntsel[i];
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
escr_addr = p4_escr_addr(pmc, control->evntsel[i]);
|
|
Packit |
577717 |
if (!escr_addr) {
|
|
Packit |
577717 |
errno = EINVAL;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
regs[nr_regs].nr = escr_addr;
|
|
Packit |
577717 |
regs[nr_regs].value = control->p4.escr[i];
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
if (i >= nractrs) {
|
|
Packit |
577717 |
regs[nr_regs].nr = MSR_P4_PERFCTR0 + pmc;
|
|
Packit |
577717 |
regs[nr_regs].value = control->ireset[i];
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
regs[nr_regs].nr = MSR_P4_PEBS_ENABLE;
|
|
Packit |
577717 |
regs[nr_regs].value = control->p4.pebs_enable;
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
regs[nr_regs].nr = MSR_P4_PEBS_MATRIX_VERT;
|
|
Packit |
577717 |
regs[nr_regs].value = control->p4.pebs_matrix_vert;
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
if (do_write) {
|
|
Packit |
577717 |
show_regs(regs, nr_regs);
|
|
Packit |
577717 |
return _sys_vperfctr_write(fd, PERFCTR_DOMAIN_CPU_REGS, regs, nr_regs*sizeof(regs[0]));
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
ret = read_packet(fd, PERFCTR_DOMAIN_CPU_REGS, regs, nr_regs*sizeof(regs[0]));
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
show_regs(regs, nr_regs);
|
|
Packit |
577717 |
nr_regs = 0;
|
|
Packit |
577717 |
for(i = 0; i < nrctrs; ++i) {
|
|
Packit |
577717 |
control->evntsel[i] = regs[nr_regs].value;
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
control->p4.escr[i] = regs[nr_regs].value;
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
if (i >= nractrs) {
|
|
Packit |
577717 |
control->ireset[i] = regs[nr_regs].value;
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
control->p4.pebs_enable = regs[nr_regs].value;
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
control->p4.pebs_matrix_vert = regs[nr_regs].value;
|
|
Packit |
577717 |
++nr_regs;
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int write_cpu_regs(int fd, unsigned int cpu_type, struct perfctr_cpu_control *arg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch (cpu_type) {
|
|
Packit |
577717 |
case PERFCTR_X86_GENERIC:
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
#if !defined(__x86_64__)
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P5:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P5MMX:
|
|
Packit |
577717 |
case PERFCTR_X86_CYRIX_MII:
|
|
Packit |
577717 |
case PERFCTR_X86_WINCHIP_C6:
|
|
Packit |
577717 |
case PERFCTR_X86_WINCHIP_2:
|
|
Packit |
577717 |
return p5_write_regs(fd, arg);
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P6:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PII:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PIII:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PENTM:
|
|
Packit |
577717 |
case PERFCTR_X86_VIA_C3:
|
|
Packit |
577717 |
return p6_like_read_write_regs(fd, arg, MSR_P6_EVNTSEL0, MSR_P6_PERFCTR0, 1);
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K7:
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8:
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8C:
|
|
Packit |
577717 |
return p6_like_read_write_regs(fd, arg, MSR_K7_EVNTSEL0, MSR_K7_PERFCTR0, 1);
|
|
Packit |
577717 |
#if !defined(__x86_64__)
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4M2:
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4M3:
|
|
Packit |
577717 |
return p4_read_write_regs(fd, arg, 1);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
fprintf(stderr, "unable to write control registers for cpu type %u\n",
|
|
Packit |
577717 |
cpu_type);
|
|
Packit |
577717 |
errno = EINVAL;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int _sys_vperfctr_write_control(int fd, unsigned int cpu_type, const struct vperfctr_control *control)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
union {
|
|
Packit |
577717 |
struct vperfctr_control_kernel control;
|
|
Packit |
577717 |
struct perfctr_cpu_control_header header;
|
|
Packit |
577717 |
} u;
|
|
Packit |
577717 |
unsigned int nrctrs;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = _sys_vperfctr_control(fd, VPERFCTR_CONTROL_CLEAR);
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
u.control.si_signo = control->si_signo;
|
|
Packit |
577717 |
u.control.preserve = control->preserve;
|
|
Packit |
577717 |
ret = _sys_vperfctr_write(fd, VPERFCTR_DOMAIN_CONTROL,
|
|
Packit |
577717 |
&u.control, sizeof u.control);
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
u.header.tsc_on = control->cpu_control.tsc_on;
|
|
Packit |
577717 |
u.header.nractrs = control->cpu_control.nractrs;
|
|
Packit |
577717 |
u.header.nrictrs = control->cpu_control.nrictrs;
|
|
Packit |
577717 |
ret = _sys_vperfctr_write(fd, PERFCTR_DOMAIN_CPU_CONTROL,
|
|
Packit |
577717 |
&u.header, sizeof u.header);
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
nrctrs = control->cpu_control.nractrs + control->cpu_control.nrictrs;
|
|
Packit |
577717 |
ret = _sys_vperfctr_write(fd, PERFCTR_DOMAIN_CPU_MAP,
|
|
Packit |
577717 |
&control->cpu_control.pmc_map,
|
|
Packit |
577717 |
nrctrs * sizeof control->cpu_control.pmc_map[0]);
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = write_cpu_regs(fd, cpu_type, (struct perfctr_cpu_control*)&control->cpu_control);
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return _sys_vperfctr_control(fd, VPERFCTR_CONTROL_RESUME);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int read_cpu_regs(int fd, unsigned int cpu_type, struct perfctr_cpu_control *arg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch (cpu_type) {
|
|
Packit |
577717 |
case PERFCTR_X86_GENERIC:
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
#if !defined(__x86_64__)
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P5:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P5MMX:
|
|
Packit |
577717 |
case PERFCTR_X86_CYRIX_MII:
|
|
Packit |
577717 |
case PERFCTR_X86_WINCHIP_C6:
|
|
Packit |
577717 |
case PERFCTR_X86_WINCHIP_2:
|
|
Packit |
577717 |
return p5_read_regs(fd, arg);
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P6:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PII:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PIII:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PENTM:
|
|
Packit |
577717 |
case PERFCTR_X86_VIA_C3:
|
|
Packit |
577717 |
return p6_like_read_write_regs(fd, arg, MSR_P6_EVNTSEL0, MSR_P6_PERFCTR0, 0);
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K7:
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8:
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8C:
|
|
Packit |
577717 |
return p6_like_read_write_regs(fd, arg, MSR_K7_EVNTSEL0, MSR_K7_PERFCTR0, 0);
|
|
Packit |
577717 |
#if !defined(__x86_64__)
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4M2:
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4M3:
|
|
Packit |
577717 |
return p4_read_write_regs(fd, arg, 0);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
fprintf(stderr, "unable to read control registers for cpu type %u\n",
|
|
Packit |
577717 |
cpu_type);
|
|
Packit |
577717 |
errno = EINVAL;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int _sys_vperfctr_read_control(int fd, unsigned int cpu_type, struct vperfctr_control *control)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
union {
|
|
Packit |
577717 |
struct vperfctr_control_kernel control;
|
|
Packit |
577717 |
struct perfctr_cpu_control_header header;
|
|
Packit |
577717 |
} u;
|
|
Packit |
577717 |
unsigned int nrctrs;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(control, 0, sizeof *control);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = read_packet(fd, VPERFCTR_DOMAIN_CONTROL,
|
|
Packit |
577717 |
&u.control, sizeof u.control);
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
control->si_signo = u.control.si_signo;
|
|
Packit |
577717 |
control->preserve = u.control.preserve;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = read_packet(fd, PERFCTR_DOMAIN_CPU_CONTROL,
|
|
Packit |
577717 |
&u.header, sizeof u.header);
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
control->cpu_control.tsc_on = u.header.tsc_on;
|
|
Packit |
577717 |
control->cpu_control.nractrs = u.header.nractrs;
|
|
Packit |
577717 |
control->cpu_control.nrictrs = u.header.nrictrs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
nrctrs = control->cpu_control.nractrs + control->cpu_control.nrictrs;
|
|
Packit |
577717 |
ret = read_packet(fd, PERFCTR_DOMAIN_CPU_MAP,
|
|
Packit |
577717 |
&control->cpu_control.pmc_map,
|
|
Packit |
577717 |
nrctrs * sizeof control->cpu_control.pmc_map[0]);
|
|
Packit |
577717 |
if (ret < 0)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return read_cpu_regs(fd, cpu_type, &control->cpu_control);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int intel_init(const struct cpuinfo *cpuinfo,
|
|
Packit |
577717 |
struct perfctr_info *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int family, model, stepping;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!cpu_has(cpuinfo, X86_FEATURE_TSC))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
family = cpu_family(cpuinfo);
|
|
Packit |
577717 |
model = cpu_model(cpuinfo);
|
|
Packit |
577717 |
stepping = cpu_stepping(cpuinfo);
|
|
Packit |
577717 |
switch (family) {
|
|
Packit |
577717 |
case 5:
|
|
Packit |
577717 |
if (cpu_has(cpuinfo, X86_FEATURE_MMX)) {
|
|
Packit |
577717 |
/* Avoid Pentium Erratum 74. */
|
|
Packit |
577717 |
if (model == 4 &&
|
|
Packit |
577717 |
(stepping == 4 ||
|
|
Packit |
577717 |
(stepping == 3 &&
|
|
Packit |
577717 |
cpu_type(cpuinfo) == 1)))
|
|
Packit |
577717 |
info->cpu_features &= ~PERFCTR_FEATURE_RDPMC;
|
|
Packit |
577717 |
return PERFCTR_X86_INTEL_P5MMX;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
info->cpu_features &= ~PERFCTR_FEATURE_RDPMC;
|
|
Packit |
577717 |
return PERFCTR_X86_INTEL_P5;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
if (model == 9 || model == 13)
|
|
Packit |
577717 |
return PERFCTR_X86_INTEL_PENTM;
|
|
Packit |
577717 |
else if (model >= 7)
|
|
Packit |
577717 |
return PERFCTR_X86_INTEL_PIII;
|
|
Packit |
577717 |
else if (model >= 3)
|
|
Packit |
577717 |
return PERFCTR_X86_INTEL_PII;
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
/* Avoid Pentium Pro Erratum 26. */
|
|
Packit |
577717 |
if (stepping < 9)
|
|
Packit |
577717 |
info->cpu_features &= ~PERFCTR_FEATURE_RDPMC;
|
|
Packit |
577717 |
return PERFCTR_X86_INTEL_P6;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
case 15:
|
|
Packit |
577717 |
if (model >= 3)
|
|
Packit |
577717 |
return PERFCTR_X86_INTEL_P4M3;
|
|
Packit |
577717 |
else if (model >= 2)
|
|
Packit |
577717 |
return PERFCTR_X86_INTEL_P4M2;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
return PERFCTR_X86_INTEL_P4;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int amd_init(const struct cpuinfo *cpuinfo,
|
|
Packit |
577717 |
struct perfctr_info *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int family, model, stepping;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!cpu_has(cpuinfo, X86_FEATURE_TSC))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
family = cpu_family(cpuinfo);
|
|
Packit |
577717 |
model = cpu_model(cpuinfo);
|
|
Packit |
577717 |
stepping = cpu_stepping(cpuinfo);
|
|
Packit |
577717 |
switch (family) {
|
|
Packit |
577717 |
case 15:
|
|
Packit |
577717 |
if (model > 5 || (model >= 4 && stepping >= 8))
|
|
Packit |
577717 |
return PERFCTR_X86_AMD_K8C;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
return PERFCTR_X86_AMD_K8;
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
return PERFCTR_X86_AMD_K7;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int cyrix_init(const struct cpuinfo *cpuinfo,
|
|
Packit |
577717 |
struct perfctr_info *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (!cpu_has(cpuinfo, X86_FEATURE_TSC))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
switch (cpu_family(cpuinfo)) {
|
|
Packit |
577717 |
case 6: /* 6x86MX, MII, or III */
|
|
Packit |
577717 |
return PERFCTR_X86_CYRIX_MII;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int centaur_init(const struct cpuinfo *cpuinfo,
|
|
Packit |
577717 |
struct perfctr_info *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int family, model;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
family = cpu_family(cpuinfo);
|
|
Packit |
577717 |
model = cpu_model(cpuinfo);
|
|
Packit |
577717 |
switch (family) {
|
|
Packit |
577717 |
case 5:
|
|
Packit |
577717 |
if (cpu_has(cpuinfo, X86_FEATURE_TSC))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
info->cpu_features &= ~PERFCTR_FEATURE_RDTSC;
|
|
Packit |
577717 |
switch (model) {
|
|
Packit |
577717 |
case 4:
|
|
Packit |
577717 |
return PERFCTR_X86_WINCHIP_C6;
|
|
Packit |
577717 |
case 8: /* WinChip 2, 2A, or 2B */
|
|
Packit |
577717 |
case 9: /* WinChip 3 */
|
|
Packit |
577717 |
return PERFCTR_X86_WINCHIP_2;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
if (!cpu_has(cpuinfo, X86_FEATURE_TSC))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
switch (model) {
|
|
Packit |
577717 |
case 6: /* Cyrix III */
|
|
Packit |
577717 |
case 7: /* Samuel 2 */
|
|
Packit |
577717 |
case 8: /* Ezra-T */
|
|
Packit |
577717 |
case 9: /* Antaur/Nehemiah */
|
|
Packit |
577717 |
return PERFCTR_X86_VIA_C3;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int generic_init(const struct cpuinfo *cpuinfo,
|
|
Packit |
577717 |
struct perfctr_info *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (!cpu_has(cpuinfo, X86_FEATURE_TSC))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
info->cpu_features &= ~PERFCTR_FEATURE_RDPMC;
|
|
Packit |
577717 |
return PERFCTR_X86_GENERIC;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void perfctr_info_cpu_init(struct perfctr_info *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
struct cpuinfo cpuinfo;
|
|
Packit |
577717 |
int cpu_type;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
identify_cpu(&cpuinfo);
|
|
Packit |
577717 |
cpu_type = -1; /* binary compat prevents using 0 for "unknown" */
|
|
Packit |
577717 |
if (cpu_has(&cpuinfo, X86_FEATURE_MSR)) {
|
|
Packit |
577717 |
switch (cpuinfo.vendor) {
|
|
Packit |
577717 |
case X86_VENDOR_INTEL:
|
|
Packit |
577717 |
cpu_type = intel_init(&cpuinfo, info);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case X86_VENDOR_AMD:
|
|
Packit |
577717 |
cpu_type = amd_init(&cpuinfo, info);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case X86_VENDOR_CYRIX:
|
|
Packit |
577717 |
cpu_type = cyrix_init(&cpuinfo, info);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case X86_VENDOR_CENTAUR:
|
|
Packit |
577717 |
cpu_type = centaur_init(&cpuinfo, info);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (cpu_type < 0)
|
|
Packit |
577717 |
cpu_type = generic_init(&cpuinfo, info);
|
|
Packit |
577717 |
info->cpu_type = cpu_type;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
unsigned int perfctr_info_nrctrs(const struct perfctr_info *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch( info->cpu_type ) {
|
|
Packit |
577717 |
#if !defined(__x86_64__)
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P5:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P5MMX:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P6:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PII:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PIII:
|
|
Packit |
577717 |
case PERFCTR_X86_CYRIX_MII:
|
|
Packit |
577717 |
case PERFCTR_X86_WINCHIP_C6:
|
|
Packit |
577717 |
case PERFCTR_X86_WINCHIP_2:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PENTM:
|
|
Packit |
577717 |
return 2;
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K7:
|
|
Packit |
577717 |
return 4;
|
|
Packit |
577717 |
case PERFCTR_X86_VIA_C3:
|
|
Packit |
577717 |
return 1;
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4M2:
|
|
Packit |
577717 |
return 18;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4M3:
|
|
Packit |
577717 |
return 18;
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8:
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8C:
|
|
Packit |
577717 |
return 4;
|
|
Packit |
577717 |
case PERFCTR_X86_GENERIC:
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
const char *perfctr_info_cpu_name(const struct perfctr_info *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch( info->cpu_type ) {
|
|
Packit |
577717 |
case PERFCTR_X86_GENERIC:
|
|
Packit |
577717 |
return "Generic x86 with TSC";
|
|
Packit |
577717 |
#if !defined(__x86_64__)
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P5:
|
|
Packit |
577717 |
return "Intel Pentium";
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P5MMX:
|
|
Packit |
577717 |
return "Intel Pentium MMX";
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P6:
|
|
Packit |
577717 |
return "Intel Pentium Pro";
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PII:
|
|
Packit |
577717 |
return "Intel Pentium II";
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PIII:
|
|
Packit |
577717 |
return "Intel Pentium III";
|
|
Packit |
577717 |
case PERFCTR_X86_CYRIX_MII:
|
|
Packit |
577717 |
return "Cyrix 6x86MX/MII/III";
|
|
Packit |
577717 |
case PERFCTR_X86_WINCHIP_C6:
|
|
Packit |
577717 |
return "WinChip C6";
|
|
Packit |
577717 |
case PERFCTR_X86_WINCHIP_2:
|
|
Packit |
577717 |
return "WinChip 2/3";
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K7:
|
|
Packit |
577717 |
return "AMD K7";
|
|
Packit |
577717 |
case PERFCTR_X86_VIA_C3:
|
|
Packit |
577717 |
return "VIA C3";
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4:
|
|
Packit |
577717 |
return "Intel Pentium 4";
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4M2:
|
|
Packit |
577717 |
return "Intel Pentium 4 Model 2";
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_PENTM:
|
|
Packit |
577717 |
return "Intel Pentium M";
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_P4M3:
|
|
Packit |
577717 |
return "Intel Pentium 4 Model 3";
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8:
|
|
Packit |
577717 |
return "AMD K8";
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8C:
|
|
Packit |
577717 |
return "AMD K8 Revision C";
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return "?";
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void perfctr_cpu_control_print(const struct perfctr_cpu_control *control)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i, nractrs, nrictrs, nrctrs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
nractrs = control->nractrs;
|
|
Packit |
577717 |
nrictrs = control->nrictrs;
|
|
Packit |
577717 |
nrctrs = control->nractrs + nrictrs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
printf("tsc_on\t\t\t%u\n", control->tsc_on);
|
|
Packit |
577717 |
printf("nractrs\t\t\t%u\n", nractrs);
|
|
Packit |
577717 |
if( nrictrs )
|
|
Packit |
577717 |
printf("nrictrs\t\t\t%u\n", nrictrs);
|
|
Packit |
577717 |
for(i = 0; i < nrctrs; ++i) {
|
|
Packit |
577717 |
if( control->pmc_map[i] >= 18 ) /* for P4 'fast rdpmc' cases */
|
|
Packit |
577717 |
printf("pmc_map[%u]\t\t0x%08X\n", i, control->pmc_map[i]);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
printf("pmc_map[%u]\t\t%u\n", i, control->pmc_map[i]);
|
|
Packit |
577717 |
printf("evntsel[%u]\t\t0x%08X\n", i, control->evntsel[i]);
|
|
Packit |
577717 |
if( control->p4.escr[i] )
|
|
Packit |
577717 |
printf("escr[%u]\t\t\t0x%08X\n", i, control->p4.escr[i]);
|
|
Packit |
577717 |
if( i >= nractrs )
|
|
Packit |
577717 |
printf("ireset[%u]\t\t%d\n", i, control->ireset[i]);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if( control->p4.pebs_enable )
|
|
Packit |
577717 |
printf("pebs_enable\t\t0x%08X\n", control->p4.pebs_enable);
|
|
Packit |
577717 |
if( control->p4.pebs_matrix_vert )
|
|
Packit |
577717 |
printf("pebs_matrix_vert\t0x%08X\n", control->p4.pebs_matrix_vert);
|
|
Packit |
577717 |
}
|