/*
* Copyright (c) 2004-2006 Hewlett-Packard Development Company, L.P.
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* This file is part of libpfm, a performance monitoring support library for
* applications on Linux.
*/
#ifndef __PFMLIB_AMD64_PRIV_H__
#define __PFMLIB_AMD64_PRIV_H__
#define AMD64_MAX_GRP 4 /* must be < 32 (int) */
typedef struct {
const char *uname; /* unit mask name */
const char *udesc; /* event/umask description */
unsigned int ucode; /* unit mask code */
unsigned int uflags; /* unit mask flags */
unsigned int grpid; /* unit mask group id */
} amd64_umask_t;
typedef struct {
const char *name; /* event name */
const char *desc; /* event description */
const amd64_umask_t *umasks;/* list of umasks */
unsigned int code; /* event code */
unsigned int numasks;/* number of umasks */
unsigned int flags; /* flags */
unsigned int modmsk; /* modifiers bitmask */
unsigned int ngrp; /* number of unit masks groups */
} amd64_entry_t;
/*
* we keep an internal revision type to avoid
* dealing with arbitrarily large pfm_pmu_t
* which would not fit into the 8 bits reserved
* in amd64_entry_t.flags or amd64_umask_t.flags
*/
#define AMD64_FAM10H AMD64_FAM10H_REV_B
typedef enum {
AMD64_CPU_UN = 0,
AMD64_K7,
AMD64_K8_REV_B,
AMD64_K8_REV_C,
AMD64_K8_REV_D,
AMD64_K8_REV_E,
AMD64_K8_REV_F,
AMD64_K8_REV_G,
AMD64_FAM10H_REV_B,
AMD64_FAM10H_REV_C,
AMD64_FAM10H_REV_D,
AMD64_FAM14H_REV_B,
} amd64_rev_t;
typedef struct {
pfm_pmu_t revision;
int family; /* 0 means nothing detected yet */
int model;
int stepping;
} pfm_amd64_config_t;
extern pfm_amd64_config_t pfm_amd64_cfg;
/*
* flags values (bottom 8 bits only)
* bits 00-07: flags
* bits 08-15: from revision
* bits 16-23: till revision
*/
#define AMD64_FROM_REV(rev) ((rev)<<8)
#define AMD64_TILL_REV(rev) ((rev)<<16)
#define AMD64_NOT_SUPP 0x1ff00
#define AMD64_FL_NCOMBO 0x01 /* unit mask can be combined */
#define AMD64_FL_IBSFE 0x02 /* IBS fetch */
#define AMD64_FL_IBSOP 0x04 /* IBS op */
#define AMD64_FL_DFL 0x08 /* unit mask is default choice */
#define AMD64_FL_OMIT 0x10 /* umask can be omitted */
#define AMD64_FL_TILL_K8_REV_C AMD64_TILL_REV(AMD64_K8_REV_C)
#define AMD64_FL_K8_REV_D AMD64_FROM_REV(AMD64_K8_REV_D)
#define AMD64_FL_K8_REV_E AMD64_FROM_REV(AMD64_K8_REV_E)
#define AMD64_FL_TILL_K8_REV_E AMD64_TILL_REV(AMD64_K8_REV_E)
#define AMD64_FL_K8_REV_F AMD64_FROM_REV(AMD64_K8_REV_F)
#define AMD64_FL_TILL_FAM10H_REV_B AMD64_TILL_REV(AMD64_FAM10H_REV_B)
#define AMD64_FL_FAM10H_REV_C AMD64_FROM_REV(AMD64_FAM10H_REV_C)
#define AMD64_FL_TILL_FAM10H_REV_C AMD64_TILL_REV(AMD64_FAM10H_REV_C)
#define AMD64_FL_FAM10H_REV_D AMD64_FROM_REV(AMD64_FAM10H_REV_D)
#define AMD64_ATTR_K 0
#define AMD64_ATTR_U 1
#define AMD64_ATTR_E 2
#define AMD64_ATTR_I 3
#define AMD64_ATTR_C 4
#define AMD64_ATTR_H 5
#define AMD64_ATTR_G 6
#define _AMD64_ATTR_U (1 << AMD64_ATTR_U)
#define _AMD64_ATTR_K (1 << AMD64_ATTR_K)
#define _AMD64_ATTR_I (1 << AMD64_ATTR_I)
#define _AMD64_ATTR_E (1 << AMD64_ATTR_E)
#define _AMD64_ATTR_C (1 << AMD64_ATTR_C)
#define _AMD64_ATTR_H (1 << AMD64_ATTR_H)
#define _AMD64_ATTR_G (1 << AMD64_ATTR_G)
#define AMD64_BASIC_ATTRS \
(_AMD64_ATTR_I|_AMD64_ATTR_E|_AMD64_ATTR_C|_AMD64_ATTR_U|_AMD64_ATTR_K)
#define AMD64_K8_ATTRS (AMD64_BASIC_ATTRS)
#define AMD64_FAM10H_ATTRS (AMD64_BASIC_ATTRS|_AMD64_ATTR_H|_AMD64_ATTR_G)
#define AMD64_FAM12H_ATTRS AMD64_FAM10H_ATTRS
#define AMD64_FAM14H_ATTRS AMD64_FAM10H_ATTRS
#define AMD64_FAM15H_ATTRS AMD64_FAM10H_ATTRS
#define AMD64_FAM17H_ATTRS AMD64_FAM10H_ATTRS
#define AMD64_FAM10H_PLM (PFM_PLM0|PFM_PLM3|PFM_PLMH)
#define AMD64_K7_PLM (PFM_PLM0|PFM_PLM3)
/*
* AMD64 MSR definitions
*/
typedef union {
uint64_t val; /* complete register value */
struct {
uint64_t sel_event_mask:8; /* event mask */
uint64_t sel_unit_mask:8; /* unit mask */
uint64_t sel_usr:1; /* user level */
uint64_t sel_os:1; /* system level */
uint64_t sel_edge:1; /* edge detec */
uint64_t sel_pc:1; /* pin control */
uint64_t sel_int:1; /* enable APIC intr */
uint64_t sel_res1:1; /* reserved */
uint64_t sel_en:1; /* enable */
uint64_t sel_inv:1; /* invert counter mask */
uint64_t sel_cnt_mask:8; /* counter mask */
uint64_t sel_event_mask2:4; /* 10h only: event mask [11:8] */
uint64_t sel_res2:4; /* reserved */
uint64_t sel_guest:1; /* 10h only: guest only counter */
uint64_t sel_host:1; /* 10h only: host only counter */
uint64_t sel_res3:22; /* reserved */
} perfsel;
struct {
uint64_t maxcnt:16;
uint64_t cnt:16;
uint64_t lat:16;
uint64_t en:1;
uint64_t val:1;
uint64_t comp:1;
uint64_t icmiss:1;
uint64_t phyaddrvalid:1;
uint64_t l1tlbpgsz:2;
uint64_t l1tlbmiss:1;
uint64_t l2tlbmiss:1;
uint64_t randen:1;
uint64_t reserved:6;
} ibsfetch;
struct {
uint64_t maxcnt:16;
uint64_t reserved1:1;
uint64_t en:1;
uint64_t val:1;
uint64_t reserved2:45;
} ibsop;
} pfm_amd64_reg_t; /* MSR 0xc001000-0xc001003 */
/* let's define some handy shortcuts! */
#define sel_event_mask perfsel.sel_event_mask
#define sel_unit_mask perfsel.sel_unit_mask
#define sel_usr perfsel.sel_usr
#define sel_os perfsel.sel_os
#define sel_edge perfsel.sel_edge
#define sel_pc perfsel.sel_pc
#define sel_int perfsel.sel_int
#define sel_en perfsel.sel_en
#define sel_inv perfsel.sel_inv
#define sel_cnt_mask perfsel.sel_cnt_mask
#define sel_event_mask2 perfsel.sel_event_mask2
#define sel_guest perfsel.sel_guest
#define sel_host perfsel.sel_host
#define IS_FAMILY_10H(p) (((pfmlib_pmu_t *)(p))->pmu_rev >= AMD64_FAM10H)
#define IS_FAMILY_15H(p) (((pfmlib_pmu_t *)(p))->pmu == PFM_PMU_AMD64_FAM15H_INTERLAGOS)
extern int pfm_amd64_get_encoding(void *this, pfmlib_event_desc_t *e);
extern int pfm_amd64_get_event_first(void *this);
extern int pfm_amd64_get_event_next(void *this, int idx);
extern int pfm_amd64_event_is_valid(void *this, int idx);
extern int pfm_amd64_get_event_attr_info(void *this, int idx, int attr_idx, pfmlib_event_attr_info_t *info);
extern int pfm_amd64_get_event_info(void *this, int idx, pfm_event_info_t *info);
extern int pfm_amd64_validate_table(void *this, FILE *fp);
extern int pfm_amd64_detect(void *this);
extern const pfmlib_attr_desc_t amd64_mods[];
extern unsigned int pfm_amd64_get_event_nattrs(void *this, int pidx);
extern int pfm_amd64_get_num_events(void *this);
extern int pfm_amd64_get_perf_encoding(void *this, pfmlib_event_desc_t *e);
extern void pfm_amd64_perf_validate_pattrs(void *this, pfmlib_event_desc_t *e);
extern void pfm_amd64_nb_perf_validate_pattrs(void *this, pfmlib_event_desc_t *e);
extern int pfm_amd64_family_detect(void *this);
#endif /* __PFMLIB_AMD64_PRIV_H__ */