|
Packit |
577717 |
/* $Id: x86.c,v 1.3.2.11 2010/11/07 19:46:06 mikpe Exp $
|
|
Packit |
577717 |
* x86-specific code.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (C) 2001-2010 Mikael Pettersson
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#define __USE_GNU /* enable symbolic names for gregset_t[] indices */
|
|
Packit |
577717 |
#include <sys/ucontext.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include "libperfctr.h"
|
|
Packit |
577717 |
#include "arch.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef __x86_64__
|
|
Packit |
577717 |
#ifndef REG_RIP
|
|
Packit |
577717 |
#define REG_RIP 16
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#define REG_PC REG_RIP
|
|
Packit |
577717 |
#else /* !__x86_64__ */
|
|
Packit |
577717 |
#ifndef REG_EIP
|
|
Packit |
577717 |
#define REG_EIP 14
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#define REG_PC REG_EIP
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline unsigned long mcontext_pc(const mcontext_t *mc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return mc->gregs[REG_PC];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
unsigned long ucontext_pc(const struct ucontext *uc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return mcontext_pc(&uc->uc_mcontext);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void do_setup(const struct perfctr_info *info,
|
|
Packit |
577717 |
struct perfctr_cpu_control *cpu_control)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int nractrs = 0;
|
|
Packit |
577717 |
unsigned int pmc_map0 = 0, pmc_map1 = 1;
|
|
Packit |
577717 |
unsigned int evntsel0, evntsel1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(cpu_control, 0, sizeof *cpu_control);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch (info->cpu_type) {
|
|
Packit |
577717 |
#if !defined(__x86_64__)
|
|
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_INTEL_CORE:
|
|
Packit |
577717 |
/* FLOPS, USR, ENable, INT */
|
|
Packit |
577717 |
evntsel0 = 0xC1 | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
/* BR_TAKEN_RETIRED, USR, INT */
|
|
Packit |
577717 |
evntsel1 = 0xC9 | (1 << 16) | (1 << 20);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_CORE2:
|
|
Packit |
577717 |
/* X87_OPS_RETIRED_ANY, USR, Enable, INT */
|
|
Packit |
577717 |
evntsel0 = 0xC1 | (0xFE << 8) | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
/* BR_INST_RETIRED_TAKEN, USR, Enable, INT */
|
|
Packit |
577717 |
evntsel1 = 0xC4 | (0x0C << 8) | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_ATOM:
|
|
Packit |
577717 |
/* Atom's architectural events don't include FLOPS */
|
|
Packit |
577717 |
/* INST_RETIRED_ANY, USR, Enable, INT */
|
|
Packit |
577717 |
evntsel0 = 0xC0 | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
/* BR_INST_RETIRED_ANY, USR, Enable, INT */
|
|
Packit |
577717 |
evntsel1 = 0xC4 | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_NHLM:
|
|
Packit |
577717 |
case PERFCTR_X86_INTEL_WSTMR:
|
|
Packit |
577717 |
/* FP_COMP_OPS_EXE.ANY, USR, Enable, INT */
|
|
Packit |
577717 |
evntsel0 = 0x10 | (0xFF << 8) | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
/* BR_INST_RETIRED.ALL, USR, Enable, INT */
|
|
Packit |
577717 |
evntsel1 = 0xC4 | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
#if !defined(__x86_64__)
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K7:
|
|
Packit |
577717 |
/* K7 can't count FLOPS. Count RETIRED_INSTRUCTIONS instead. */
|
|
Packit |
577717 |
evntsel0 = 0xC0 | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
/* RETIRED_TAKEN_BRANCHES, USR, INT */
|
|
Packit |
577717 |
evntsel1 = 0xC4 | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
break;
|
|
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 |
nractrs = 1;
|
|
Packit |
577717 |
/* PMC(0) produces tagged x87_FP_uop:s (FLAME_CCCR0, FIRM_ESCR0) */
|
|
Packit |
577717 |
cpu_control->pmc_map[0] = 0x8 | (1 << 31);
|
|
Packit |
577717 |
cpu_control->evntsel[0] = (0x3 << 16) | (1 << 13) | (1 << 12);
|
|
Packit |
577717 |
cpu_control->p4.escr[0] = (4 << 25) | (1 << 24) | (1 << 5) | (1 << 4) | (1 << 2);
|
|
Packit |
577717 |
/* PMC(1) counts execution_event(X87_FP_retired) (IQ_CCCR0, CRU_ESCR2) */
|
|
Packit |
577717 |
pmc_map0 = 0xC | (1 << 31);
|
|
Packit |
577717 |
evntsel0 = (1 << 26) | (0x3 << 16) | (5 << 13) | (1 << 12);
|
|
Packit |
577717 |
cpu_control->p4.escr[1] = (0xC << 25) | (1 << 9) | (1 << 2);
|
|
Packit |
577717 |
/* PMC(2) counts branch_retired(TP,TM) (IQ_CCCR2, CRU_ESCR3) */
|
|
Packit |
577717 |
pmc_map1 = 0xE | (1 << 31);
|
|
Packit |
577717 |
evntsel1 = (1 << 26) | (0x3 << 16) | (5 << 13) | (1 << 12);
|
|
Packit |
577717 |
cpu_control->p4.escr[2] = (6 << 25) | (((1 << 3)|(1 << 2)) << 9) | (1 << 2);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8:
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_K8C:
|
|
Packit |
577717 |
case PERFCTR_X86_AMD_FAM10H:
|
|
Packit |
577717 |
/* RETIRED_FPU_INSTRS, Unit Mask "x87 instrs", any CPL, Enable, INT */
|
|
Packit |
577717 |
evntsel0 = 0xCB | (0x01 << 8) | (3 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
/* RETIRED_TAKEN_BRANCHES, USR, Enable, INT */
|
|
Packit |
577717 |
evntsel1 = 0xC4 | (1 << 16) | (1 << 22) | (1 << 20);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
printf("%s: unsupported cpu type %u\n", __FUNCTION__, info->cpu_type);
|
|
Packit |
577717 |
exit(1);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
cpu_control->tsc_on = 1;
|
|
Packit |
577717 |
cpu_control->nractrs = nractrs;
|
|
Packit |
577717 |
cpu_control->nrictrs = 2;
|
|
Packit |
577717 |
cpu_control->pmc_map[nractrs+0] = pmc_map0;
|
|
Packit |
577717 |
cpu_control->evntsel[nractrs+0] = evntsel0;
|
|
Packit |
577717 |
cpu_control->ireset[nractrs+0] = -25;
|
|
Packit |
577717 |
cpu_control->pmc_map[nractrs+1] = pmc_map1;
|
|
Packit |
577717 |
cpu_control->evntsel[nractrs+1] = evntsel1;
|
|
Packit |
577717 |
cpu_control->ireset[nractrs+1] = -25;
|
|
Packit |
577717 |
}
|