|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P.
|
|
Packit |
577717 |
* Copyright (c) 2006 IBM Corp.
|
|
Packit |
577717 |
* Contributed by Kevin Corry <kevcorry@us.ibm.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
Packit |
577717 |
* copy of this software and associated documentation files (the "Software"),
|
|
Packit |
577717 |
* to deal in the Software without restriction, including without limitation
|
|
Packit |
577717 |
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
Packit |
577717 |
* and/or sell copies of the Software, and to permit persons to whom the
|
|
Packit |
577717 |
* Software is furnished to do so, subject to the following conditions:
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* The above copyright notice and this permission notice shall be included in
|
|
Packit |
577717 |
* all copies or substantial portions of the Software.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
Packit |
577717 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
Packit |
577717 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
Packit |
577717 |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
Packit |
577717 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
Packit |
577717 |
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
Packit |
577717 |
* IN THE SOFTWARE.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* pfmlib_pentium4.c
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Support for libpfm for the Pentium4/Xeon/EM64T processor family (family=15).
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifndef _GNU_SOURCE
|
|
Packit |
577717 |
#define _GNU_SOURCE /* for getline */
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <limits.h>
|
|
Packit |
577717 |
#include <perfmon/pfmlib_pentium4.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* private headers */
|
|
Packit |
577717 |
#include "pfmlib_priv.h"
|
|
Packit |
577717 |
#include "pfmlib_pentium4_priv.h"
|
|
Packit |
577717 |
#include "pentium4_events.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
typedef struct {
|
|
Packit |
577717 |
unsigned long addr;
|
|
Packit |
577717 |
char *name;
|
|
Packit |
577717 |
} p4_regmap_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define P4_REGMAP(a, n) { .addr = a, .name = n }
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static p4_regmap_t p4_pmc_regmap[]={
|
|
Packit |
577717 |
/* 0 */ P4_REGMAP(0x3b2, "BPU_ESCR0"),
|
|
Packit |
577717 |
/* 1 */ P4_REGMAP(0x3ba, "IS_ESCR0"),
|
|
Packit |
577717 |
/* 2 */ P4_REGMAP(0x3aa, "MOB_ESCR0"),
|
|
Packit |
577717 |
/* 3 */ P4_REGMAP(0x3b6, "ITLB_ESCR0"),
|
|
Packit |
577717 |
/* 4 */ P4_REGMAP(0x3ac, "PMH_ESCR0"),
|
|
Packit |
577717 |
/* 5 */ P4_REGMAP(0x3c8, "IX_ESCR0"),
|
|
Packit |
577717 |
/* 6 */ P4_REGMAP(0x3a2, "FSB_ESCR0"),
|
|
Packit |
577717 |
/* 7 */ P4_REGMAP(0x3a0, "BSU_ESCR0"),
|
|
Packit |
577717 |
/* 8 */ P4_REGMAP(0x3c0, "MS_ESCR0"),
|
|
Packit |
577717 |
/* 9 */ P4_REGMAP(0x3c4, "TC_ESCR0"),
|
|
Packit |
577717 |
/* 10 */ P4_REGMAP(0x3c2, "TBPU_ESCR0"),
|
|
Packit |
577717 |
/* 11 */ P4_REGMAP(0x3a6, "FLAME_ESCR0"),
|
|
Packit |
577717 |
/* 12 */ P4_REGMAP(0x3a4, "FIRM_ESCR0"),
|
|
Packit |
577717 |
/* 13 */ P4_REGMAP(0x3ae, "SAAT_ESCR0"),
|
|
Packit |
577717 |
/* 14 */ P4_REGMAP(0x3b0, "U2L_ESCR0"),
|
|
Packit |
577717 |
/* 15 */ P4_REGMAP(0x3a8, "DAC_ESCR0"),
|
|
Packit |
577717 |
/* 16 */ P4_REGMAP(0x3ba, "IQ_ESCR0"),
|
|
Packit |
577717 |
/* 17 */ P4_REGMAP(0x3ca, "ALF_ESCR0"),
|
|
Packit |
577717 |
/* 18 */ P4_REGMAP(0x3bc, "RAT_ESCR0"),
|
|
Packit |
577717 |
/* 19 */ P4_REGMAP(0x3be, "SSU_ESCR0"),
|
|
Packit |
577717 |
/* 20 */ P4_REGMAP(0x3b8, "CRU_ESCR0"),
|
|
Packit |
577717 |
/* 21 */ P4_REGMAP(0x3cc, "CRU_ESCR2"),
|
|
Packit |
577717 |
/* 22 */ P4_REGMAP(0x3e0, "CRU_ESCR4"),
|
|
Packit |
577717 |
/* 23 */ P4_REGMAP(0x360, "BPU_CCCR0"),
|
|
Packit |
577717 |
/* 24 */ P4_REGMAP(0x361, "BPU_CCCR1"),
|
|
Packit |
577717 |
/* 25 */ P4_REGMAP(0x364, "MS_CCCR0"),
|
|
Packit |
577717 |
/* 26 */ P4_REGMAP(0x365, "MS_CCCR1"),
|
|
Packit |
577717 |
/* 27 */ P4_REGMAP(0x368, "FLAME_CCCR0"),
|
|
Packit |
577717 |
/* 28 */ P4_REGMAP(0x369, "FLAME_CCCR1"),
|
|
Packit |
577717 |
/* 29 */ P4_REGMAP(0x36c, "IQ_CCCR0"),
|
|
Packit |
577717 |
/* 30 */ P4_REGMAP(0x36d, "IQ_CCCR1"),
|
|
Packit |
577717 |
/* 31 */ P4_REGMAP(0x370, "IQ_CCCR4"),
|
|
Packit |
577717 |
/* 32 */ P4_REGMAP(0x3b3, "BPU_ESCR1"),
|
|
Packit |
577717 |
/* 33 */ P4_REGMAP(0x3b5, "IS_ESCR1"),
|
|
Packit |
577717 |
/* 34 */ P4_REGMAP(0x3ab, "MOB_ESCR1"),
|
|
Packit |
577717 |
/* 35 */ P4_REGMAP(0x3b7, "ITLB_ESCR1"),
|
|
Packit |
577717 |
/* 36 */ P4_REGMAP(0x3ad, "PMH_ESCR1"),
|
|
Packit |
577717 |
/* 37 */ P4_REGMAP(0x3c9, "IX_ESCR1"),
|
|
Packit |
577717 |
/* 38 */ P4_REGMAP(0x3a3, "FSB_ESCR1"),
|
|
Packit |
577717 |
/* 39 */ P4_REGMAP(0x3a1, "BSU_ESCR1"),
|
|
Packit |
577717 |
/* 40 */ P4_REGMAP(0x3c1, "MS_ESCR1"),
|
|
Packit |
577717 |
/* 41 */ P4_REGMAP(0x3c5, "TC_ESCR1"),
|
|
Packit |
577717 |
/* 42 */ P4_REGMAP(0x3c3, "TBPU_ESCR1"),
|
|
Packit |
577717 |
/* 43 */ P4_REGMAP(0x3a7, "FLAME_ESCR1"),
|
|
Packit |
577717 |
/* 44 */ P4_REGMAP(0x3a5, "FIRM_ESCR1"),
|
|
Packit |
577717 |
/* 45 */ P4_REGMAP(0x3af, "SAAT_ESCR1"),
|
|
Packit |
577717 |
/* 46 */ P4_REGMAP(0x3b1, "U2L_ESCR1"),
|
|
Packit |
577717 |
/* 47 */ P4_REGMAP(0x3a9, "DAC_ESCR1"),
|
|
Packit |
577717 |
/* 48 */ P4_REGMAP(0x3bb, "IQ_ESCR1"),
|
|
Packit |
577717 |
/* 49 */ P4_REGMAP(0x3cb, "ALF_ESCR1"),
|
|
Packit |
577717 |
/* 50 */ P4_REGMAP(0x3bd, "RAT_ESCR1"),
|
|
Packit |
577717 |
/* 51 */ P4_REGMAP(0x3b9, "CRU_ESCR1"),
|
|
Packit |
577717 |
/* 52 */ P4_REGMAP(0x3cd, "CRU_ESCR3"),
|
|
Packit |
577717 |
/* 53 */ P4_REGMAP(0x3e1, "CRU_ESCR5"),
|
|
Packit |
577717 |
/* 54 */ P4_REGMAP(0x362, "BPU_CCCR2"),
|
|
Packit |
577717 |
/* 55 */ P4_REGMAP(0x363, "BPU_CCCR3"),
|
|
Packit |
577717 |
/* 56 */ P4_REGMAP(0x366, "MS_CCCR2"),
|
|
Packit |
577717 |
/* 57 */ P4_REGMAP(0x367, "MS_CCCR3"),
|
|
Packit |
577717 |
/* 58 */ P4_REGMAP(0x36a, "FLAME_CCCR2"),
|
|
Packit |
577717 |
/* 59 */ P4_REGMAP(0x36b, "FLAME_CCCR3"),
|
|
Packit |
577717 |
/* 60 */ P4_REGMAP(0x36e, "IQ_CCCR2"),
|
|
Packit |
577717 |
/* 61 */ P4_REGMAP(0x36f, "IQ_CCCR3"),
|
|
Packit |
577717 |
/* 62 */ P4_REGMAP(0x371, "IQ_CCCR5"),
|
|
Packit |
577717 |
/* 63 */ P4_REGMAP(0x3f2, "PEBS_MATRIX_VERT"),
|
|
Packit |
577717 |
/* 64 */ P4_REGMAP(0x3f1, "PEBS_ENABLE"),
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define PMC_PEBS_MATRIX_VERT 63
|
|
Packit |
577717 |
#define PMC_PEBS_ENABLE 64
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static p4_regmap_t p4_pmd_regmap[]={
|
|
Packit |
577717 |
/* 0 */ P4_REGMAP(0x300, "BPU_CTR0"),
|
|
Packit |
577717 |
/* 1 */ P4_REGMAP(0x301, "BPU_CTR1"),
|
|
Packit |
577717 |
/* 2 */ P4_REGMAP(0x304, "MS_CTR0"),
|
|
Packit |
577717 |
/* 3 */ P4_REGMAP(0x305, "MS_CTR1"),
|
|
Packit |
577717 |
/* 4 */ P4_REGMAP(0x308, "FLAME_CTR0"),
|
|
Packit |
577717 |
/* 5 */ P4_REGMAP(0x309, "FLAME_CTR1"),
|
|
Packit |
577717 |
/* 6 */ P4_REGMAP(0x30c, "IQ_CTR0"),
|
|
Packit |
577717 |
/* 7 */ P4_REGMAP(0x30d, "IQ_CTR1"),
|
|
Packit |
577717 |
/* 8 */ P4_REGMAP(0x310, "IQ_CTR4"),
|
|
Packit |
577717 |
/* 9 */ P4_REGMAP(0x302, "BPU_CTR2"),
|
|
Packit |
577717 |
/* 10 */ P4_REGMAP(0x303, "BPU_CTR3"),
|
|
Packit |
577717 |
/* 11 */ P4_REGMAP(0x306, "MS_CTR2"),
|
|
Packit |
577717 |
/* 12 */ P4_REGMAP(0x307, "MS_CTR3"),
|
|
Packit |
577717 |
/* 13 */ P4_REGMAP(0x30a, "FLAME_CTR2"),
|
|
Packit |
577717 |
/* 14 */ P4_REGMAP(0x30b, "FLAME_CTR3"),
|
|
Packit |
577717 |
/* 15 */ P4_REGMAP(0x30d, "IQ_CTR2"),
|
|
Packit |
577717 |
/* 16 */ P4_REGMAP(0x30f, "IQ_CTR3"),
|
|
Packit |
577717 |
/* 17 */ P4_REGMAP(0x311, "IQ_CTR5"),
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* This array provides values for the PEBS_ENABLE and PEBS_MATRIX_VERT
|
|
Packit |
577717 |
registers to support a series of metric for replay_event.
|
|
Packit |
577717 |
The first two entries are dummies; the remaining 9 correspond to
|
|
Packit |
577717 |
virtual bit masks in the replay_event definition and map onto Intel
|
|
Packit |
577717 |
documentation.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define P4_REPLAY_REAL_MASK 0x00000003
|
|
Packit |
577717 |
#define P4_REPLAY_VIRT_MASK 0x00000FFC
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static pentium4_replay_regs_t p4_replay_regs[]={
|
|
Packit |
577717 |
/* 0 */ {.enb = 0, /* dummy */
|
|
Packit |
577717 |
.mat_vert = 0,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 1 */ {.enb = 0, /* dummy */
|
|
Packit |
577717 |
.mat_vert = 0,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 2 */ {.enb = 0x01000001, /* 1stL_cache_load_miss_retired */
|
|
Packit |
577717 |
.mat_vert = 0x00000001,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 3 */ {.enb = 0x01000002, /* 2ndL_cache_load_miss_retired */
|
|
Packit |
577717 |
.mat_vert = 0x00000001,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 4 */ {.enb = 0x01000004, /* DTLB_load_miss_retired */
|
|
Packit |
577717 |
.mat_vert = 0x00000001,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 5 */ {.enb = 0x01000004, /* DTLB_store_miss_retired */
|
|
Packit |
577717 |
.mat_vert = 0x00000002,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 6 */ {.enb = 0x01000004, /* DTLB_all_miss_retired */
|
|
Packit |
577717 |
.mat_vert = 0x00000003,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 7 */ {.enb = 0x01018001, /* Tagged_mispred_branch */
|
|
Packit |
577717 |
.mat_vert = 0x00000010,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 8 */ {.enb = 0x01000200, /* MOB_load_replay_retired */
|
|
Packit |
577717 |
.mat_vert = 0x00000001,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 9 */ {.enb = 0x01000400, /* split_load_retired */
|
|
Packit |
577717 |
.mat_vert = 0x00000001,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
/* 10 */ {.enb = 0x01000400, /* split_store_retired */
|
|
Packit |
577717 |
.mat_vert = 0x00000002,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int p4_model;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_event_code
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Return the event-select value for the specified event as
|
|
Packit |
577717 |
* needed for the specified PMD counter.
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static int pentium4_get_event_code(unsigned int event,
|
|
Packit |
577717 |
unsigned int pmd,
|
|
Packit |
577717 |
int *code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i, j, escr, cccr;
|
|
Packit |
577717 |
int rc = PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmd >= PENTIUM4_NUM_PMDS && pmd != PFMLIB_CNT_FIRST) {
|
|
Packit |
577717 |
goto out;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Check that the specified event is allowed for the specified PMD.
|
|
Packit |
577717 |
* Each event has a specific set of ESCRs it can use, which implies
|
|
Packit |
577717 |
* a specific set of CCCRs (and thus PMDs). A specified PMD of -1
|
|
Packit |
577717 |
* means assume any allowable PMD.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pmd == PFMLIB_CNT_FIRST) {
|
|
Packit |
577717 |
*code = pentium4_events[event].event_select;
|
|
Packit |
577717 |
rc = PFMLIB_SUCCESS;
|
|
Packit |
577717 |
goto out;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = 0; i < MAX_ESCRS_PER_EVENT; i++) {
|
|
Packit |
577717 |
escr = pentium4_events[event].allowed_escrs[i];
|
|
Packit |
577717 |
if (escr < 0) {
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j = 0; j < MAX_CCCRS_PER_ESCR; j++) {
|
|
Packit |
577717 |
cccr = pentium4_escrs[escr].allowed_cccrs[j];
|
|
Packit |
577717 |
if (cccr < 0) {
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmd == pentium4_cccrs[cccr].pmd) {
|
|
Packit |
577717 |
*code = pentium4_events[event].event_select;
|
|
Packit |
577717 |
rc = PFMLIB_SUCCESS;
|
|
Packit |
577717 |
goto out;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
out:
|
|
Packit |
577717 |
return rc;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_event_name
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Return the name of the specified event.
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static char *pentium4_get_event_name(unsigned int event)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return pentium4_events[event].name;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_event_mask_name
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Return the name of the specified event-mask.
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static char *pentium4_get_event_mask_name(unsigned int event, unsigned int mask)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (mask >= EVENT_MASK_BITS || pentium4_events[event].event_masks[mask].name == NULL)
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pentium4_events[event].event_masks[mask].name;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_event_counters
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Fill in the 'counters' bitmask with all possible PMDs that could be
|
|
Packit |
577717 |
* used to count the specified event.
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static void pentium4_get_event_counters(unsigned int event,
|
|
Packit |
577717 |
pfmlib_regmask_t *counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i, j, escr, cccr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(counters, 0, sizeof(*counters));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = 0; i < MAX_ESCRS_PER_EVENT; i++) {
|
|
Packit |
577717 |
escr = pentium4_events[event].allowed_escrs[i];
|
|
Packit |
577717 |
if (escr < 0) {
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j = 0; j < MAX_CCCRS_PER_ESCR; j++) {
|
|
Packit |
577717 |
cccr = pentium4_escrs[escr].allowed_cccrs[j];
|
|
Packit |
577717 |
if (cccr < 0) {
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pfm_regmask_set(counters, pentium4_cccrs[cccr].pmd);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_num_event_masks
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Count the number of available event-masks for the specified event. All
|
|
Packit |
577717 |
* valid masks in pentium4_events[].event_masks are contiguous in the array
|
|
Packit |
577717 |
* and have a non-NULL name.
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static unsigned int pentium4_get_num_event_masks(unsigned int event)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while (pentium4_events[event].event_masks[i].name) {
|
|
Packit |
577717 |
i++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return i;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_dispatch_events
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Examine each desired event specified in "input" and find an appropriate
|
|
Packit |
577717 |
* ESCR/CCCR pair that can be used to count them.
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static int pentium4_dispatch_events(pfmlib_input_param_t *input,
|
|
Packit |
577717 |
void *model_input,
|
|
Packit |
577717 |
pfmlib_output_param_t *output,
|
|
Packit |
577717 |
void *model_output)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int assigned_pmcs[PENTIUM4_NUM_PMCS] = {0};
|
|
Packit |
577717 |
unsigned int event, event_mask, mask;
|
|
Packit |
577717 |
unsigned int bit, tag_value, tag_enable;
|
|
Packit |
577717 |
unsigned int plm;
|
|
Packit |
577717 |
unsigned int i, j, k, m, n;
|
|
Packit |
577717 |
int escr, escr_pmc;
|
|
Packit |
577717 |
int cccr, cccr_pmc, cccr_pmd;
|
|
Packit |
577717 |
int assigned;
|
|
Packit |
577717 |
pentium4_escr_value_t escr_value;
|
|
Packit |
577717 |
pentium4_cccr_value_t cccr_value;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (input->pfp_event_count > PENTIUM4_NUM_PMDS) {
|
|
Packit |
577717 |
/* Can't specify more events than we have counters. */
|
|
Packit |
577717 |
return PFMLIB_ERR_TOOMANY;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (input->pfp_dfl_plm & (PFM_PLM1|PFM_PLM2)) {
|
|
Packit |
577717 |
/* Can't specify privilege levels 1 or 2. */
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Examine each event specified in input->pfp_events. i counts
|
|
Packit |
577717 |
* through the input->pfp_events array, and j counts through the
|
|
Packit |
577717 |
* PMCs in output->pfp_pmcs as they are set up.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i = 0, j = 0; i < input->pfp_event_count; i++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (input->pfp_events[i].plm & (PFM_PLM1|PFM_PLM2)) {
|
|
Packit |
577717 |
/* Can't specify privilege levels 1 or 2. */
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* INSTR_COMPLETED event only exist for model 3, 4, 6 (Prescott)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (input->pfp_events[i].event == PME_INSTR_COMPLETED &&
|
|
Packit |
577717 |
p4_model != 3 && p4_model != 4 && p4_model != 6)
|
|
Packit |
577717 |
return PFMLIB_ERR_EVTINCOMP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
event = input->pfp_events[i].event;
|
|
Packit |
577717 |
assigned = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Use the event-specific privilege mask if set.
|
|
Packit |
577717 |
* Otherwise use the default privilege mask.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
plm = input->pfp_events[i].plm ?
|
|
Packit |
577717 |
input->pfp_events[i].plm : input->pfp_dfl_plm;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Examine each ESCR that this event could be assigned to. */
|
|
Packit |
577717 |
for (k = 0; k < MAX_ESCRS_PER_EVENT && !assigned; k++) {
|
|
Packit |
577717 |
escr = pentium4_events[event].allowed_escrs[k];
|
|
Packit |
577717 |
if (escr < 0)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Make sure this ESCR isn't already assigned
|
|
Packit |
577717 |
* and isn't on the "unavailable" list.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
escr_pmc = pentium4_escrs[escr].pmc;
|
|
Packit |
577717 |
if (assigned_pmcs[escr_pmc] ||
|
|
Packit |
577717 |
pfm_regmask_isset(&input->pfp_unavail_pmcs, escr_pmc)) {
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Examine each CCCR that can be used with this ESCR. */
|
|
Packit |
577717 |
for (m = 0; m < MAX_CCCRS_PER_ESCR && !assigned; m++) {
|
|
Packit |
577717 |
cccr = pentium4_escrs[escr].allowed_cccrs[m];
|
|
Packit |
577717 |
if (cccr < 0) {
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Make sure this CCCR isn't already assigned
|
|
Packit |
577717 |
* and isn't on the "unavailable" list.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
cccr_pmc = pentium4_cccrs[cccr].pmc;
|
|
Packit |
577717 |
cccr_pmd = pentium4_cccrs[cccr].pmd;
|
|
Packit |
577717 |
if (assigned_pmcs[cccr_pmc] ||
|
|
Packit |
577717 |
pfm_regmask_isset(&input->pfp_unavail_pmcs, cccr_pmc)) {
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Found an available ESCR/CCCR pair. */
|
|
Packit |
577717 |
assigned = 1;
|
|
Packit |
577717 |
assigned_pmcs[escr_pmc] = 1;
|
|
Packit |
577717 |
assigned_pmcs[cccr_pmc] = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Calculate the event-mask value. Invalid masks
|
|
Packit |
577717 |
* specified by the caller are ignored.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
event_mask = 0;
|
|
Packit |
577717 |
tag_value = 0;
|
|
Packit |
577717 |
tag_enable = 0;
|
|
Packit |
577717 |
for (n = 0; n < input->pfp_events[i].num_masks; n++) {
|
|
Packit |
577717 |
mask = input->pfp_events[i].unit_masks[n];
|
|
Packit |
577717 |
bit = pentium4_events[event].event_masks[mask].bit;
|
|
Packit |
577717 |
if (bit < EVENT_MASK_BITS &&
|
|
Packit |
577717 |
pentium4_events[event].event_masks[mask].name) {
|
|
Packit |
577717 |
event_mask |= (1 << bit);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (bit >= EVENT_MASK_BITS &&
|
|
Packit |
577717 |
pentium4_events[event].event_masks[mask].name) {
|
|
Packit |
577717 |
tag_value |= (1 << (bit - EVENT_MASK_BITS));
|
|
Packit |
577717 |
tag_enable = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Set up the ESCR and CCCR register values. */
|
|
Packit |
577717 |
escr_value.val = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
escr_value.bits.t1_usr = 0; /* controlled by kernel */
|
|
Packit |
577717 |
escr_value.bits.t1_os = 0; /* controlled by kernel */
|
|
Packit |
577717 |
escr_value.bits.t0_usr = (plm & PFM_PLM3) ? 1 : 0;
|
|
Packit |
577717 |
escr_value.bits.t0_os = (plm & PFM_PLM0) ? 1 : 0;
|
|
Packit |
577717 |
escr_value.bits.tag_enable = tag_enable;
|
|
Packit |
577717 |
escr_value.bits.tag_value = tag_value;
|
|
Packit |
577717 |
escr_value.bits.event_mask = event_mask;
|
|
Packit |
577717 |
escr_value.bits.event_select = pentium4_events[event].event_select;
|
|
Packit |
577717 |
escr_value.bits.reserved = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cccr_value.val = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cccr_value.bits.reserved1 = 0;
|
|
Packit |
577717 |
cccr_value.bits.enable = 1;
|
|
Packit |
577717 |
cccr_value.bits.escr_select = pentium4_events[event].escr_select;
|
|
Packit |
577717 |
cccr_value.bits.active_thread = 3; /* FIXME: This is set to count when either logical
|
|
Packit |
577717 |
* CPU is active. Need a way to distinguish
|
|
Packit |
577717 |
* between logical CPUs when HT is enabled. */
|
|
Packit |
577717 |
cccr_value.bits.compare = 0; /* FIXME: What do we do with "threshold" settings? */
|
|
Packit |
577717 |
cccr_value.bits.complement = 0; /* FIXME: What do we do with "threshold" settings? */
|
|
Packit |
577717 |
cccr_value.bits.threshold = 0; /* FIXME: What do we do with "threshold" settings? */
|
|
Packit |
577717 |
cccr_value.bits.force_ovf = 0; /* FIXME: Do we want to allow "forcing" overflow
|
|
Packit |
577717 |
* interrupts on all counter increments? */
|
|
Packit |
577717 |
cccr_value.bits.ovf_pmi_t0 = 1;
|
|
Packit |
577717 |
cccr_value.bits.ovf_pmi_t1 = 0; /* PMI taken care of by kernel typically */
|
|
Packit |
577717 |
cccr_value.bits.reserved2 = 0;
|
|
Packit |
577717 |
cccr_value.bits.cascade = 0; /* FIXME: How do we handle "cascading" counters? */
|
|
Packit |
577717 |
cccr_value.bits.overflow = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Special processing for the replay event:
|
|
Packit |
577717 |
Remove virtual mask bits from actual mask;
|
|
Packit |
577717 |
scan mask bit list and OR bit values for each virtual mask
|
|
Packit |
577717 |
into the PEBS ENABLE and PEBS MATRIX VERT registers */
|
|
Packit |
577717 |
if (event == PME_REPLAY_EVENT) {
|
|
Packit |
577717 |
escr_value.bits.event_mask &= P4_REPLAY_REAL_MASK; /* remove virtual mask bits */
|
|
Packit |
577717 |
if (event_mask & P4_REPLAY_VIRT_MASK) { /* find a valid virtual mask */
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_value = 0;
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_num = PMC_PEBS_ENABLE;
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_addr = p4_pmc_regmap[PMC_PEBS_ENABLE].addr;
|
|
Packit |
577717 |
output->pfp_pmcs[j+1].reg_value = 0;
|
|
Packit |
577717 |
output->pfp_pmcs[j+1].reg_num = PMC_PEBS_MATRIX_VERT;
|
|
Packit |
577717 |
output->pfp_pmcs[j+1].reg_addr = p4_pmc_regmap[PMC_PEBS_MATRIX_VERT].addr;
|
|
Packit |
577717 |
for (n = 0; n < input->pfp_events[i].num_masks; n++) {
|
|
Packit |
577717 |
mask = input->pfp_events[i].unit_masks[n];
|
|
Packit |
577717 |
if (mask > 1 && mask < 11) { /* process each valid mask we find */
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_value |= p4_replay_regs[mask].enb;
|
|
Packit |
577717 |
output->pfp_pmcs[j+1].reg_value |= p4_replay_regs[mask].mat_vert;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
j += 2;
|
|
Packit |
577717 |
output->pfp_pmc_count += 2;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Set up the PMCs in the
|
|
Packit |
577717 |
* output->pfp_pmcs array.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_num = escr_pmc;
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_value = escr_value.val;
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_addr = p4_pmc_regmap[escr_pmc].addr;
|
|
Packit |
577717 |
j++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[%s(pmc%u)=0x%lx os=%u usr=%u tag=%u tagval=0x%x mask=%u sel=0x%x] %s\n",
|
|
Packit |
577717 |
p4_pmc_regmap[escr_pmc].name,
|
|
Packit |
577717 |
escr_pmc,
|
|
Packit |
577717 |
escr_value.val,
|
|
Packit |
577717 |
escr_value.bits.t0_os,
|
|
Packit |
577717 |
escr_value.bits.t0_usr,
|
|
Packit |
577717 |
escr_value.bits.tag_enable,
|
|
Packit |
577717 |
escr_value.bits.tag_value,
|
|
Packit |
577717 |
escr_value.bits.event_mask,
|
|
Packit |
577717 |
escr_value.bits.event_select,
|
|
Packit |
577717 |
pentium4_events[event].name);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_num = cccr_pmc;
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_value = cccr_value.val;
|
|
Packit |
577717 |
output->pfp_pmcs[j].reg_addr = p4_pmc_regmap[cccr_pmc].addr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
output->pfp_pmds[i].reg_num = cccr_pmd;
|
|
Packit |
577717 |
output->pfp_pmds[i].reg_addr = p4_pmd_regmap[cccr_pmd].addr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[%s(pmc%u)=0x%lx ena=1 sel=0x%x cmp=%u cmpl=%u thres=%u edg=%u cas=%u] %s\n",
|
|
Packit |
577717 |
p4_pmc_regmap[cccr_pmc].name,
|
|
Packit |
577717 |
cccr_pmc,
|
|
Packit |
577717 |
cccr_value.val,
|
|
Packit |
577717 |
cccr_value.bits.escr_select,
|
|
Packit |
577717 |
cccr_value.bits.compare,
|
|
Packit |
577717 |
cccr_value.bits.complement,
|
|
Packit |
577717 |
cccr_value.bits.threshold,
|
|
Packit |
577717 |
cccr_value.bits.edge,
|
|
Packit |
577717 |
cccr_value.bits.cascade,
|
|
Packit |
577717 |
pentium4_events[event].name);
|
|
Packit |
577717 |
__pfm_vbprintf("[%s(pmd%u)]\n", p4_pmd_regmap[output->pfp_pmds[i].reg_num].name, output->pfp_pmds[i].reg_num);
|
|
Packit |
577717 |
j++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
output->pfp_pmc_count += 2;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (k == MAX_ESCRS_PER_EVENT && !assigned) {
|
|
Packit |
577717 |
/* Couldn't find an available ESCR and/or CCCR. */
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
output->pfp_pmd_count = input->pfp_event_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_pmu_detect
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Determine whether the system we're running on is a Pentium4
|
|
Packit |
577717 |
* (or other CPU that uses the same PMU).
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static int pentium4_pmu_detect(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret, family;
|
|
Packit |
577717 |
char buffer[128];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = __pfm_getcpuinfo_attr("vendor_id", buffer, sizeof(buffer));
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (strcmp(buffer, "GenuineIntel"))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = __pfm_getcpuinfo_attr("cpu family", buffer, sizeof(buffer));
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
family = atoi(buffer);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = __pfm_getcpuinfo_attr("model", buffer, sizeof(buffer));
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we use model to detect model 2 which has one more counter IQ_ESCR1
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
p4_model = atoi(buffer);
|
|
Packit |
577717 |
if (family != 15)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* IQ_ESCR0, IQ_ESCR1 only for model 1 and 2
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (p4_model >2)
|
|
Packit |
577717 |
pentium4_support.pmc_count -= 2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return family == 15 ? PFMLIB_SUCCESS : PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_impl_pmcs
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Set the appropriate bit in the impl_pmcs bitmask for each PMC that's
|
|
Packit |
577717 |
* available on Pentium4.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* FIXME: How can we detect when HyperThreading is enabled?
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static void pentium4_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i = 0; i < PENTIUM4_NUM_PMCS; i++) {
|
|
Packit |
577717 |
pfm_regmask_set(impl_pmcs, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* IQ_ESCR0, IQ_ESCR1 only available on model 1 and 2
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (p4_model > 2) {
|
|
Packit |
577717 |
pfm_regmask_clr(impl_pmcs, 16);
|
|
Packit |
577717 |
pfm_regmask_clr(impl_pmcs, 48);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_impl_pmds
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Set the appropriate bit in the impl_pmcs bitmask for each PMD that's
|
|
Packit |
577717 |
* available on Pentium4.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* FIXME: How can we detect when HyperThreading is enabled?
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static void pentium4_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i = 0; i < PENTIUM4_NUM_PMDS; i++) {
|
|
Packit |
577717 |
pfm_regmask_set(impl_pmds, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_impl_counters
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Set the appropriate bit in the impl_counters bitmask for each counter
|
|
Packit |
577717 |
* that's available on Pentium4.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* For now, all PMDs are counters, so just call get_impl_pmds().
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static void pentium4_get_impl_counters(pfmlib_regmask_t *impl_counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pentium4_get_impl_pmds(impl_counters);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_hw_counter_width
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Return the number of usable bits in the PMD counters.
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static void pentium4_get_hw_counter_width(unsigned int *width)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
*width = PENTIUM4_COUNTER_WIDTH;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_event_desc
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Return the description for the specified event (if it has one).
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* FIXME: In this routine, we make a copy of the description string to
|
|
Packit |
577717 |
* return. But in get_event_name(), we just return the string
|
|
Packit |
577717 |
* directly. Why the difference?
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static int pentium4_get_event_desc(unsigned int event, char **desc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (pentium4_events[event].desc) {
|
|
Packit |
577717 |
*desc = strdup(pentium4_events[event].desc);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
*desc = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_get_event_mask_desc
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Return the description for the specified event-mask (if it has one).
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
static int pentium4_get_event_mask_desc(unsigned int event,
|
|
Packit |
577717 |
unsigned int mask, char **desc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (mask >= EVENT_MASK_BITS || pentium4_events[event].event_masks[mask].desc == NULL)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*desc = strdup(pentium4_events[event].event_masks[mask].desc);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int pentium4_get_event_mask_code(unsigned int event,
|
|
Packit |
577717 |
unsigned int mask, unsigned int *code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
*code = 1U << pentium4_events[event].event_masks[mask].bit;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pentium4_get_cycle_event(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
e->event = PENTIUM4_CPU_CLK_UNHALTED;
|
|
Packit |
577717 |
e->num_masks = 1;
|
|
Packit |
577717 |
e->unit_masks[0] = 0;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pentium4_get_inst_retired(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* some models do not implement INSTR_COMPLETED
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (p4_model != 3 && p4_model != 4 && p4_model != 6) {
|
|
Packit |
577717 |
e->event = PENTIUM4_INST_RETIRED;
|
|
Packit |
577717 |
e->num_masks = 2;
|
|
Packit |
577717 |
e->unit_masks[0] = 0;
|
|
Packit |
577717 |
e->unit_masks[1] = 1;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
e->event = PME_INSTR_COMPLETED;
|
|
Packit |
577717 |
e->num_masks = 1;
|
|
Packit |
577717 |
e->unit_masks[0] = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* pentium4_support
|
|
Packit |
577717 |
**/
|
|
Packit |
577717 |
pfm_pmu_support_t pentium4_support = {
|
|
Packit |
577717 |
.pmu_name = "Pentium4/Xeon/EM64T",
|
|
Packit |
577717 |
.pmu_type = PFMLIB_PENTIUM4_PMU,
|
|
Packit |
577717 |
.pme_count = PENTIUM4_EVENT_COUNT,
|
|
Packit |
577717 |
.pmd_count = PENTIUM4_NUM_PMDS,
|
|
Packit |
577717 |
.pmc_count = PENTIUM4_NUM_PMCS,
|
|
Packit |
577717 |
.num_cnt = PENTIUM4_NUM_PMDS,
|
|
Packit |
577717 |
.get_event_code = pentium4_get_event_code,
|
|
Packit |
577717 |
.get_event_name = pentium4_get_event_name,
|
|
Packit |
577717 |
.get_event_mask_name = pentium4_get_event_mask_name,
|
|
Packit |
577717 |
.get_event_counters = pentium4_get_event_counters,
|
|
Packit |
577717 |
.get_num_event_masks = pentium4_get_num_event_masks,
|
|
Packit |
577717 |
.dispatch_events = pentium4_dispatch_events,
|
|
Packit |
577717 |
.pmu_detect = pentium4_pmu_detect,
|
|
Packit |
577717 |
.get_impl_pmcs = pentium4_get_impl_pmcs,
|
|
Packit |
577717 |
.get_impl_pmds = pentium4_get_impl_pmds,
|
|
Packit |
577717 |
.get_impl_counters = pentium4_get_impl_counters,
|
|
Packit |
577717 |
.get_hw_counter_width = pentium4_get_hw_counter_width,
|
|
Packit |
577717 |
.get_event_desc = pentium4_get_event_desc,
|
|
Packit |
577717 |
.get_event_mask_desc = pentium4_get_event_mask_desc,
|
|
Packit |
577717 |
.get_event_mask_code = pentium4_get_event_mask_code,
|
|
Packit |
577717 |
.get_cycle_event = pentium4_get_cycle_event,
|
|
Packit |
577717 |
.get_inst_retired_event = pentium4_get_inst_retired
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|