Hello Stephane,

I have transmitted the mail mistaken a while ago.
I transmit a new patch file(1/5, 2/5, 3/5) from now on.
Would you replace the file?

My best regards,

--Yoshio Funayama


pfmlib_cell.c: Base Cell support for libpfm. It treats Cell specific processing 
as creating PM registers value, checking available event combination and so on.
pfmlib_common.c uses this file.

Signed-off-by: Yoshio Funayama <[EMAIL PROTECTED]>
Signed-off-by: Takayuki Uchikawa <[EMAIL PROTECTED]>

Index: libpfm-3.2-070725/lib/pfmlib_cell.c
===================================================================
--- libpfm-3.2-070725_org/lib/pfmlib_cell.c
+++ libpfm-3.2-070725/lib/pfmlib_cell.c
@@ -0,0 +1,515 @@
+/*
+ * pfmlib_cell.c : support for the Cell PMU family
+ *
+ * Copyright (c) 2007 TOSHIBA CORPORATION based on code from
+ * Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
+ * Contributed by Stephane Eranian <[EMAIL PROTECTED]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies
+ * of the Software, and to permit persons to whom the Software is furnished to 
do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in 
all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR 
A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* public headers */
+#include <perfmon/pfmlib_cell.h>
+
+/* private headers */
+#include "pfmlib_priv.h"       /* library private */
+#include "pfmlib_cell_priv.h"  /* architecture private */
+#include "cell_events.h"       /* PMU private */
+
+#define PFM_CELL_NUM_PMCS      24
+#define PFM_CELL_EVENT_MIN     1
+#define PFM_CELL_EVENT_MAX     8
+#define PMX_MIN_NUM            1
+#define PMX_MAX_NUM            8
+
+#define COMMON_REG_NUMS                8
+
+#define ENABLE_WORD0           0
+#define ENABLE_WORD1           1
+#define ENABLE_WORD2           2
+
+#define PFM_CELL_GROUP_CONTROL_REG_GROUP0_BIT  30
+#define PFM_CELL_GROUP_CONTROL_REG_GROUP1_BIT  28
+#define PFM_CELL_BASE_WORD_UNIT_FIELD_BIT      24
+#define PFM_CELL_WORD_UNIT_FIELD_WIDTH         2
+#define PFM_CELL_MAX_WORD_NUMBER               3
+#define PFM_CELL_DEFAULT_PM_CONTROL_REG_VALUE  0x0
+#define PFM_CELL_COUNTER_CONTROL_GROUP1                0x80000000
+
+#define ONLY_WORD(x) \
+       ((x == WORD_0_ONLY)||(x == WORD_2_ONLY)) ? x : 0 
+
+struct pfm_cell_signal_group_desc {
+       unsigned int            signal_type;
+       unsigned int            word_type;
+       unsigned long long      word;
+       unsigned long long      freq;
+};
+
+#define swap_int(num1, num2) do {      \
+       int tmp = num1;                 \
+       num1 = num2;                    \
+       num2 = tmp;                     \
+} while(0)
+
+static int pmx_ctrl_bits;
+
+static int
+pfm_cell_detect(void)
+{
+       int ret;
+       char buffer[128];
+       
+       pmx_ctrl_bits = 0;
+
+       ret = __pfm_getcpuinfo_attr("cpu", buffer, sizeof(buffer));
+       if (ret == -1) {
+               return PFMLIB_ERR_NOTSUPP;
+       }
+       if (strcmp(buffer, "Cell Broadband Engine, altivec supported")) {
+               return PFMLIB_ERR_NOTSUPP;
+       }
+
+       return PFMLIB_SUCCESS;
+}
+
+static int
+get_pmx_offset(int pmx_num)
+{
+       /* pmx_num==0 -> not specified
+        * pmx_num==1 -> pm0
+        *            :
+        * pmx_num==8 -> pm7
+        */
+       int i = 0;
+       int offset;
+       
+       if ((pmx_num >= PMX_MIN_NUM) && (pmx_num <= PMX_MAX_NUM)) {
+               /* offset is specified */
+               offset = (pmx_num - 1);
+               
+               if ((~pmx_ctrl_bits >> offset) & 0x1) {
+                       pmx_ctrl_bits |= (0x1 << offset);
+                       return offset;
+               } else {
+                       /* offset is used */
+                       return PFMLIB_ERR_INVAL;
+               }
+       } else if (pmx_num == 0){
+               /* offset is not specified */
+               while (((pmx_ctrl_bits >> i) & 0x1) && (i < PMX_MAX_NUM)) {
+                       i++;
+               }
+               pmx_ctrl_bits |= (0x1 << i);
+               return i;
+       }
+       /* pmx_num is invalid */
+       return PFMLIB_ERR_INVAL;
+}
+
+static unsigned long long
+search_enable_word(int word)
+{
+       unsigned long long count = 0;
+       
+       while ((~word) & 0x1) {
+               count++;
+               word >>= 1;
+       }
+       return count;
+}
+
+static int
+get_debug_bus_word(struct pfm_cell_signal_group_desc *group0, struct 
pfm_cell_signal_group_desc *group1)
+{
+       if (group1->signal_type != NONE_SIGNAL) {
+               return PFMLIB_ERR_INVAL;
+       }
+       group0->word = search_enable_word(group0->word_type);
+
+       return PFMLIB_SUCCESS;
+}
+
+static unsigned int get_signal_type(unsigned long long event_code) 
+{
+       return (event_code & 0x00000000FFFFFFFFULL) / 100;
+}      
+
+static unsigned int get_signal_bit(unsigned long long event_code) 
+{
+       return (event_code & 0x00000000FFFFFFFFULL) % 100;
+}      
+
+static int
+check_signal_type(pfmlib_input_param_t *inp,
+                 struct pfm_cell_signal_group_desc *group0, struct 
pfm_cell_signal_group_desc *group1)
+{
+       pfmlib_event_t *e;
+       unsigned int event_cnt;
+       int signal_cnt = 0;
+       int i;
+       unsigned int signal_type;
+       
+       e               = inp->pfp_events;
+       event_cnt       = inp->pfp_event_count;
+
+       for(i = 0; i < event_cnt; i++) {
+               signal_type = get_signal_type(cell_pe[e[i].event].pme_code);
+                       
+               switch(signal_cnt) {
+                       case 0:
+                               group0->signal_type = signal_type;
+                               group0->word_type = 
cell_pe[e[i].event].pme_enable_word;
+                               group0->freq = cell_pe[e[i].event].pme_freq;
+                               signal_cnt++;
+                               break;
+                               
+                       case 1:
+                               if (group0->signal_type != signal_type) {
+                                       group1->signal_type = signal_type;
+                                       group1->word_type = 
cell_pe[e[i].event].pme_enable_word;
+                                       group1->freq = 
cell_pe[e[i].event].pme_freq;
+                                       signal_cnt++;
+                                       
+                               }
+                               break;
+                               
+                       case 2:
+                               if ((group0->signal_type != signal_type)
+                                 && (group1->signal_type != signal_type)) {
+                                       DPRINT(("signal count is invalid\n"));
+                                       return PFMLIB_ERR_INVAL;
+                               }
+                               break;
+                               
+                       default:
+                               DPRINT(("signal count is invalid\n"));
+                               return PFMLIB_ERR_INVAL;
+               }
+       }
+       return signal_cnt;
+}
+
+static int
+pfm_cell_dispatch_counters(pfmlib_input_param_t *inp, 
pfmlib_cell_input_param_t *mod_in, pfmlib_output_param_t *outp)
+{
+       pfmlib_event_t *e;
+       pfmlib_reg_t *pc, *pd;
+       unsigned int event_cnt;
+       unsigned int signal_cnt = 0, pmcs_cnt = 0;
+       unsigned int signal_type;
+       unsigned long long signal_bit;
+       struct pfm_cell_signal_group_desc group[2];
+       int pmx_offset = 0;
+       int i, ret;
+       int input_control, polarity, count_cycle, count_enable;
+       unsigned long long subunit;
+       int shift0, shift1;
+       
+       count_enable = 1;
+       
+       group[0].signal_type = group[1].signal_type = NONE_SIGNAL;
+       group[0].word = group[1].word = 0L;
+       group[0].freq = group[1].freq = 0L;
+       group[0].word_type = group[1].word_type = WORD_NONE;
+
+       event_cnt = inp->pfp_event_count;
+       e = inp->pfp_events;
+       pc = outp->pfp_pmcs;
+       pd = outp->pfp_pmds;
+       
+       /* check event_cnt */
+       if ((event_cnt < PFM_CELL_EVENT_MIN) || (event_cnt > 
PFM_CELL_EVENT_MAX)) {
+               DPRINT(("event count is invalid\n"));
+               return PFMLIB_ERR_INVAL;
+       }
+
+       /* check signal type */
+       signal_cnt = check_signal_type(inp, &group[0], &group[1]);
+       if (signal_cnt == PFMLIB_ERR_INVAL) {
+               DPRINT(("signal type is invalid\n"));
+               return PFMLIB_ERR_INVAL;
+       }
+
+       /* decide debug_bus word */
+       if (signal_cnt != 0) {
+               ret = get_debug_bus_word(&group[0], &group[1]);
+               if (ret != PFMLIB_SUCCESS) {
+                       return ret;
+               }
+       }
+
+       /* common register setting */
+       pc[0].reg_num   = REG_GROUP_CONTROL;
+       if (signal_cnt == 1) {
+               pc[0].reg_value = group[0].word << 
PFM_CELL_GROUP_CONTROL_REG_GROUP0_BIT;
+       } else if (signal_cnt == 2) {
+               pc[0].reg_value = (group[0].word << 
PFM_CELL_GROUP_CONTROL_REG_GROUP0_BIT) |
+                               (group[1].word << 
PFM_CELL_GROUP_CONTROL_REG_GROUP1_BIT);
+       }
+       
+       pc[1].reg_num   = REG_DEBUG_BUS_CONTROL;
+       if (signal_cnt == 1) {
+               shift0 = PFM_CELL_BASE_WORD_UNIT_FIELD_BIT +
+                       ((PFM_CELL_MAX_WORD_NUMBER - group[0].word) * 
PFM_CELL_WORD_UNIT_FIELD_WIDTH);
+               pc[1].reg_value = group[0].freq << shift0;
+       } else if (signal_cnt == 2) {
+               shift0 = PFM_CELL_BASE_WORD_UNIT_FIELD_BIT +
+                       ((PFM_CELL_MAX_WORD_NUMBER - group[0].word) * 
PFM_CELL_WORD_UNIT_FIELD_WIDTH);
+               shift1 = PFM_CELL_BASE_WORD_UNIT_FIELD_BIT +
+                       ((PFM_CELL_MAX_WORD_NUMBER - group[1].word) * 
PFM_CELL_WORD_UNIT_FIELD_WIDTH);
+               pc[1].reg_value = (group[0].freq << shift0) | (group[1].freq << 
shift1);
+       }
+
+       pc[2].reg_num   = REG_TRACE_ADDRESS;
+       pc[2].reg_value = 0;
+       
+       pc[3].reg_num   = REG_EXT_TRACE_TIMER;
+       pc[3].reg_value = 0;
+       
+       pc[4].reg_num   = REG_PM_STATUS;
+       pc[4].reg_value = 0;
+       
+       pc[5].reg_num   = REG_PM_CONTROL;
+       pc[5].reg_value = PFM_CELL_DEFAULT_PM_CONTROL_REG_VALUE;
+       
+       pc[6].reg_num   = REG_PM_INTERVAL;
+       pc[6].reg_value = 0;
+       
+       pc[7].reg_num   = REG_PM_START_STOP;
+       pc[7].reg_value = mod_in->triggers;
+       
+       pmcs_cnt = COMMON_REG_NUMS;
+       
+       /* pmX register setting */
+       for(i = 0; i < event_cnt; i++) {
+               /* PMX_CONTROL */
+               pmx_offset = 
get_pmx_offset(mod_in->pfp_cell_counters[i].pmX_control_num);
+               if (pmx_offset == PFMLIB_ERR_INVAL) {
+                       DPRINT(("pmX already used\n"));
+                       return PFMLIB_ERR_INVAL;
+               }
+               
+               switch(cell_pe[e[i].event].pme_type) {
+                       case COUNT_TYPE_BOTH_TYPE:
+                       case COUNT_TYPE_CUMULATIVE_LEN:
+                       case COUNT_TYPE_MULTI_CYCLE:
+                       case COUNT_TYPE_SINGLE_CYCLE:
+                               count_cycle = 1;
+                               break;
+                               
+                       case COUNT_TYPE_OCCURRENCE:
+                               count_cycle = 0;
+                               break;
+                               
+                       default:
+                               return PFMLIB_ERR_INVAL;
+               }
+
+               signal_type = get_signal_type(cell_pe[e[i].event].pme_code);
+               signal_bit = get_signal_bit(cell_pe[e[i].event].pme_code);
+               polarity = mod_in->pfp_cell_counters[i].polarity;
+               input_control = mod_in->pfp_cell_counters[i].input_control;
+               if ((41 <= signal_type) && (signal_type <= 56)) {
+                       subunit = mod_in->pfp_cell_counters[i].spe_subunit;
+               } else {
+                       subunit = 0;
+               }
+               
+               pc[pmcs_cnt].reg_value  = ( (signal_bit << (31 - 5))
+                                         | (input_control << (31 - 6))
+                                         | (polarity << (31 - 7))
+                                         | (count_cycle << (31 - 8))
+                                         | (count_enable << (31 - 9)) );
+               pc[pmcs_cnt].reg_num    = REG_PM0_CONTROL + pmx_offset;
+
+               if (signal_type == group[1].signal_type) {
+                       pc[pmcs_cnt].reg_value |= 
PFM_CELL_COUNTER_CONTROL_GROUP1;
+               }
+
+               pmcs_cnt++;
+
+               /* PMX_EVENT */
+               pc[pmcs_cnt].reg_num    = REG_PM0_EVENT + pmx_offset;
+
+               /* debug bus word setting */
+               if (signal_type == group[0].signal_type) {
+                       pc[pmcs_cnt].reg_value  = (cell_pe[e[i].event].pme_code 
|
+                                                  (group[0].word << 48) | 
(subunit << 32));
+               } else if (signal_type == group[1].signal_type) {
+                       pc[pmcs_cnt].reg_value  = (cell_pe[e[i].event].pme_code 
|
+                                                  (group[1].word << 48) | 
(subunit << 32));
+               } else {
+                       return PFMLIB_ERR_INVAL;
+               }
+               pmcs_cnt++;
+       }
+       /* pmds setting */
+       for(i = 0; i < pmx_offset+1; i++) {
+               pd[i].reg_num = i;
+               pd[i].reg_value = 0;
+       }
+       
+       outp->pfp_pmc_count = pmcs_cnt;
+       outp->pfp_pmd_count = event_cnt;
+
+       return PFMLIB_SUCCESS;
+}
+
+static int
+pfm_cell_dispatch_events(pfmlib_input_param_t *inp, void *model_in, 
pfmlib_output_param_t *outp, void *model_out)
+{
+       pfmlib_cell_input_param_t *mod_in  = (pfmlib_cell_input_param_t 
*)model_in;
+
+       if (inp->pfp_dfl_plm & (PFM_PLM1|PFM_PLM2)) {
+               DPRINT(("invalid plm=%x\n", inp->pfp_dfl_plm));
+               return PFMLIB_ERR_INVAL;
+       }
+       return pfm_cell_dispatch_counters(inp, mod_in, outp);
+}
+
+static int
+pfm_cell_get_event_code(unsigned int i, unsigned int cnt, int *code)
+{
+       if (cnt != PFMLIB_CNT_FIRST && cnt > 2) {
+               return PFMLIB_ERR_INVAL;
+       }
+
+       *code = cell_pe[i].pme_code;
+
+       return PFMLIB_SUCCESS;
+}
+
+static void
+pfm_cell_get_event_counters(unsigned int j, pfmlib_regmask_t *counters)
+{
+       unsigned int i;
+
+       memset(counters, 0, sizeof(*counters));
+
+       for(i=0; i < PMU_CELL_NUM_COUNTERS; i++) {
+               pfm_regmask_set(counters, i);
+       }
+}
+
+static void
+pfm_cell_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
+{
+       unsigned int i;
+
+       memset(impl_pmcs, 0, sizeof(*impl_pmcs));
+
+       for(i=0; i < PFM_CELL_NUM_PMCS; i++) {
+               pfm_regmask_set(impl_pmcs, i);
+       }
+}
+
+static void
+pfm_cell_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
+{
+       unsigned int i;
+
+       memset(impl_pmds, 0, sizeof(*impl_pmds));
+
+       for(i=0; i < PMU_CELL_NUM_PERFCTR; i++) {
+               pfm_regmask_set(impl_pmds, i);
+       }
+}
+
+static void
+pfm_cell_get_impl_counters(pfmlib_regmask_t *impl_counters)
+{
+       unsigned int i;
+
+       for(i=0; i < PMU_CELL_NUM_COUNTERS; i++) {
+               pfm_regmask_set(impl_counters, i);
+       }
+}
+
+static char*
+pfm_cell_get_event_name(unsigned int i)
+{
+       return cell_pe[i].pme_name;
+}
+
+static int
+pfm_cell_get_event_desc(unsigned int ev, char **str)
+{
+       char *s;
+
+       s = cell_pe[ev].pme_desc;
+       if (s) {
+               *str = strdup(s);
+       } else {
+               *str = NULL;
+       }
+       return PFMLIB_SUCCESS;
+}
+
+static char*
+pfm_cell_get_event_mask_name(unsigned int ev, unsigned int midx)
+{
+       return "";
+}
+
+static int
+pfm_cell_get_event_mask_desc(unsigned int ev, unsigned int midx, char **str)
+{
+       *str = strdup("");
+       return PFMLIB_SUCCESS;
+}
+
+static unsigned int
+pfm_cell_get_num_event_masks(unsigned int ev)
+{
+       return 0;
+}
+
+static int
+pfm_cell_get_event_mask_code(unsigned int ev, unsigned int midx, unsigned int 
*code)
+{
+       *code = 0;
+       return PFMLIB_SUCCESS;
+}
+
+pfm_pmu_support_t cell_support={
+       .pmu_name               = "CELL",
+       .pmu_type               = PFMLIB_CELL_PMU,
+       .pme_count              = PME_CELL_EVENT_COUNT,
+       .pmc_count              = PFM_CELL_NUM_PMCS,
+       .pmd_count              = PMU_CELL_NUM_PERFCTR,
+       .num_cnt                = PMU_CELL_NUM_COUNTERS,
+       .get_event_code         = pfm_cell_get_event_code,
+       .get_event_name         = pfm_cell_get_event_name,
+       .get_event_counters     = pfm_cell_get_event_counters,
+       .dispatch_events        = pfm_cell_dispatch_events,
+       .pmu_detect             = pfm_cell_detect,
+       .get_impl_pmcs          = pfm_cell_get_impl_pmcs,
+       .get_impl_pmds          = pfm_cell_get_impl_pmds,
+       .get_impl_counters      = pfm_cell_get_impl_counters,
+       .get_event_desc         = pfm_cell_get_event_desc,
+       .get_num_event_masks    = pfm_cell_get_num_event_masks,
+       .get_event_mask_name    = pfm_cell_get_event_mask_name,
+       .get_event_mask_code    = pfm_cell_get_event_mask_code,
+       .get_event_mask_desc    = pfm_cell_get_event_mask_desc
+};
_______________________________________________
perfmon mailing list
[email protected]
http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/

Reply via email to