|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_cell.c : support for the Cell PMU family
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2007 TOSHIBA CORPORATION based on code from
|
|
Packit |
577717 |
* Copyright (c) 2001-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_cell.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* private headers */
|
|
Packit |
577717 |
#include "pfmlib_priv.h" /* library private */
|
|
Packit |
577717 |
#include "pfmlib_cell_priv.h" /* architecture private */
|
|
Packit |
577717 |
#include "cell_events.h" /* PMU private */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define SIGNAL_TYPE_CYCLES 0
|
|
Packit |
577717 |
#define PM_COUNTER_CTRL_CYLES 0x42C00000U
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define PFM_CELL_NUM_PMCS 24
|
|
Packit |
577717 |
#define PFM_CELL_EVENT_MIN 1
|
|
Packit |
577717 |
#define PFM_CELL_EVENT_MAX 8
|
|
Packit |
577717 |
#define PMX_MIN_NUM 1
|
|
Packit |
577717 |
#define PMX_MAX_NUM 8
|
|
Packit |
577717 |
#define PFM_CELL_16BIT_CNTR_EVENT_MAX 8
|
|
Packit |
577717 |
#define PFM_CELL_32BIT_CNTR_EVENT_MAX 4
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define COMMON_REG_NUMS 8
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define ENABLE_WORD0 0
|
|
Packit |
577717 |
#define ENABLE_WORD1 1
|
|
Packit |
577717 |
#define ENABLE_WORD2 2
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define PFM_CELL_GRP_CONTROL_REG_GRP0_BIT 30
|
|
Packit |
577717 |
#define PFM_CELL_GRP_CONTROL_REG_GRP1_BIT 28
|
|
Packit |
577717 |
#define PFM_CELL_BASE_WORD_UNIT_FIELD_BIT 24
|
|
Packit |
577717 |
#define PFM_CELL_WORD_UNIT_FIELD_WIDTH 2
|
|
Packit |
577717 |
#define PFM_CELL_MAX_WORD_NUMBER 3
|
|
Packit |
577717 |
#define PFM_CELL_COUNTER_CONTROL_GRP1 0x80000000U
|
|
Packit |
577717 |
#define PFM_CELL_DEFAULT_TRIGGER_EVENT_UNIT 0x00555500U
|
|
Packit |
577717 |
#define PFM_CELL_PM_CONTROL_16BIT_CNTR_MASK 0x01E00000U
|
|
Packit |
577717 |
#define PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_PROBLEM 0x00080000U
|
|
Packit |
577717 |
#define PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_SUPERVISOR 0x00000000U
|
|
Packit |
577717 |
#define PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_HYPERVISOR 0x00040000U
|
|
Packit |
577717 |
#define PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_ALL 0x000C0000U
|
|
Packit |
577717 |
#define PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_MASK 0x000C0000U
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define ONLY_WORD(x) \
|
|
Packit |
577717 |
((x == WORD_0_ONLY)||(x == WORD_2_ONLY)) ? x : 0
|
|
Packit |
577717 |
|
|
Packit |
577717 |
struct pfm_cell_signal_group_desc {
|
|
Packit |
577717 |
unsigned int signal_type;
|
|
Packit |
577717 |
unsigned int word_type;
|
|
Packit |
577717 |
unsigned long long word;
|
|
Packit |
577717 |
unsigned long long freq;
|
|
Packit |
577717 |
unsigned int subunit;
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define swap_int(num1, num2) do { \
|
|
Packit |
577717 |
int tmp = num1; \
|
|
Packit |
577717 |
num1 = num2; \
|
|
Packit |
577717 |
num2 = tmp; \
|
|
Packit |
577717 |
} while(0)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_cell_detect(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
char buffer[128];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = __pfm_getcpuinfo_attr("cpu", buffer, sizeof(buffer));
|
|
Packit |
577717 |
if (ret == -1) {
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (strcmp(buffer, "Cell Broadband Engine, altivec supported")) {
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
get_pmx_offset(int pmx_num, unsigned int *pmx_ctrl_bits)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
/* pmx_num==0 -> not specified
|
|
Packit |
577717 |
* pmx_num==1 -> pm0
|
|
Packit |
577717 |
* :
|
|
Packit |
577717 |
* pmx_num==8 -> pm7
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int i = 0;
|
|
Packit |
577717 |
int offset;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((pmx_num >= PMX_MIN_NUM) && (pmx_num <= PMX_MAX_NUM)) {
|
|
Packit |
577717 |
/* offset is specified */
|
|
Packit |
577717 |
offset = (pmx_num - 1);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((~*pmx_ctrl_bits >> offset) & 0x1) {
|
|
Packit |
577717 |
*pmx_ctrl_bits |= (0x1 << offset);
|
|
Packit |
577717 |
return offset;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
/* offset is used */
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else if (pmx_num == 0){
|
|
Packit |
577717 |
/* offset is not specified */
|
|
Packit |
577717 |
while (((*pmx_ctrl_bits >> i) & 0x1) && (i < PMX_MAX_NUM)) {
|
|
Packit |
577717 |
i++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
*pmx_ctrl_bits |= (0x1 << i);
|
|
Packit |
577717 |
return i;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* pmx_num is invalid */
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static unsigned long long
|
|
Packit |
577717 |
search_enable_word(int word)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned long long count = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while ((~word) & 0x1) {
|
|
Packit |
577717 |
count++;
|
|
Packit |
577717 |
word >>= 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return count;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int get_count_bit(unsigned int type)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int count = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while(type) {
|
|
Packit |
577717 |
if (type & 1) {
|
|
Packit |
577717 |
count++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
type >>= 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return count;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
get_debug_bus_word(struct pfm_cell_signal_group_desc *group0, struct pfm_cell_signal_group_desc *group1)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int word_type0, word_type1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* search enable word */
|
|
Packit |
577717 |
word_type0 = group0->word_type;
|
|
Packit |
577717 |
word_type1 = group1->word_type;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (group1->signal_type == NONE_SIGNAL) {
|
|
Packit |
577717 |
group0->word = search_enable_word(word_type0);
|
|
Packit |
577717 |
goto found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* swap */
|
|
Packit |
577717 |
if ((get_count_bit(word_type0) > get_count_bit(word_type1)) ||
|
|
Packit |
577717 |
(group0->freq == PFM_CELL_PME_FREQ_SPU)) {
|
|
Packit |
577717 |
swap_int(group0->signal_type, group1->signal_type);
|
|
Packit |
577717 |
swap_int(group0->freq, group1->freq);
|
|
Packit |
577717 |
swap_int(group0->word_type, group1->word_type);
|
|
Packit |
577717 |
swap_int(group0->subunit, group1->subunit);
|
|
Packit |
577717 |
swap_int(word_type0, word_type1);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((ONLY_WORD(word_type0) != 0) && (word_type0 == word_type1)) {
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ONLY_WORD(word_type0)) {
|
|
Packit |
577717 |
group0->word = search_enable_word(ONLY_WORD(word_type0));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
word_type1 &= ~(1UL << (group0->word));
|
|
Packit |
577717 |
group1->word = search_enable_word(word_type1);
|
|
Packit |
577717 |
} else if (ONLY_WORD(word_type1)) {
|
|
Packit |
577717 |
group1->word = search_enable_word(ONLY_WORD(word_type1));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
word_type0 &= ~(1UL << (group1->word));
|
|
Packit |
577717 |
group0->word = search_enable_word(word_type0);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
group0->word = ENABLE_WORD0;
|
|
Packit |
577717 |
if (word_type1 == WORD_0_AND_1) {
|
|
Packit |
577717 |
group1->word = ENABLE_WORD1;
|
|
Packit |
577717 |
} else if(word_type1 == WORD_0_AND_2) {
|
|
Packit |
577717 |
group1->word = ENABLE_WORD2;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static unsigned int get_signal_type(unsigned long long event_code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return (event_code & 0x00000000FFFFFFFFULL) / 100;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static unsigned int get_signal_bit(unsigned long long event_code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return (event_code & 0x00000000FFFFFFFFULL) % 100;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int is_spe_signal_group(unsigned int signal_type)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (41 <= signal_type && signal_type <= 56) {
|
|
Packit |
577717 |
return 1;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
check_signal_type(pfmlib_input_param_t *inp,
|
|
Packit |
577717 |
pfmlib_cell_input_param_t *mod_in,
|
|
Packit |
577717 |
struct pfm_cell_signal_group_desc *group0,
|
|
Packit |
577717 |
struct pfm_cell_signal_group_desc *group1)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_event_t *e;
|
|
Packit |
577717 |
unsigned int event_cnt;
|
|
Packit |
577717 |
int signal_cnt = 0;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
int cycles_signal_cnt = 0;
|
|
Packit |
577717 |
unsigned int signal_type, subunit;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e = inp->pfp_events;
|
|
Packit |
577717 |
event_cnt = inp->pfp_event_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i = 0; i < event_cnt; i++) {
|
|
Packit |
577717 |
signal_type = get_signal_type(cell_pe[e[i].event].pme_code);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((signal_type == SIGNAL_SPU_TRIGGER)
|
|
Packit |
577717 |
|| (signal_type == SIGNAL_SPU_EVENT)) {
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (signal_type == SIGNAL_TYPE_CYCLES) {
|
|
Packit |
577717 |
cycles_signal_cnt = 1;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
subunit = 0;
|
|
Packit |
577717 |
if (is_spe_signal_group(signal_type)) {
|
|
Packit |
577717 |
subunit = mod_in->pfp_cell_counters[i].spe_subunit;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
switch(signal_cnt) {
|
|
Packit |
577717 |
case 0:
|
|
Packit |
577717 |
group0->signal_type = signal_type;
|
|
Packit |
577717 |
group0->word_type = cell_pe[e[i].event].pme_enable_word;
|
|
Packit |
577717 |
group0->freq = cell_pe[e[i].event].pme_freq;
|
|
Packit |
577717 |
group0->subunit = subunit;
|
|
Packit |
577717 |
signal_cnt++;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
case 1:
|
|
Packit |
577717 |
if ((group0->signal_type != signal_type) ||
|
|
Packit |
577717 |
(is_spe_signal_group(signal_type) && group0->subunit != subunit)) {
|
|
Packit |
577717 |
group1->signal_type = signal_type;
|
|
Packit |
577717 |
group1->word_type = cell_pe[e[i].event].pme_enable_word;
|
|
Packit |
577717 |
group1->freq = cell_pe[e[i].event].pme_freq;
|
|
Packit |
577717 |
group1->subunit = subunit;
|
|
Packit |
577717 |
signal_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
case 2:
|
|
Packit |
577717 |
if ((group0->signal_type != signal_type)
|
|
Packit |
577717 |
&& (group1->signal_type != signal_type)) {
|
|
Packit |
577717 |
DPRINT("signal count is invalid\n");
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
DPRINT("signal count is invalid\n");
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return (signal_cnt + cycles_signal_cnt);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* The assignment between the privilege leve options
|
|
Packit |
577717 |
* and ppu-count-mode field in pm_control register.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* option ppu count mode(pm_control)
|
|
Packit |
577717 |
* ---------------------------------
|
|
Packit |
577717 |
* -u(-3) 0b10 : Problem mode
|
|
Packit |
577717 |
* -k(-0) 0b00 : Supervisor mode
|
|
Packit |
577717 |
* -1 0b00 : Supervisor mode
|
|
Packit |
577717 |
* -2 0b01 : Hypervisor mode
|
|
Packit |
577717 |
* two options 0b11 : Any mode
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Note : Hypervisor-mode and Any-mode don't work on PS3.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static unsigned int get_ppu_count_mode(unsigned int plm)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int ppu_count_mode = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch (plm) {
|
|
Packit |
577717 |
case PFM_PLM0:
|
|
Packit |
577717 |
case PFM_PLM1:
|
|
Packit |
577717 |
ppu_count_mode = PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_SUPERVISOR;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
case PFM_PLM2:
|
|
Packit |
577717 |
ppu_count_mode = PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_HYPERVISOR;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
case PFM_PLM3:
|
|
Packit |
577717 |
ppu_count_mode = PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_PROBLEM;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
default :
|
|
Packit |
577717 |
ppu_count_mode = PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_ALL;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return ppu_count_mode;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_cell_dispatch_counters(pfmlib_input_param_t *inp,
|
|
Packit |
577717 |
pfmlib_cell_input_param_t *mod_in,
|
|
Packit |
577717 |
pfmlib_output_param_t *outp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_event_t *e;
|
|
Packit |
577717 |
pfmlib_reg_t *pc, *pd;
|
|
Packit |
577717 |
unsigned int event_cnt;
|
|
Packit |
577717 |
unsigned int signal_cnt = 0, pmcs_cnt = 0;
|
|
Packit |
577717 |
unsigned int signal_type;
|
|
Packit |
577717 |
unsigned long long signal_bit;
|
|
Packit |
577717 |
struct pfm_cell_signal_group_desc group[2];
|
|
Packit |
577717 |
int pmx_offset = 0;
|
|
Packit |
577717 |
int i, ret;
|
|
Packit |
577717 |
int input_control, polarity, count_cycle, count_enable;
|
|
Packit |
577717 |
unsigned long long subunit;
|
|
Packit |
577717 |
int shift0, shift1;
|
|
Packit |
577717 |
unsigned int pmx_ctrl_bits;
|
|
Packit |
577717 |
int max_event_cnt = PFM_CELL_32BIT_CNTR_EVENT_MAX;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
count_enable = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
group[0].signal_type = group[1].signal_type = NONE_SIGNAL;
|
|
Packit |
577717 |
group[0].word = group[1].word = 0L;
|
|
Packit |
577717 |
group[0].freq = group[1].freq = 0L;
|
|
Packit |
577717 |
group[0].subunit = group[1].subunit = 0;
|
|
Packit |
577717 |
group[0].word_type = group[1].word_type = WORD_NONE;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
event_cnt = inp->pfp_event_count;
|
|
Packit |
577717 |
e = inp->pfp_events;
|
|
Packit |
577717 |
pc = outp->pfp_pmcs;
|
|
Packit |
577717 |
pd = outp->pfp_pmds;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* check event_cnt */
|
|
Packit |
577717 |
if (mod_in->control & PFM_CELL_PM_CONTROL_16BIT_CNTR_MASK)
|
|
Packit |
577717 |
max_event_cnt = PFM_CELL_16BIT_CNTR_EVENT_MAX;
|
|
Packit |
577717 |
if (event_cnt < PFM_CELL_EVENT_MIN)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTFOUND;
|
|
Packit |
577717 |
if (event_cnt > max_event_cnt)
|
|
Packit |
577717 |
return PFMLIB_ERR_TOOMANY;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* check signal type */
|
|
Packit |
577717 |
signal_cnt = check_signal_type(inp, mod_in, &group[0], &group[1]);
|
|
Packit |
577717 |
if (signal_cnt == PFMLIB_ERR_INVAL)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* decide debug_bus word */
|
|
Packit |
577717 |
if (signal_cnt != 0 && group[0].signal_type != NONE_SIGNAL) {
|
|
Packit |
577717 |
ret = get_debug_bus_word(&group[0], &group[1]);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* common register setting */
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_GROUP_CONTROL;
|
|
Packit |
577717 |
if (signal_cnt == 1) {
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value =
|
|
Packit |
577717 |
group[0].word << PFM_CELL_GRP_CONTROL_REG_GRP0_BIT;
|
|
Packit |
577717 |
} else if (signal_cnt == 2) {
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value =
|
|
Packit |
577717 |
(group[0].word << PFM_CELL_GRP_CONTROL_REG_GRP0_BIT) |
|
|
Packit |
577717 |
(group[1].word << PFM_CELL_GRP_CONTROL_REG_GRP1_BIT);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_DEBUG_BUS_CONTROL;
|
|
Packit |
577717 |
if (signal_cnt == 1) {
|
|
Packit |
577717 |
shift0 = PFM_CELL_BASE_WORD_UNIT_FIELD_BIT +
|
|
Packit |
577717 |
((PFM_CELL_MAX_WORD_NUMBER - group[0].word) *
|
|
Packit |
577717 |
PFM_CELL_WORD_UNIT_FIELD_WIDTH);
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = group[0].freq << shift0;
|
|
Packit |
577717 |
} else if (signal_cnt == 2) {
|
|
Packit |
577717 |
shift0 = PFM_CELL_BASE_WORD_UNIT_FIELD_BIT +
|
|
Packit |
577717 |
((PFM_CELL_MAX_WORD_NUMBER - group[0].word) *
|
|
Packit |
577717 |
PFM_CELL_WORD_UNIT_FIELD_WIDTH);
|
|
Packit |
577717 |
shift1 = PFM_CELL_BASE_WORD_UNIT_FIELD_BIT +
|
|
Packit |
577717 |
((PFM_CELL_MAX_WORD_NUMBER - group[1].word) *
|
|
Packit |
577717 |
PFM_CELL_WORD_UNIT_FIELD_WIDTH);
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = (group[0].freq << shift0) |
|
|
Packit |
577717 |
(group[1].freq << shift1);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value |= PFM_CELL_DEFAULT_TRIGGER_EVENT_UNIT;
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_TRACE_ADDRESS;
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = 0;
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_EXT_TRACE_TIMER;
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = 0;
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_PM_STATUS;
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = 0;
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_PM_CONTROL;
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value =
|
|
Packit |
577717 |
(mod_in->control & ~PFM_CELL_PM_CONTROL_PPU_CNTR_MODE_MASK) |
|
|
Packit |
577717 |
get_ppu_count_mode(inp->pfp_dfl_plm);
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_PM_INTERVAL;
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = mod_in->interval;
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_PM_START_STOP;
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = mod_in->triggers;
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmx_ctrl_bits = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* pmX register setting */
|
|
Packit |
577717 |
for(i = 0; i < event_cnt; i++) {
|
|
Packit |
577717 |
/* PMX_CONTROL */
|
|
Packit |
577717 |
pmx_offset = get_pmx_offset(mod_in->pfp_cell_counters[i].pmX_control_num,
|
|
Packit |
577717 |
&pmx_ctrl_bits);
|
|
Packit |
577717 |
if (pmx_offset == PFMLIB_ERR_INVAL) {
|
|
Packit |
577717 |
DPRINT("pmX already used\n");
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
signal_type = get_signal_type(cell_pe[e[i].event].pme_code);
|
|
Packit |
577717 |
if (signal_type == SIGNAL_TYPE_CYCLES) {
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = PM_COUNTER_CTRL_CYLES;
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_PM0_CONTROL + pmx_offset;
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = cell_pe[e[i].event].pme_code;
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_PM0_EVENT + pmx_offset;
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
pd[i].reg_num = pmx_offset;
|
|
Packit |
577717 |
pd[i].reg_value = 0;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch(cell_pe[e[i].event].pme_type) {
|
|
Packit |
577717 |
case COUNT_TYPE_BOTH_TYPE:
|
|
Packit |
577717 |
case COUNT_TYPE_CUMULATIVE_LEN:
|
|
Packit |
577717 |
case COUNT_TYPE_MULTI_CYCLE:
|
|
Packit |
577717 |
case COUNT_TYPE_SINGLE_CYCLE:
|
|
Packit |
577717 |
count_cycle = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
case COUNT_TYPE_OCCURRENCE:
|
|
Packit |
577717 |
count_cycle = 0;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
signal_bit = get_signal_bit(cell_pe[e[i].event].pme_code);
|
|
Packit |
577717 |
polarity = mod_in->pfp_cell_counters[i].polarity;
|
|
Packit |
577717 |
input_control = mod_in->pfp_cell_counters[i].input_control;
|
|
Packit |
577717 |
subunit = 0;
|
|
Packit |
577717 |
if (is_spe_signal_group(signal_type)) {
|
|
Packit |
577717 |
subunit = mod_in->pfp_cell_counters[i].spe_subunit;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = ( (signal_bit << (31 - 5))
|
|
Packit |
577717 |
| (input_control << (31 - 6))
|
|
Packit |
577717 |
| (polarity << (31 - 7))
|
|
Packit |
577717 |
| (count_cycle << (31 - 8))
|
|
Packit |
577717 |
| (count_enable << (31 - 9)) );
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_PM0_CONTROL + pmx_offset;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (signal_type == group[1].signal_type && subunit == group[1].subunit) {
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value |= PFM_CELL_COUNTER_CONTROL_GRP1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* PMX_EVENT */
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_num = REG_PM0_EVENT + pmx_offset;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* debug bus word setting */
|
|
Packit |
577717 |
if (signal_type == group[0].signal_type && subunit == group[0].subunit) {
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = (cell_pe[e[i].event].pme_code |
|
|
Packit |
577717 |
(group[0].word << 48) | (subunit << 32));
|
|
Packit |
577717 |
} else if (signal_type == group[1].signal_type && subunit == group[1].subunit) {
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = (cell_pe[e[i].event].pme_code |
|
|
Packit |
577717 |
(group[1].word << 48) | (subunit << 32));
|
|
Packit |
577717 |
} else if ((signal_type == SIGNAL_SPU_TRIGGER)
|
|
Packit |
577717 |
|| (signal_type == SIGNAL_SPU_EVENT)) {
|
|
Packit |
577717 |
pc[pmcs_cnt].reg_value = cell_pe[e[i].event].pme_code | (subunit << 32);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pmcs_cnt++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* pmd setting */
|
|
Packit |
577717 |
pd[i].reg_num = pmx_offset;
|
|
Packit |
577717 |
pd[i].reg_value = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
outp->pfp_pmc_count = pmcs_cnt;
|
|
Packit |
577717 |
outp->pfp_pmd_count = event_cnt;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_cell_dispatch_events(pfmlib_input_param_t *inp, void *model_in, pfmlib_output_param_t *outp, void *model_out)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_cell_input_param_t *mod_in = (pfmlib_cell_input_param_t *)model_in;
|
|
Packit |
577717 |
pfmlib_cell_input_param_t default_model_in;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (model_in) {
|
|
Packit |
577717 |
mod_in = (pfmlib_cell_input_param_t *)model_in;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
mod_in = &default_model_in;
|
|
Packit |
577717 |
mod_in->control = 0x80000000;
|
|
Packit |
577717 |
mod_in->interval = 0;
|
|
Packit |
577717 |
mod_in->triggers = 0;
|
|
Packit |
577717 |
for (i = 0; i < PMU_CELL_NUM_COUNTERS; i++) {
|
|
Packit |
577717 |
mod_in->pfp_cell_counters[i].pmX_control_num = 0;
|
|
Packit |
577717 |
mod_in->pfp_cell_counters[i].spe_subunit = 0;
|
|
Packit |
577717 |
mod_in->pfp_cell_counters[i].polarity = 1;
|
|
Packit |
577717 |
mod_in->pfp_cell_counters[i].input_control = 0;
|
|
Packit |
577717 |
mod_in->pfp_cell_counters[i].cnt_mask = 0;
|
|
Packit |
577717 |
mod_in->pfp_cell_counters[i].flags = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfm_cell_dispatch_counters(inp, mod_in, outp);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_cell_get_event_code(unsigned int i, unsigned int cnt, int *code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
// if (cnt != PFMLIB_CNT_FIRST && cnt > 2) {
|
|
Packit |
577717 |
if (cnt != PFMLIB_CNT_FIRST && cnt > cell_support.num_cnt) {
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*code = cell_pe[i].pme_code;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_cell_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 < PMU_CELL_NUM_COUNTERS; i++) {
|
|
Packit |
577717 |
pfm_regmask_set(counters, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_cell_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(impl_pmcs, 0, sizeof(*impl_pmcs));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < PFM_CELL_NUM_PMCS; i++) {
|
|
Packit |
577717 |
pfm_regmask_set(impl_pmcs, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_cell_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(impl_pmds, 0, sizeof(*impl_pmds));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < PMU_CELL_NUM_PERFCTR; i++) {
|
|
Packit |
577717 |
pfm_regmask_set(impl_pmds, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_cell_get_impl_counters(pfmlib_regmask_t *impl_counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < PMU_CELL_NUM_COUNTERS; i++) {
|
|
Packit |
577717 |
pfm_regmask_set(impl_counters, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static char*
|
|
Packit |
577717 |
pfm_cell_get_event_name(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return cell_pe[i].pme_name;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_cell_get_event_desc(unsigned int ev, char **str)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *s;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
s = cell_pe[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 int
|
|
Packit |
577717 |
pfm_cell_get_cycle_event(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = 0; i < PME_CELL_EVENT_COUNT; i++) {
|
|
Packit |
577717 |
if (!strcmp(cell_pe[i].pme_name, "CYCLES")) {
|
|
Packit |
577717 |
e->event = i;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTFOUND;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int pfm_cell_spe_event(unsigned int event_index)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (event_index >= PME_CELL_EVENT_COUNT)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return is_spe_signal_group(get_signal_type(cell_pe[event_index].pme_code));
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_pmu_support_t cell_support={
|
|
Packit |
577717 |
.pmu_name = "CELL",
|
|
Packit |
577717 |
.pmu_type = PFMLIB_CELL_PMU,
|
|
Packit |
577717 |
.pme_count = PME_CELL_EVENT_COUNT,
|
|
Packit |
577717 |
.pmc_count = PFM_CELL_NUM_PMCS,
|
|
Packit |
577717 |
.pmd_count = PMU_CELL_NUM_PERFCTR,
|
|
Packit |
577717 |
.num_cnt = PMU_CELL_NUM_COUNTERS,
|
|
Packit |
577717 |
.get_event_code = pfm_cell_get_event_code,
|
|
Packit |
577717 |
.get_event_name = pfm_cell_get_event_name,
|
|
Packit |
577717 |
.get_event_counters = pfm_cell_get_event_counters,
|
|
Packit |
577717 |
.dispatch_events = pfm_cell_dispatch_events,
|
|
Packit |
577717 |
.pmu_detect = pfm_cell_detect,
|
|
Packit |
577717 |
.get_impl_pmcs = pfm_cell_get_impl_pmcs,
|
|
Packit |
577717 |
.get_impl_pmds = pfm_cell_get_impl_pmds,
|
|
Packit |
577717 |
.get_impl_counters = pfm_cell_get_impl_counters,
|
|
Packit |
577717 |
.get_event_desc = pfm_cell_get_event_desc,
|
|
Packit |
577717 |
.get_cycle_event = pfm_cell_get_cycle_event
|
|
Packit |
577717 |
};
|