|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_amd64.c : support for the AMD64 architected PMU
|
|
Packit |
577717 |
* (for both 64 and 32 bit modes)
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P.
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
577717 |
* of this software and associated documentation files (the "Software"), to deal
|
|
Packit |
577717 |
* in the Software without restriction, including without limitation the rights
|
|
Packit |
577717 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit |
577717 |
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
Packit |
577717 |
* subject to the following conditions:
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* The above copyright notice and this permission notice shall be included in all
|
|
Packit |
577717 |
* copies or substantial portions of the Software.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
Packit |
577717 |
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
Packit |
577717 |
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit |
577717 |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
Packit |
577717 |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
Packit |
577717 |
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <ctype.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* public headers */
|
|
Packit |
577717 |
#include <perfmon/pfmlib_amd64.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* private headers */
|
|
Packit |
577717 |
#include "pfmlib_priv.h" /* library private */
|
|
Packit |
577717 |
#include "pfmlib_amd64_priv.h" /* architecture private */
|
|
Packit |
577717 |
#include "amd64_events.h" /* PMU private */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* let's define some handy shortcuts! */
|
|
Packit |
577717 |
#define sel_event_mask perfsel.sel_event_mask
|
|
Packit |
577717 |
#define sel_unit_mask perfsel.sel_unit_mask
|
|
Packit |
577717 |
#define sel_usr perfsel.sel_usr
|
|
Packit |
577717 |
#define sel_os perfsel.sel_os
|
|
Packit |
577717 |
#define sel_edge perfsel.sel_edge
|
|
Packit |
577717 |
#define sel_pc perfsel.sel_pc
|
|
Packit |
577717 |
#define sel_int perfsel.sel_int
|
|
Packit |
577717 |
#define sel_en perfsel.sel_en
|
|
Packit |
577717 |
#define sel_inv perfsel.sel_inv
|
|
Packit |
577717 |
#define sel_cnt_mask perfsel.sel_cnt_mask
|
|
Packit |
577717 |
#define sel_event_mask2 perfsel.sel_event_mask2
|
|
Packit |
577717 |
#define sel_guest perfsel.sel_guest
|
|
Packit |
577717 |
#define sel_host perfsel.sel_host
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define CHECK_AMD_ARCH(reg) \
|
|
Packit |
577717 |
((reg).sel_event_mask2 || (reg).sel_guest || (reg).sel_host)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define PFMLIB_AMD64_HAS_COMBO(_e) \
|
|
Packit |
577717 |
((pfm_amd64_get_event_entry(_e)->pme_flags & PFMLIB_AMD64_UMASK_COMBO) != 0)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define PFMLIB_AMD64_ALL_FLAGS \
|
|
Packit |
577717 |
(PFM_AMD64_SEL_INV|PFM_AMD64_SEL_EDGE|PFM_AMD64_SEL_GUEST|PFM_AMD64_SEL_HOST)
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Description of the PMC register mappings use by
|
|
Packit |
577717 |
* this module:
|
|
Packit |
577717 |
* pfp_pmcs[].reg_num:
|
|
Packit |
577717 |
* 0 -> PMC0 -> PERFEVTSEL0 -> MSR @ 0xc0010000
|
|
Packit |
577717 |
* 1 -> PMC1 -> PERFEVTSEL1 -> MSR @ 0xc0010001
|
|
Packit |
577717 |
* ...
|
|
Packit |
577717 |
* pfp_pmds[].reg_num:
|
|
Packit |
577717 |
* 0 -> PMD0 -> PERCTR0 -> MSR @ 0xc0010004
|
|
Packit |
577717 |
* 1 -> PMD1 -> PERCTR1 -> MSR @ 0xc0010005
|
|
Packit |
577717 |
* ...
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#define AMD64_SEL_BASE 0xc0010000
|
|
Packit |
577717 |
#define AMD64_CTR_BASE 0xc0010004
|
|
Packit |
577717 |
#define AMD64_SEL_BASE_F15H 0xc0010200
|
|
Packit |
577717 |
#define AMD64_CTR_BASE_F15H 0xc0010201
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static struct {
|
|
Packit |
577717 |
amd64_rev_t revision;
|
|
Packit |
577717 |
char *name;
|
|
Packit |
577717 |
unsigned int cpu_clks;
|
|
Packit |
577717 |
unsigned int ret_inst;
|
|
Packit |
577717 |
int family;
|
|
Packit |
577717 |
int model;
|
|
Packit |
577717 |
int stepping;
|
|
Packit |
577717 |
pme_amd64_entry_t *events;
|
|
Packit |
577717 |
} amd64_pmu;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pme_amd64_entry_t unsupported_event = {
|
|
Packit |
577717 |
.pme_name = "<unsupported>",
|
|
Packit |
577717 |
.pme_desc = "This event is not supported be this cpu revision.",
|
|
Packit |
577717 |
.pme_code = ~0,
|
|
Packit |
577717 |
.pme_flags = PFMLIB_AMD64_NOT_SUPP,
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_pmu_support_t amd64_support;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define amd64_revision amd64_pmu.revision
|
|
Packit |
577717 |
#define amd64_event_count amd64_support.pme_count
|
|
Packit |
577717 |
#define amd64_cpu_clks amd64_pmu.cpu_clks
|
|
Packit |
577717 |
#define amd64_ret_inst amd64_pmu.ret_inst
|
|
Packit |
577717 |
#define amd64_events amd64_pmu.events
|
|
Packit |
577717 |
#define amd64_family amd64_pmu.family
|
|
Packit |
577717 |
#define amd64_model amd64_pmu.model
|
|
Packit |
577717 |
#define amd64_stepping amd64_pmu.stepping
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* AMD architectural pmu features starts with family 10h */
|
|
Packit |
577717 |
#define IS_AMD_ARCH() (amd64_pmu.family >= 0x10)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static amd64_rev_t
|
|
Packit |
577717 |
amd64_get_revision(int family, int model, int stepping)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch (family) {
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
return AMD64_K7;
|
|
Packit |
577717 |
case 0x0f:
|
|
Packit |
577717 |
switch (model >> 4) {
|
|
Packit |
577717 |
case 0:
|
|
Packit |
577717 |
if (model == 5 && stepping < 2)
|
|
Packit |
577717 |
return AMD64_K8_REV_B;
|
|
Packit |
577717 |
if (model == 4 && stepping == 0)
|
|
Packit |
577717 |
return AMD64_K8_REV_B;
|
|
Packit |
577717 |
return AMD64_K8_REV_C;
|
|
Packit |
577717 |
case 1:
|
|
Packit |
577717 |
return AMD64_K8_REV_D;
|
|
Packit |
577717 |
case 2:
|
|
Packit |
577717 |
case 3:
|
|
Packit |
577717 |
return AMD64_K8_REV_E;
|
|
Packit |
577717 |
case 4:
|
|
Packit |
577717 |
case 5:
|
|
Packit |
577717 |
case 0xc:
|
|
Packit |
577717 |
return AMD64_K8_REV_F;
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
case 7:
|
|
Packit |
577717 |
case 8:
|
|
Packit |
577717 |
return AMD64_K8_REV_G;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return AMD64_K8_REV_B;
|
|
Packit |
577717 |
case 0x10:
|
|
Packit |
577717 |
switch (model) {
|
|
Packit |
577717 |
case 4:
|
|
Packit |
577717 |
case 5:
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
return AMD64_FAM10H_REV_C;
|
|
Packit |
577717 |
case 8:
|
|
Packit |
577717 |
case 9:
|
|
Packit |
577717 |
return AMD64_FAM10H_REV_D;
|
|
Packit |
577717 |
case 10:
|
|
Packit |
577717 |
return AMD64_FAM10H_REV_E;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return AMD64_FAM10H_REV_B;
|
|
Packit |
577717 |
case 0x15:
|
|
Packit |
577717 |
return AMD64_FAM15H_REV_B;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return AMD64_CPU_UN;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* .byte 0x53 == push ebx. it's universal for 32 and 64 bit
|
|
Packit |
577717 |
* .byte 0x5b == pop ebx.
|
|
Packit |
577717 |
* Some gcc's (4.1.2 on Core2) object to pairing push/pop and ebx in 64 bit mode.
|
|
Packit |
577717 |
* Using the opcode directly avoids this problem.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static inline void cpuid(unsigned int op, unsigned int *a, unsigned int *b,
|
|
Packit |
577717 |
unsigned int *c, unsigned int *d)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
__asm__ __volatile__ (".byte 0x53\n\tcpuid\n\tmovl %%ebx, %%esi\n\t.byte 0x5b"
|
|
Packit |
577717 |
: "=a" (*a),
|
|
Packit |
577717 |
"=S" (*b),
|
|
Packit |
577717 |
"=c" (*c),
|
|
Packit |
577717 |
"=d" (*d)
|
|
Packit |
577717 |
: "a" (op));
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_amd64_setup(amd64_rev_t revision)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
amd64_pmu.revision = revision;
|
|
Packit |
577717 |
amd64_pmu.name = (char *)amd64_cpu_strs[revision];
|
|
Packit |
577717 |
amd64_support.pmu_name = amd64_pmu.name;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* K8 (default) */
|
|
Packit |
577717 |
amd64_pmu.events = amd64_k8_table.events;
|
|
Packit |
577717 |
amd64_support.pme_count = amd64_k8_table.num;
|
|
Packit |
577717 |
amd64_pmu.cpu_clks = amd64_k8_table.cpu_clks;
|
|
Packit |
577717 |
amd64_pmu.ret_inst = amd64_k8_table.ret_inst;
|
|
Packit |
577717 |
amd64_support.pmu_type = PFMLIB_AMD64_PMU;
|
|
Packit |
577717 |
amd64_support.num_cnt = PMU_AMD64_NUM_COUNTERS;
|
|
Packit |
577717 |
amd64_support.pmc_count = PMU_AMD64_NUM_COUNTERS;
|
|
Packit |
577717 |
amd64_support.pmd_count = PMU_AMD64_NUM_COUNTERS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch (amd64_pmu.family) {
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
/* K7 */
|
|
Packit |
577717 |
amd64_pmu.events = amd64_k7_table.events;
|
|
Packit |
577717 |
amd64_support.pme_count = amd64_k7_table.num;
|
|
Packit |
577717 |
amd64_pmu.cpu_clks = amd64_k7_table.cpu_clks;
|
|
Packit |
577717 |
amd64_pmu.ret_inst = amd64_k7_table.ret_inst;
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
case 0x10:
|
|
Packit |
577717 |
/* Family 10h */
|
|
Packit |
577717 |
amd64_pmu.events = amd64_fam10h_table.events;
|
|
Packit |
577717 |
amd64_support.pme_count = amd64_fam10h_table.num;
|
|
Packit |
577717 |
amd64_pmu.cpu_clks = amd64_fam10h_table.cpu_clks;
|
|
Packit |
577717 |
amd64_pmu.ret_inst = amd64_fam10h_table.ret_inst;
|
|
Packit |
577717 |
amd64_support.pmc_count = PMU_AMD64_NUM_PERFSEL;
|
|
Packit |
577717 |
amd64_support.pmd_count = PMU_AMD64_NUM_PERFCTR;
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
case 0x15:
|
|
Packit |
577717 |
/* Family 15h */
|
|
Packit |
577717 |
amd64_pmu.events = amd64_fam15h_table.events;
|
|
Packit |
577717 |
amd64_support.pme_count = amd64_fam15h_table.num;
|
|
Packit |
577717 |
amd64_pmu.cpu_clks = amd64_fam15h_table.cpu_clks;
|
|
Packit |
577717 |
amd64_pmu.ret_inst = amd64_fam15h_table.ret_inst;
|
|
Packit |
577717 |
amd64_support.num_cnt = PMU_AMD64_NUM_COUNTERS_F15H;
|
|
Packit |
577717 |
amd64_support.pmc_count = PMU_AMD64_NUM_PERFSEL;
|
|
Packit |
577717 |
amd64_support.pmd_count = PMU_AMD64_NUM_PERFCTR;
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_detect(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int a, b, c, d;
|
|
Packit |
577717 |
char buffer[128];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cpuid(0, &a, &b, &c, &d);
|
|
Packit |
577717 |
strncpy(&buffer[0], (char *)(&b), 4);
|
|
Packit |
577717 |
strncpy(&buffer[4], (char *)(&d), 4);
|
|
Packit |
577717 |
strncpy(&buffer[8], (char *)(&c), 4);
|
|
Packit |
577717 |
buffer[12] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (strcmp(buffer, "AuthenticAMD"))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cpuid(1, &a, &b, &c, &d);
|
|
Packit |
577717 |
amd64_family = (a >> 8) & 0x0000000f; // bits 11 - 8
|
|
Packit |
577717 |
amd64_model = (a >> 4) & 0x0000000f; // Bits 7 - 4
|
|
Packit |
577717 |
if (amd64_family == 0xf) {
|
|
Packit |
577717 |
amd64_family += (a >> 20) & 0x000000ff; // Extended family
|
|
Packit |
577717 |
amd64_model |= (a >> 12) & 0x000000f0; // Extended model
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
amd64_stepping = a & 0x0000000f; // bits 3 - 0
|
|
Packit |
577717 |
|
|
Packit |
577717 |
amd64_revision = amd64_get_revision(amd64_family, amd64_model, amd64_stepping);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (amd64_revision == AMD64_CPU_UN)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_amd64_force(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *str;
|
|
Packit |
577717 |
int pmu_type;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* parses LIBPFM_FORCE_PMU=16,<family>,<model>,<stepping> */
|
|
Packit |
577717 |
str = getenv("LIBPFM_FORCE_PMU");
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
goto failed;
|
|
Packit |
577717 |
pmu_type = strtol(str, &str, 10);
|
|
Packit |
577717 |
if (pmu_type != PFMLIB_AMD64_PMU)
|
|
Packit |
577717 |
goto failed;
|
|
Packit |
577717 |
if (!*str || *str++ != ',')
|
|
Packit |
577717 |
goto failed;
|
|
Packit |
577717 |
amd64_family = strtol(str, &str, 10);
|
|
Packit |
577717 |
if (!*str || *str++ != ',')
|
|
Packit |
577717 |
goto failed;
|
|
Packit |
577717 |
amd64_model = strtol(str, &str, 10);
|
|
Packit |
577717 |
if (!*str || *str++ != ',')
|
|
Packit |
577717 |
goto failed;
|
|
Packit |
577717 |
amd64_stepping = strtol(str, &str, 10);
|
|
Packit |
577717 |
if (!*str)
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
failed:
|
|
Packit |
577717 |
DPRINT("force failed at: %s\n", str ? str : "<NULL>");
|
|
Packit |
577717 |
/* force AMD64 = force to Barcelona */
|
|
Packit |
577717 |
amd64_family = 16;
|
|
Packit |
577717 |
amd64_model = 2;
|
|
Packit |
577717 |
amd64_stepping = 2;
|
|
Packit |
577717 |
done:
|
|
Packit |
577717 |
amd64_revision = amd64_get_revision(amd64_family, amd64_model,
|
|
Packit |
577717 |
amd64_stepping);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_init(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (forced_pmu != PFMLIB_NO_PMU)
|
|
Packit |
577717 |
pfm_amd64_force();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("AMD family=%d model=0x%x stepping=0x%x rev=%s, %s\n",
|
|
Packit |
577717 |
amd64_family,
|
|
Packit |
577717 |
amd64_model,
|
|
Packit |
577717 |
amd64_stepping,
|
|
Packit |
577717 |
amd64_rev_strs[amd64_revision],
|
|
Packit |
577717 |
amd64_cpu_strs[amd64_revision]);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_amd64_setup(amd64_revision);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
is_valid_rev(unsigned int flags, int revision)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (revision < from_revision(flags))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (revision > till_revision(flags))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* no restrictions or matches restrictions */
|
|
Packit |
577717 |
return 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline pme_amd64_entry_t
|
|
Packit |
577717 |
*pfm_amd64_get_event_entry(unsigned int index)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Since there are no NULL pointer checks for the return
|
|
Packit |
577717 |
* value, &unsupported_event is returned instead. Function
|
|
Packit |
577717 |
* is_valid_index() may be used to validate the index.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pme_amd64_entry_t *event;
|
|
Packit |
577717 |
if (index >= amd64_event_count)
|
|
Packit |
577717 |
return &unsupported_event;
|
|
Packit |
577717 |
event = &amd64_events[index];
|
|
Packit |
577717 |
if (!is_valid_rev(event->pme_flags, amd64_revision))
|
|
Packit |
577717 |
return &unsupported_event;
|
|
Packit |
577717 |
return event;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
is_valid_index(unsigned int index)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return (pfm_amd64_get_event_entry(index) != &unsupported_event);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Automatically dispatch events to corresponding counters following constraints.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_dispatch_counters(pfmlib_input_param_t *inp, pfmlib_amd64_input_param_t *mod_in, pfmlib_output_param_t *outp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_amd64_input_param_t *param = mod_in;
|
|
Packit |
577717 |
pfmlib_amd64_counter_t *cntrs;
|
|
Packit |
577717 |
pfm_amd64_sel_reg_t reg;
|
|
Packit |
577717 |
pfmlib_event_t *e;
|
|
Packit |
577717 |
pfmlib_reg_t *pc, *pd;
|
|
Packit |
577717 |
pfmlib_regmask_t *r_pmcs;
|
|
Packit |
577717 |
unsigned long plm;
|
|
Packit |
577717 |
unsigned int i, j, k, cnt, umask;
|
|
Packit |
577717 |
unsigned int assign[PMU_AMD64_MAX_COUNTERS];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e = inp->pfp_events;
|
|
Packit |
577717 |
pc = outp->pfp_pmcs;
|
|
Packit |
577717 |
pd = outp->pfp_pmds;
|
|
Packit |
577717 |
cnt = inp->pfp_event_count;
|
|
Packit |
577717 |
r_pmcs = &inp->pfp_unavail_pmcs;
|
|
Packit |
577717 |
cntrs = param ? param->pfp_amd64_counters : NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* priviledge level 1 and 2 are not supported */
|
|
Packit |
577717 |
if (inp->pfp_dfl_plm & (PFM_PLM1|PFM_PLM2)) {
|
|
Packit |
577717 |
DPRINT("invalid plm=%x\n", inp->pfp_dfl_plm);
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_DEBUG()) {
|
|
Packit |
577717 |
for (j=0; j < cnt; j++) {
|
|
Packit |
577717 |
DPRINT("ev[%d]=%s\n", j, pfm_amd64_get_event_entry(e[j].event)->pme_name);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (cnt > amd64_support.num_cnt) return PFMLIB_ERR_TOOMANY;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0, j=0; j < cnt; j++, i++) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* AMD64 only supports two priv levels for perf counters
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (e[j].plm & (PFM_PLM1|PFM_PLM2)) {
|
|
Packit |
577717 |
DPRINT("event=%d invalid plm=%d\n", e[j].event, e[j].plm);
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check illegal unit masks combination
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (e[j].num_masks > 1 && PFMLIB_AMD64_HAS_COMBO(e[j].event) == 0) {
|
|
Packit |
577717 |
DPRINT("event does not supports unit mask combination\n");
|
|
Packit |
577717 |
return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check revision restrictions at the event level
|
|
Packit |
577717 |
* (check at the umask level later)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (!is_valid_rev(pfm_amd64_get_event_entry(e[i].event)->pme_flags,
|
|
Packit |
577717 |
amd64_revision)) {
|
|
Packit |
577717 |
DPRINT("CPU does not have correct revision level\n");
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (cntrs && (cntrs[j].flags & ~PFMLIB_AMD64_ALL_FLAGS)) {
|
|
Packit |
577717 |
DPRINT("invalid AMD64 flags\n");
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (cntrs && (cntrs[j].cnt_mask >= PMU_AMD64_CNT_MASK_MAX)) {
|
|
Packit |
577717 |
DPRINT("event=%d invalid cnt_mask=%d: must be < %u\n",
|
|
Packit |
577717 |
e[j].event,
|
|
Packit |
577717 |
cntrs[j].cnt_mask,
|
|
Packit |
577717 |
PMU_AMD64_CNT_MASK_MAX);
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* exclude unavailable registers from assignment
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
while(i < amd64_support.num_cnt && pfm_regmask_isset(r_pmcs, i))
|
|
Packit |
577717 |
i++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (i == amd64_support.num_cnt)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
assign[j] = i;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j=0; j < cnt ; j++ ) {
|
|
Packit |
577717 |
reg.val = 0; /* assume reserved bits are zerooed */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* if plm is 0, then assume not specified per-event and use default */
|
|
Packit |
577717 |
plm = e[j].plm ? e[j].plm : inp->pfp_dfl_plm;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!is_valid_rev(pfm_amd64_get_event_entry(e[j].event)->pme_flags,
|
|
Packit |
577717 |
amd64_revision))
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.sel_event_mask = pfm_amd64_get_event_entry(e[j].event)->pme_code;
|
|
Packit |
577717 |
reg.sel_event_mask2 = pfm_amd64_get_event_entry(e[j].event)->pme_code >> 8;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
umask = 0;
|
|
Packit |
577717 |
for(k=0; k < e[j].num_masks; k++) {
|
|
Packit |
577717 |
/* check unit mask revision restrictions */
|
|
Packit |
577717 |
if (!is_valid_rev(pfm_amd64_get_event_entry(e[j].event)->pme_umasks[e[j].unit_masks[k]].pme_uflags,
|
|
Packit |
577717 |
amd64_revision))
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
umask |= pfm_amd64_get_event_entry(e[j].event)->pme_umasks[e[j].unit_masks[k]].pme_ucode;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (e[j].event == PME_AMD64_IBSOP) {
|
|
Packit |
577717 |
ibsopctl_t ibsopctl;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ibsopctl.val = 0;
|
|
Packit |
577717 |
ibsopctl.reg.ibsopen = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (umask == 2 && amd64_revision < from_revision(PFMLIB_AMD64_FAM10H_REV_C)) {
|
|
Packit |
577717 |
DPRINT("IBSOP:UOPS available on Rev C and later processors\n");
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* 1: cycles
|
|
Packit |
577717 |
* 2: uops
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ibsopctl.reg.ibsopcntl = umask == 0x1 ? 0 : 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[j].reg_value = ibsopctl.val;
|
|
Packit |
577717 |
pc[j].reg_num = PMU_AMD64_IBSOPCTL_PMC;
|
|
Packit |
577717 |
pc[j].reg_addr = 0xc0011033;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[IBSOPCTL(pmc%u)=0x%llx en=%d uops=%d maxcnt=0x%x]\n",
|
|
Packit |
577717 |
PMU_AMD64_IBSOPCTL_PMD,
|
|
Packit |
577717 |
ibsopctl.val,
|
|
Packit |
577717 |
ibsopctl.reg.ibsopen,
|
|
Packit |
577717 |
ibsopctl.reg.ibsopcntl,
|
|
Packit |
577717 |
ibsopctl.reg.ibsopmaxcnt);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pd[j].reg_num = PMU_AMD64_IBSOPCTL_PMD;
|
|
Packit |
577717 |
pd[j].reg_addr = 0xc0011033;
|
|
Packit |
577717 |
__pfm_vbprintf("[IBSOPCTL(pmd%u)]\n", PMU_AMD64_IBSOPCTL_PMD);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
} else if (e[j].event == PME_AMD64_IBSFETCH) {
|
|
Packit |
577717 |
ibsfetchctl_t ibsfetchctl;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ibsfetchctl.val = 0;
|
|
Packit |
577717 |
ibsfetchctl.reg.ibsfetchen = 1;
|
|
Packit |
577717 |
ibsfetchctl.reg.ibsranden = umask == 0x1 ? 1 : 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[j].reg_value = ibsfetchctl.val;
|
|
Packit |
577717 |
pc[j].reg_num = PMU_AMD64_IBSFETCHCTL_PMC;
|
|
Packit |
577717 |
pc[j].reg_addr = 0xc0011031;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pd[j].reg_num = PMU_AMD64_IBSFETCHCTL_PMD;
|
|
Packit |
577717 |
pd[j].reg_addr = 0xc0011031;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[IBSFETCHCTL(pmc%u)=0x%llx en=%d maxcnt=0x%x rand=%u]\n",
|
|
Packit |
577717 |
PMU_AMD64_IBSFETCHCTL_PMD,
|
|
Packit |
577717 |
ibsfetchctl.val,
|
|
Packit |
577717 |
ibsfetchctl.reg.ibsfetchen,
|
|
Packit |
577717 |
ibsfetchctl.reg.ibsfetchmaxcnt,
|
|
Packit |
577717 |
ibsfetchctl.reg.ibsranden);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[IBSOPFETCH(pmd%u)]\n", PMU_AMD64_IBSFETCHCTL_PMD);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
reg.sel_unit_mask = umask;
|
|
Packit |
577717 |
reg.sel_usr = plm & PFM_PLM3 ? 1 : 0;
|
|
Packit |
577717 |
reg.sel_os = plm & PFM_PLM0 ? 1 : 0;
|
|
Packit |
577717 |
reg.sel_en = 1; /* force enable bit to 1 */
|
|
Packit |
577717 |
reg.sel_int = 1; /* force APIC int to 1 */
|
|
Packit |
577717 |
if (cntrs) {
|
|
Packit |
577717 |
reg.sel_cnt_mask = cntrs[j].cnt_mask;
|
|
Packit |
577717 |
reg.sel_edge = cntrs[j].flags & PFM_AMD64_SEL_EDGE ? 1 : 0;
|
|
Packit |
577717 |
reg.sel_inv = cntrs[j].flags & PFM_AMD64_SEL_INV ? 1 : 0;
|
|
Packit |
577717 |
reg.sel_guest = cntrs[j].flags & PFM_AMD64_SEL_GUEST ? 1 : 0;
|
|
Packit |
577717 |
reg.sel_host = cntrs[j].flags & PFM_AMD64_SEL_HOST ? 1 : 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pc[j].reg_num = assign[j];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((CHECK_AMD_ARCH(reg)) && !IS_AMD_ARCH())
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (amd64_support.num_cnt == PMU_AMD64_NUM_COUNTERS_F15H) {
|
|
Packit |
577717 |
pc[j].reg_addr = AMD64_SEL_BASE_F15H + (assign[j] << 1);
|
|
Packit |
577717 |
pd[j].reg_addr = AMD64_CTR_BASE_F15H + (assign[j] << 1);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
pc[j].reg_addr = AMD64_SEL_BASE + assign[j];
|
|
Packit |
577717 |
pd[j].reg_addr = AMD64_CTR_BASE + assign[j];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[j].reg_value = reg.val;
|
|
Packit |
577717 |
pc[j].reg_alt_addr = pc[j].reg_addr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pd[j].reg_num = assign[j];
|
|
Packit |
577717 |
pd[j].reg_alt_addr = assign[j]; /* index to use with RDPMC */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PERFSEL%u(pmc%u)=0x%llx emask=0x%x umask=0x%x os=%d usr=%d inv=%d en=%d int=%d edge=%d cnt_mask=%d] %s\n",
|
|
Packit |
577717 |
assign[j],
|
|
Packit |
577717 |
assign[j],
|
|
Packit |
577717 |
reg.val,
|
|
Packit |
577717 |
reg.sel_event_mask,
|
|
Packit |
577717 |
reg.sel_unit_mask,
|
|
Packit |
577717 |
reg.sel_os,
|
|
Packit |
577717 |
reg.sel_usr,
|
|
Packit |
577717 |
reg.sel_inv,
|
|
Packit |
577717 |
reg.sel_en,
|
|
Packit |
577717 |
reg.sel_int,
|
|
Packit |
577717 |
reg.sel_edge,
|
|
Packit |
577717 |
reg.sel_cnt_mask,
|
|
Packit |
577717 |
pfm_amd64_get_event_entry(e[j].event)->pme_name);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PERFCTR%u(pmd%u)]\n", pd[j].reg_num, pd[j].reg_num);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* number of evtsel/ctr registers programmed */
|
|
Packit |
577717 |
outp->pfp_pmc_count = cnt;
|
|
Packit |
577717 |
outp->pfp_pmd_count = cnt;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int pfm_amd64_dispatch_ibs(pfmlib_input_param_t *inp,
|
|
Packit |
577717 |
pfmlib_amd64_input_param_t *inp_mod,
|
|
Packit |
577717 |
pfmlib_output_param_t *outp,
|
|
Packit |
577717 |
pfmlib_amd64_output_param_t *outp_mod)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int pmc_base, pmd_base;
|
|
Packit |
577717 |
ibsfetchctl_t ibsfetchctl;
|
|
Packit |
577717 |
ibsopctl_t ibsopctl;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!inp_mod || !outp || !outp_mod)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!IS_AMD_ARCH())
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* IBS fetch profiling */
|
|
Packit |
577717 |
if (inp_mod->flags & PFMLIB_AMD64_USE_IBSFETCH) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* check availability of a PMC and PMD */
|
|
Packit |
577717 |
if (outp->pfp_pmc_count >= PFMLIB_MAX_PMCS)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (outp->pfp_pmd_count >= PFMLIB_MAX_PMDS)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmc_base = outp->pfp_pmc_count;
|
|
Packit |
577717 |
pmd_base = outp->pfp_pmd_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
outp->pfp_pmcs[pmc_base].reg_num = PMU_AMD64_IBSFETCHCTL_PMC;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ibsfetchctl.val = 0;
|
|
Packit |
577717 |
ibsfetchctl.reg.ibsfetchen = 1;
|
|
Packit |
577717 |
ibsfetchctl.reg.ibsfetchmaxcnt = inp_mod->ibsfetch.maxcnt >> 4;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (inp_mod->ibsfetch.options & IBS_OPTIONS_RANDEN)
|
|
Packit |
577717 |
ibsfetchctl.reg.ibsranden = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
outp->pfp_pmcs[pmc_base].reg_value = ibsfetchctl.val;
|
|
Packit |
577717 |
outp->pfp_pmds[pmd_base].reg_num = PMU_AMD64_IBSFETCHCTL_PMD;
|
|
Packit |
577717 |
outp_mod->ibsfetch_base = pmd_base;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
++outp->pfp_pmc_count;
|
|
Packit |
577717 |
++outp->pfp_pmd_count;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* IBS execution profiling */
|
|
Packit |
577717 |
if (inp_mod->flags & PFMLIB_AMD64_USE_IBSOP) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* check availability of a PMC and PMD */
|
|
Packit |
577717 |
if (outp->pfp_pmc_count >= PFMLIB_MAX_PMCS)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (outp->pfp_pmd_count >= PFMLIB_MAX_PMDS)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmc_base = outp->pfp_pmc_count;
|
|
Packit |
577717 |
pmd_base = outp->pfp_pmd_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
outp->pfp_pmcs[pmc_base].reg_num = PMU_AMD64_IBSOPCTL_PMC;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ibsopctl.val = 0;
|
|
Packit |
577717 |
ibsopctl.reg.ibsopen = 1;
|
|
Packit |
577717 |
ibsopctl.reg.ibsopmaxcnt = inp_mod->ibsop.maxcnt >> 4;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (inp_mod->ibsop.options & IBS_OPTIONS_UOPS) {
|
|
Packit |
577717 |
if (amd64_revision < from_revision(PFMLIB_AMD64_FAM10H_REV_C)) {
|
|
Packit |
577717 |
DPRINT("IBSOP:UOPS available on Rev C and later processors\n");
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
ibsopctl.reg.ibsopcntl = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
outp->pfp_pmcs[pmc_base].reg_value = ibsopctl.val;
|
|
Packit |
577717 |
outp->pfp_pmds[pmd_base].reg_num = PMU_AMD64_IBSOPCTL_PMD;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
outp_mod->ibsop_base = pmd_base;
|
|
Packit |
577717 |
++outp->pfp_pmc_count;
|
|
Packit |
577717 |
++outp->pfp_pmd_count;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_dispatch_events(
|
|
Packit |
577717 |
pfmlib_input_param_t *inp, void *_inp_mod,
|
|
Packit |
577717 |
pfmlib_output_param_t *outp, void *outp_mod)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_amd64_input_param_t *inp_mod = _inp_mod;
|
|
Packit |
577717 |
int ret = PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!outp)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* At least one of the dispatch function calls must return
|
|
Packit |
577717 |
* PFMLIB_SUCCESS
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (inp && inp->pfp_event_count) {
|
|
Packit |
577717 |
ret = pfm_amd64_dispatch_counters(inp, inp_mod, outp);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (inp_mod && inp_mod->flags & (PFMLIB_AMD64_USE_IBSOP | PFMLIB_AMD64_USE_IBSFETCH))
|
|
Packit |
577717 |
ret = pfm_amd64_dispatch_ibs(inp, inp_mod, outp, outp_mod);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_get_event_code(unsigned int i, unsigned int cnt, int *code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (cnt != PFMLIB_CNT_FIRST && cnt >= amd64_support.num_cnt)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*code = pfm_amd64_get_event_entry(i)->pme_code;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* This function is accessible directly to the user
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_amd64_get_event_umask(unsigned int i, unsigned long *umask)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (i >= amd64_event_count || umask == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
*umask = 0; //evt_umask(i);
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_amd64_get_event_counters(unsigned int j, pfmlib_regmask_t *counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(counters, 0, sizeof(*counters));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < amd64_support.num_cnt; i++)
|
|
Packit |
577717 |
pfm_regmask_set(counters, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_amd64_get_impl_perfsel(pfmlib_regmask_t *impl_pmcs)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* all pmcs are contiguous */
|
|
Packit |
577717 |
for(i=0; i < amd64_support.pmc_count; i++)
|
|
Packit |
577717 |
pfm_regmask_set(impl_pmcs, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_amd64_get_impl_perfctr(pfmlib_regmask_t *impl_pmds)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* all pmds are contiguous */
|
|
Packit |
577717 |
for(i=0; i < amd64_support.pmd_count; i++)
|
|
Packit |
577717 |
pfm_regmask_set(impl_pmds, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_amd64_get_impl_counters(pfmlib_regmask_t *impl_counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* counting pmds are contiguous */
|
|
Packit |
577717 |
for(i=0; i < amd64_support.num_cnt; i++)
|
|
Packit |
577717 |
pfm_regmask_set(impl_counters, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_amd64_get_hw_counter_width(unsigned int *width)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
*width = PMU_AMD64_COUNTER_WIDTH;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static char *
|
|
Packit |
577717 |
pfm_amd64_get_event_name(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (!is_valid_index(i))
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
return pfm_amd64_get_event_entry(i)->pme_name;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_get_event_desc(unsigned int ev, char **str)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *s;
|
|
Packit |
577717 |
s = pfm_amd64_get_event_entry(ev)->pme_desc;
|
|
Packit |
577717 |
if (s) {
|
|
Packit |
577717 |
*str = strdup(s);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
*str = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static char *
|
|
Packit |
577717 |
pfm_amd64_get_event_mask_name(unsigned int ev, unsigned int midx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pme_amd64_umask_t *umask;
|
|
Packit |
577717 |
umask = &pfm_amd64_get_event_entry(ev)->pme_umasks[midx];
|
|
Packit |
577717 |
if (!is_valid_rev(umask->pme_uflags, amd64_revision))
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
return umask->pme_uname;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_get_event_mask_desc(unsigned int ev, unsigned int midx, char **str)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *s;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
s = pfm_amd64_get_event_entry(ev)->pme_umasks[midx].pme_udesc;
|
|
Packit |
577717 |
if (s) {
|
|
Packit |
577717 |
*str = strdup(s);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
*str = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static unsigned int
|
|
Packit |
577717 |
pfm_amd64_get_num_event_masks(unsigned int ev)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return pfm_amd64_get_event_entry(ev)->pme_numasks;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_get_event_mask_code(unsigned int ev, unsigned int midx, unsigned int *code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
*code = pfm_amd64_get_event_entry(ev)->pme_umasks[midx].pme_ucode;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_get_cycle_event(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
e->event = amd64_cpu_clks;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_amd64_get_inst_retired(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
e->event = amd64_ret_inst;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_pmu_support_t amd64_support = {
|
|
Packit |
577717 |
.pmu_name = "AMD64",
|
|
Packit |
577717 |
.pmu_type = PFMLIB_AMD64_PMU,
|
|
Packit |
577717 |
.pme_count = 0,
|
|
Packit |
577717 |
.pmc_count = PMU_AMD64_NUM_COUNTERS,
|
|
Packit |
577717 |
.pmd_count = PMU_AMD64_NUM_COUNTERS,
|
|
Packit |
577717 |
.num_cnt = PMU_AMD64_NUM_COUNTERS,
|
|
Packit |
577717 |
.get_event_code = pfm_amd64_get_event_code,
|
|
Packit |
577717 |
.get_event_name = pfm_amd64_get_event_name,
|
|
Packit |
577717 |
.get_event_counters = pfm_amd64_get_event_counters,
|
|
Packit |
577717 |
.dispatch_events = pfm_amd64_dispatch_events,
|
|
Packit |
577717 |
.pmu_detect = pfm_amd64_detect,
|
|
Packit |
577717 |
.pmu_init = pfm_amd64_init,
|
|
Packit |
577717 |
.get_impl_pmcs = pfm_amd64_get_impl_perfsel,
|
|
Packit |
577717 |
.get_impl_pmds = pfm_amd64_get_impl_perfctr,
|
|
Packit |
577717 |
.get_impl_counters = pfm_amd64_get_impl_counters,
|
|
Packit |
577717 |
.get_hw_counter_width = pfm_amd64_get_hw_counter_width,
|
|
Packit |
577717 |
.get_event_desc = pfm_amd64_get_event_desc,
|
|
Packit |
577717 |
.get_num_event_masks = pfm_amd64_get_num_event_masks,
|
|
Packit |
577717 |
.get_event_mask_name = pfm_amd64_get_event_mask_name,
|
|
Packit |
577717 |
.get_event_mask_code = pfm_amd64_get_event_mask_code,
|
|
Packit |
577717 |
.get_event_mask_desc = pfm_amd64_get_event_mask_desc,
|
|
Packit |
577717 |
.get_cycle_event = pfm_amd64_get_cycle_event,
|
|
Packit |
577717 |
.get_inst_retired_event = pfm_amd64_get_inst_retired
|
|
Packit |
577717 |
};
|