This patch adds support for Instruction Based Sampling (IBS) for AMD's
Barcelona CPUs (family 10h). IBS has been implemented as a model
specifific feature of the AMD64 PMU. Common code has been changed in
function pfm_dispatch_events(). Now it is possible to pass only model
specific input arguments, thus the parameter pfmlib_input_param_t *inp
in the function call can be NULL. This could make additional NULL
pointer checks necessary in other code sections.

Signed-off-by: Robert Richter <[EMAIL PROTECTED]>
---
 include/perfmon/pfmlib_amd64.h |  207 ++++++++++++++++++++++++++++++++--------
 lib/pfmlib_amd64.c             |  136 ++++++++++++++++++++++-----
 lib/pfmlib_amd64_priv.h        |   11 ++
 lib/pfmlib_common.c            |   30 ++++---
 4 files changed, 308 insertions(+), 76 deletions(-)

diff --git a/include/perfmon/pfmlib_amd64.h b/include/perfmon/pfmlib_amd64.h
index f50cb84..223790d 100644
--- a/include/perfmon/pfmlib_amd64.h
+++ b/include/perfmon/pfmlib_amd64.h
@@ -25,13 +25,14 @@
 #ifndef __PFMLIB_AMD64_H__
 #define __PFMLIB_AMD64_H__
 
-#include <perfmon/pfmlib.h>
+#include <stdint.h>
+
 /*
  * privilege level mask usage for AMD64:
  *
  * PFM_PLM0 = OS (kernel, hypervisor, ..)
- * PFM_PLM1 = unused (ignored)
- * PFM_PLM2 = unused (ignored)
+ * PFM_PLM1 = invalid parameters
+ * PFM_PLM2 = invalid parameters
  * PFM_PLM3 = USR (user level)
  */
 
@@ -39,51 +40,133 @@
 extern "C" {
 #endif
 
-#define PMU_AMD64_NUM_COUNTERS         4       /* total numbers of 
EvtSel/EvtCtr */
-#define PMU_AMD64_NUM_PERFSEL          4       /* total number of EvtSel 
defined */
-#define PMU_AMD64_NUM_PERFCTR          4       /* total number of EvtCtr 
defined */
-#define PMU_AMD64_COUNTER_WIDTH                48      /* hardware counter bit 
width   */
+#define PMU_AMD64_MAX_COUNTERS 4       /* total numbers of performance 
counters */
 
-#define PMU_AMD64_CNT_MASK_MAX         4       /* max cnt_mask value */
 /*
- * This structure provides a detailed way to setup a PMC register.
- * Once value is loaded, it must be copied (via pmu_reg) to the
- * perfmon_req_t and passed to the kernel via perfmonctl().
+ * AMD64 MSR definitions
  */
+
 typedef union {
-       unsigned long long val;                         /* complete register 
value */
+       uint64_t val;                           /* complete register value */
        struct {
-               unsigned long long sel_event_mask:8;            /* event mask */
-               unsigned long long sel_unit_mask:8;             /* unit mask */
-               unsigned long long sel_usr:1;           /* user level */
-               unsigned long long sel_os:1;                    /* system level 
*/
-               unsigned long long sel_edge:1;          /* edge detec */
-               unsigned long long sel_pc:1;                    /* pin control 
*/
-               unsigned long long sel_int:1;           /* enable APIC intr */
-               unsigned long long sel_res1:1;          /* reserved */
-               unsigned long long sel_en:1;                    /* enable */
-               unsigned long long sel_inv:1;           /* invert counter mask 
*/
-               unsigned long long sel_cnt_mask:8;              /* counter mask 
*/
-               unsigned long long sel_event_mask2:4;   /* 10h only: event mask 
[11:8] */
-               unsigned long long sel_res2:4;          /* reserved */
-               unsigned long long sel_guest:1;         /* 10h only: guest only 
counter */
-               unsigned long long sel_host:1;          /* 10h only: host only 
counter */
-               unsigned long long sel_res3:22;         /* reserved */
+               uint64_t sel_event_mask:8;      /* event mask */
+               uint64_t sel_unit_mask:8;       /* unit mask */
+               uint64_t sel_usr:1;             /* user level */
+               uint64_t sel_os:1;              /* system level */
+               uint64_t sel_edge:1;            /* edge detec */
+               uint64_t sel_pc:1;              /* pin control */
+               uint64_t sel_int:1;             /* enable APIC intr */
+               uint64_t sel_res1:1;            /* reserved */
+               uint64_t sel_en:1;              /* enable */
+               uint64_t sel_inv:1;             /* invert counter mask */
+               uint64_t sel_cnt_mask:8;        /* counter mask */
+               uint64_t sel_event_mask2:4;     /* 10h only: event mask [11:8] 
*/
+               uint64_t sel_res2:4;            /* reserved */
+               uint64_t sel_guest:1;           /* 10h only: guest only counter 
*/
+               uint64_t sel_host:1;            /* 10h only: host only counter 
*/
+               uint64_t sel_res3:22;           /* reserved */
        } perfsel;
-} pfm_amd64_sel_reg_t;
+} pfm_amd64_sel_reg_t; /* MSR 0xc001000-0xc001003 */
 
 typedef union {
-       unsigned long long val; /* counter value */
-       /* counting perfctr register */
+       uint64_t val;                           /* complete register value */
        struct {
-               unsigned long long ctr_count:48;        /* 48-bit hardware 
counter  */
-               unsigned long long ctr_res1:16;         /* reserved */
+               uint64_t ctr_count:48;          /* 48-bit hardware counter  */
+               uint64_t ctr_res1:16;           /* reserved */
        } perfctr;
-} pfm_amd64_ctr_reg_t;
+} pfm_amd64_ctr_reg_t; /* MSR 0xc001004-0xc001007 */
+
+typedef union {
+       uint64_t val;                           /* complete register value */
+       struct {
+               uint64_t ibsfetchmaxcnt:16;
+               uint64_t ibsfetchcnt:16;
+               uint64_t ibsfetchlat:16;
+               uint64_t ibsfetchen:1;
+               uint64_t ibsfetchval:1;
+               uint64_t ibsfetchcomp:1;
+               uint64_t ibsicmiss:1;
+               uint64_t ibsphyaddrvalid:1;
+               uint64_t ibsl1tlbpgsz:2;
+               uint64_t ibsl1tlbmiss:1;
+               uint64_t ibsl2tlbmiss:1;
+               uint64_t ibsranden:1;
+               uint64_t reserved:6;
+       } reg;
+} ibsfetchctl_t; /* MSR 0xc0011030 */
+
+typedef union {
+       uint64_t val;                           /* complete register value */
+       struct {
+               uint64_t ibsopmaxcnt:16;
+               uint64_t reserved1:1;
+               uint64_t ibsopen:1;
+               uint64_t ibsopval:1;
+               uint64_t reserved2:45;
+       } reg;
+} ibsopctl_t; /* MSR 0xc0011033 */
+
+typedef union {
+       uint64_t val;                           /* complete register value */
+       struct {
+               uint64_t ibscomptoretctr:16;
+               uint64_t ibstagtoretctr:16;
+               uint64_t ibsopbrnresync:1;
+               uint64_t ibsopmispreturn:1;
+               uint64_t ibsopreturn:1;
+               uint64_t ibsopbrntaken:1;
+               uint64_t ibsopbrnmisp:1;
+               uint64_t ibsopbrnret:1;
+               uint64_t reserved:26;
+       } reg;
+} ibsopdata_t; /* MSR 0xc0011035 */
+
+typedef union {
+       uint64_t val;                           /* complete register value */
+       struct {
+               uint64_t nbibsreqsrc:3;
+               uint64_t reserved1:1;
+               uint64_t nbibsreqdstproc:1;
+               uint64_t nbibsreqcachehitst:1;
+               uint64_t reserved2:58;
+       } reg;
+} ibsopdata2_t; /* MSR 0xc0011036 */
+
+typedef union {
+       uint64_t val;                           /* complete register value */
+       struct {
+               uint64_t ibsldop:1;
+               uint64_t ibsstop:1;
+               uint64_t ibsdcl1tlbmiss:1;
+               uint64_t ibsdcl2tlbmiss:1;
+               uint64_t ibsdcl1tlbhit2m:1;
+               uint64_t ibsdcl1tlbhit1g:1;
+               uint64_t ibsdcl2tlbhit2m:1;
+               uint64_t ibsdcmiss:1;
+               uint64_t ibsdcmissacc:1;
+               uint64_t ibsdcldbnkcon:1;
+               uint64_t ibsdcstbnkcon:1;
+               uint64_t ibsdcsttoldfwd:1;
+               uint64_t ibsdcsttoldcan:1;
+               uint64_t ibsdcucmemacc:1;
+               uint64_t ibsdcwcmemacc:1;
+               uint64_t ibsdclockedop:1;
+               uint64_t ibsdcmabhit:1;
+               uint64_t ibsdclinaddrvalid:1;
+               uint64_t ibsdcphyaddrvalid:1;
+               uint64_t reserved1:13;
+               uint64_t ibsdcmisslat:16;
+               uint64_t reserved2:16;
+       } reg;
+} ibsopdata3_t; /* MSR 0xc0011037 */
+
+/*
+ * AMD64 specific parameters for the library
+ */
 
 typedef struct {
-       unsigned int    cnt_mask;       /* threshold ([4-255] are reserved) */
-       unsigned int    flags;          /* counter specific flag */
+       uint32_t        cnt_mask;       /* threshold ([4-255] are reserved) */
+       uint32_t        flags;          /* counter specific flag */
 } pfmlib_amd64_counter_t;
 
 #define PFM_AMD64_SEL_INV      0x1     /* inverse */
@@ -92,17 +175,61 @@ typedef struct {
 #define PFM_AMD64_SEL_HOST     0x8     /* host only */
 
 /*
- * AMD64 specific parameters for the library
+ * AMD-specific input parameters
  */
+
+/*
+ * IBS input parameters
+ *
+ * Maxcnt specifies the maximum count value of the periodic counter,
+ * 20 bits, bits 3:0 are always set to zero.
+ */
+
 typedef struct {
-       pfmlib_amd64_counter_t  pfp_amd64_counters[PMU_AMD64_NUM_COUNTERS];     
/* extended counter features */
-       uint64_t                        reserved[4];            /* for future 
use */
+       unsigned int maxcnt;            /* 20 bits,  */
+       unsigned int options;
+} ibs_param_t;
+
+#define IBS_OPTIONS_RANDEN 1   /* enable randomization (IBS fetch only) */
+
+typedef struct {
+       pfmlib_amd64_counter_t pfp_amd64_counters[PMU_AMD64_MAX_COUNTERS]; /* 
extended counter features */
+       uint32_t        flags;          /* use flags */
+       uint32_t        reserved1;      /* for future use */
+               ibs_param_t     ibsfetch;       /* IBS fetch control */
+       ibs_param_t     ibsop;          /* IBS execution control */
+       uint64_t        reserved2;      /* for future use */
 } pfmlib_amd64_input_param_t;
 
+/* A bit mask, meaning multiple usage types may be defined */
+#define PFMLIB_AMD64_USE_IBSFETCH      1
+#define PFMLIB_AMD64_USE_IBSOP         2
+
+/*
+ * AMD-specific output parameters
+ *
+ * The values ibsfetch_base and ibsop_base pass back the index of the
+ * ibsopctl and ibsfetchctl register in pfp_pmds[].
+ */
+
 typedef struct {
-       uint64_t        reserved[8];            /* for future use */
+       uint32_t        ibsfetch_base;  /* Perfmon2 base register index */
+       uint32_t        ibsop_base;     /* Perfmon2 base register index */
+       uint64_t        reserved[7];    /* for future use */
 } pfmlib_amd64_output_param_t;
 
+/* Perfmon2 registers relative to base register */
+#define PMD_IBSFETCHCTL                0
+#define PMD_IBSFETCHLINAD      1
+#define PMD_IBSFETCHPHYSAD     2
+#define PMD_IBSOPCTL           0
+#define PMD_IBSOPRIP           1
+#define PMD_IBSOPDATA          2
+#define PMD_IBSOPDATA2         3
+#define PMD_IBSOPDATA3         4
+#define PMD_IBSDCLINAD         5
+#define PMD_IBSDCPHYSAD                6
+
 #ifdef __cplusplus /* extern C */
 }
 #endif
diff --git a/lib/pfmlib_amd64.c b/lib/pfmlib_amd64.c
index 2f56205..3cd5ffc 100644
--- a/lib/pfmlib_amd64.c
+++ b/lib/pfmlib_amd64.c
@@ -120,6 +120,7 @@ pfm_pmu_support_t amd64_support;
 #define amd64_events      amd64_pmu.events
 
 #define IS_FAMILY_10H() (amd64_pmu.revision >= AMD64_FAM10H)
+#define HAS_IBS() IS_FAMILY_10H()
 
 static amd64_rev_t
 amd64_get_revision(int family, int model, int stepping)
@@ -182,22 +183,27 @@ pfm_amd64_setup(int revision)
        amd64_pmu.revision = revision;
        snprintf(amd64_pmu.name, NAME_SIZE, "AMD64 (%s)",
                 amd64_cpu_strs[revision]);
+       amd64_support.pmu_name  = amd64_pmu.name;
+
+       /* defaults (K8) */
+       amd64_pmu.events        = amd64_k8_table.events;
+       amd64_support.pme_count = amd64_k8_table.num;
+       amd64_pmu.cpu_clks      = amd64_k8_table.cpu_clks;
+       amd64_pmu.ret_inst      = amd64_k8_table.ret_inst;
+       amd64_support.pmu_type  = PFMLIB_AMD64_PMU;
+       amd64_support.num_cnt   = PMU_AMD64_NUM_COUNTERS;
+       amd64_support.pmc_count = PMU_AMD64_NUM_COUNTERS;
+       amd64_support.pmd_count = PMU_AMD64_NUM_COUNTERS;
+
+       /* additional features */
        if (IS_FAMILY_10H()) {
                amd64_pmu.events = amd64_fam10h_table.events;
                amd64_support.pme_count = amd64_fam10h_table.num;
                amd64_pmu.cpu_clks = amd64_fam10h_table.cpu_clks;
                amd64_pmu.ret_inst = amd64_fam10h_table.ret_inst;
-       } else {
-               amd64_pmu.events = amd64_k8_table.events;
-               amd64_support.pme_count = amd64_k8_table.num;
-               amd64_pmu.cpu_clks = amd64_k8_table.cpu_clks;
-               amd64_pmu.ret_inst = amd64_k8_table.ret_inst;
+               amd64_support.pmc_count = PMU_AMD64_NUM_PERFSEL;
+               amd64_support.pmd_count = PMU_AMD64_NUM_PERFCTR;
        }
-       amd64_support.pmu_name          = amd64_pmu.name;
-       amd64_support.pmu_type          = PFMLIB_AMD64_PMU;
-       amd64_support.pmc_count         = PMU_AMD64_NUM_PERFSEL;
-       amd64_support.pmd_count         = PMU_AMD64_NUM_PERFCTR;
-       amd64_support.num_cnt           = PMU_AMD64_NUM_COUNTERS;
 }
 
 static int
@@ -286,7 +292,7 @@ pfm_amd64_dispatch_counters(pfmlib_input_param_t *inp, 
pfmlib_amd64_input_param_
        pfmlib_regmask_t *r_pmcs;
        unsigned long plm;
        unsigned int i, j, k, cnt, umask;
-       unsigned int assign[PMU_AMD64_NUM_COUNTERS];
+       unsigned int assign[PMU_AMD64_MAX_COUNTERS];
 
        e      = inp->pfp_events;
        pc     = outp->pfp_pmcs;
@@ -295,13 +301,19 @@ pfm_amd64_dispatch_counters(pfmlib_input_param_t *inp, 
pfmlib_amd64_input_param_
        r_pmcs = &inp->pfp_unavail_pmcs;
        cntrs  = param ? param->pfp_amd64_counters : NULL;
 
+       /* priviledge level 1 and 2 are not supported */
+       if (inp->pfp_dfl_plm & (PFM_PLM1|PFM_PLM2)) {
+               DPRINT(("invalid plm=%x\n", inp->pfp_dfl_plm));
+               return PFMLIB_ERR_INVAL;
+       }
+
        if (PFMLIB_DEBUG()) {
                for (j=0; j < cnt; j++) {
                        DPRINT(("ev[%d]=%s\n", j, 
pfm_amd64_get_event_entry(e[j].event)->pme_name));
                }
        }
 
-       if (cnt > PMU_AMD64_NUM_COUNTERS) return PFMLIB_ERR_TOOMANY;
+       if (cnt > amd64_support.num_cnt) return PFMLIB_ERR_TOOMANY;
 
        for(i=0, j=0; j < cnt; j++, i++) {
                /*
@@ -339,10 +351,10 @@ pfm_amd64_dispatch_counters(pfmlib_input_param_t *inp, 
pfmlib_amd64_input_param_
                /*
                 * exclude unavailable registers from assignment
                 */
-               while(i < PMU_AMD64_NUM_COUNTERS && pfm_regmask_isset(r_pmcs, 
i))
+               while(i < amd64_support.num_cnt && pfm_regmask_isset(r_pmcs, i))
                        i++;
 
-               if (i == PMU_AMD64_NUM_COUNTERS)
+               if (i == amd64_support.num_cnt)
                        return PFMLIB_ERR_NOASSIGN;
 
                assign[j] = i;
@@ -416,16 +428,92 @@ pfm_amd64_dispatch_counters(pfmlib_input_param_t *inp, 
pfmlib_amd64_input_param_
        return PFMLIB_SUCCESS;
 }
 
+static int pfm_amd64_dispatch_ibs(
+       pfmlib_input_param_t *inp, pfmlib_amd64_input_param_t *inp_mod,
+       pfmlib_output_param_t *outp,  pfmlib_amd64_output_param_t *outp_mod)
+{
+       unsigned int pmc_base, pmd_base;
+       ibsfetchctl_t ibsfetchctl;
+       ibsopctl_t ibsopctl;
+
+       if (!inp_mod || !outp || !outp_mod)
+               return PFMLIB_ERR_INVAL;
+
+       if (!HAS_IBS())
+               return PFMLIB_ERR_BADHOST;
+
+       /* IBS fetch profiling */
+       if (inp_mod->flags & PFMLIB_AMD64_USE_IBSFETCH) {
+               /* check availability of a PMC and PMD */
+               if (outp->pfp_pmc_count >= PFMLIB_MAX_PMCS)
+                       return PFMLIB_ERR_NOASSIGN;
+               if (outp->pfp_pmd_count >= PFMLIB_MAX_PMDS)
+                       return PFMLIB_ERR_NOASSIGN;
+               pmc_base = outp->pfp_pmc_count;
+               pmd_base = outp->pfp_pmd_count;
+               outp->pfp_pmcs[pmc_base].reg_num = PMU_AMD64_IBSFETCHCTL_PMC;
+               ibsfetchctl.val = 0;
+               ibsfetchctl.reg.ibsfetchen = 1;
+               ibsfetchctl.reg.ibsfetchmaxcnt = inp_mod->ibsfetch.maxcnt >> 4;
+               if (inp_mod->ibsfetch.options & IBS_OPTIONS_RANDEN)
+                       ibsfetchctl.reg.ibsranden = 1;
+               outp->pfp_pmcs[pmc_base].reg_value = ibsfetchctl.val;
+               outp->pfp_pmds[pmd_base].reg_num = PMU_AMD64_IBSFETCHCTL_PMD;
+               outp_mod->ibsfetch_base = pmd_base;
+               ++outp->pfp_pmc_count;
+               ++outp->pfp_pmd_count;
+       }
+
+       /* IBS execution profiling */
+       if (inp_mod->flags & PFMLIB_AMD64_USE_IBSOP) {
+               /* check availability of a PMC and PMD */
+               if (outp->pfp_pmc_count >= PFMLIB_MAX_PMCS)
+                       return PFMLIB_ERR_NOASSIGN;
+               if (outp->pfp_pmd_count >= PFMLIB_MAX_PMDS)
+                       return PFMLIB_ERR_NOASSIGN;
+               pmc_base = outp->pfp_pmc_count;
+               pmd_base = outp->pfp_pmd_count;
+               outp->pfp_pmcs[pmc_base].reg_num = PMU_AMD64_IBSOPCTL_PMC;
+               ibsopctl.val = 0;
+               ibsopctl.reg.ibsopen = 1;
+               ibsopctl.reg.ibsopmaxcnt = inp_mod->ibsop.maxcnt >> 4;
+               outp->pfp_pmcs[pmc_base].reg_value = ibsopctl.val;
+               outp->pfp_pmds[pmd_base].reg_num = PMU_AMD64_IBSOPCTL_PMD;
+               outp_mod->ibsop_base = pmd_base;
+               ++outp->pfp_pmc_count;
+               ++outp->pfp_pmd_count;
+       }
+
+       return PFMLIB_SUCCESS;
+}
+
 static int
-pfm_amd64_dispatch_events(pfmlib_input_param_t *inp, void *model_in, 
pfmlib_output_param_t *outp, void *model_out)
+pfm_amd64_dispatch_events(
+       pfmlib_input_param_t *inp, void *_inp_mod,
+       pfmlib_output_param_t *outp, void *outp_mod)
 {
-       pfmlib_amd64_input_param_t *mod_in  = (pfmlib_amd64_input_param_t 
*)model_in;
+       pfmlib_amd64_input_param_t *inp_mod = _inp_mod;
+       int ret = PFMLIB_ERR_INVAL;
 
-       if (inp->pfp_dfl_plm & (PFM_PLM1|PFM_PLM2)) {
-               DPRINT(("invalid plm=%x\n", inp->pfp_dfl_plm));
+       if (!outp)
                return PFMLIB_ERR_INVAL;
+
+       /*
+        * At least one of the dispatch function calls must return
+        * PFMLIB_SUCCESS
+        */
+
+       if (inp && inp->pfp_event_count) {
+               ret = pfm_amd64_dispatch_counters(inp, inp_mod, outp);
+               if (ret != PFMLIB_SUCCESS)
+                       return ret;
        }
-       return pfm_amd64_dispatch_counters(inp, mod_in, outp);
+
+       if (inp_mod && inp_mod->flags & (PFMLIB_AMD64_USE_IBSOP
+                                        | PFMLIB_AMD64_USE_IBSFETCH))
+               ret = pfm_amd64_dispatch_ibs(inp, inp_mod, outp, outp_mod);
+
+       return ret;
 }
 
 static int
@@ -457,7 +545,7 @@ pfm_amd64_get_event_counters(unsigned int j, 
pfmlib_regmask_t *counters)
 
        memset(counters, 0, sizeof(*counters));
 
-       for(i=0; i < PMU_AMD64_NUM_COUNTERS; i++)
+       for(i=0; i < amd64_support.num_cnt; i++)
                pfm_regmask_set(counters, i);
 }
 
@@ -467,7 +555,7 @@ pfm_amd64_get_impl_perfsel(pfmlib_regmask_t *impl_pmcs)
        unsigned int i = 0;
 
        /* all pmcs are contiguous */
-       for(i=0; i < PMU_AMD64_NUM_PERFSEL; i++)
+       for(i=0; i < amd64_support.pmc_count; i++)
                pfm_regmask_set(impl_pmcs, i);
 }
 
@@ -477,7 +565,7 @@ pfm_amd64_get_impl_perfctr(pfmlib_regmask_t *impl_pmds)
        unsigned int i = 0;
 
        /* all pmds are contiguous */
-       for(i=0; i < PMU_AMD64_NUM_PERFCTR; i++)
+       for(i=0; i < amd64_support.pmd_count; i++)
                pfm_regmask_set(impl_pmds, i);
 }
 
@@ -568,8 +656,8 @@ pfm_pmu_support_t amd64_support = {
        .pmu_name               = "AMD64",
        .pmu_type               = PFMLIB_AMD64_PMU,
        .pme_count              = 0,
-       .pmc_count              = PMU_AMD64_NUM_PERFSEL,
-       .pmd_count              = PMU_AMD64_NUM_PERFCTR,
+       .pmc_count              = PMU_AMD64_NUM_COUNTERS,
+       .pmd_count              = PMU_AMD64_NUM_COUNTERS,
        .num_cnt                = PMU_AMD64_NUM_COUNTERS,
        .get_event_code         = pfm_amd64_get_event_code,
        .get_event_name         = pfm_amd64_get_event_name,
diff --git a/lib/pfmlib_amd64_priv.h b/lib/pfmlib_amd64_priv.h
index 551f8bb..f5e49f4 100644
--- a/lib/pfmlib_amd64_priv.h
+++ b/lib/pfmlib_amd64_priv.h
@@ -25,6 +25,17 @@
 #ifndef __PFMLIB_AMD64_PRIV_H__
 #define __PFMLIB_AMD64_PRIV_H__
 
+/* PERFSEL/PERFCTR include IBS registers of family 10h */
+#define PMU_AMD64_NUM_PERFSEL  6       /* total number of PMCs defined */
+#define PMU_AMD64_NUM_PERFCTR  14      /* total number of PMDs defined */
+#define PMU_AMD64_NUM_COUNTERS 4       /* total numbers of EvtSel/EvtCtr */
+#define PMU_AMD64_COUNTER_WIDTH        48      /* hardware counter bit width */
+#define PMU_AMD64_CNT_MASK_MAX 4       /* max cnt_mask value */
+#define PMU_AMD64_IBSFETCHCTL_PMC 4    /* IBS: fetch PMC base */
+#define PMU_AMD64_IBSFETCHCTL_PMD 4    /* IBS: fetch PMD base */
+#define PMU_AMD64_IBSOPCTL_PMC 5       /* IBS: op PMC base */
+#define PMU_AMD64_IBSOPCTL_PMD 7       /* IBS: op PMD base */
+
 #define PFMLIB_AMD64_MAX_UMASK 9
 
 typedef struct {
diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c
index 42e3561..8c0824e 100644
--- a/lib/pfmlib_common.c
+++ b/lib/pfmlib_common.c
@@ -633,7 +633,9 @@ pfm_check_unavail_pmcs(pfmlib_regmask_t *pmcs)
  * registers. In other words, invalid registers are ignored
  */
 int
-pfm_dispatch_events(pfmlib_input_param_t *inp, void *model_in, 
pfmlib_output_param_t *outp, void *model_out)
+pfm_dispatch_events(
+       pfmlib_input_param_t *inp, void *model_in,
+       pfmlib_output_param_t *outp, void *model_out)
 {
        unsigned count;
        unsigned int i;
@@ -642,21 +644,23 @@ pfm_dispatch_events(pfmlib_input_param_t *inp, void 
*model_in, pfmlib_output_par
        if (PFMLIB_INITIALIZED() == 0)
                return PFMLIB_ERR_NOINIT;
 
-       if (inp == NULL || outp == NULL)
+       /* at least one input and one output set must exist */
+       if (!inp && !model_in)
                return PFMLIB_ERR_INVAL;
-
-       /*
-        * the default priv level must be set to something
-        */
-       if (inp->pfp_dfl_plm == 0)
+       if (!outp && !model_out)
                return PFMLIB_ERR_INVAL;
 
-       if (inp->pfp_event_count >= PFMLIB_MAX_PMCS)
+       if (!inp)
+               count = 0;
+       else if (inp->pfp_dfl_plm == 0)
+               /* the default priv level must be set to something */
                return PFMLIB_ERR_INVAL;
-
-       count = inp->pfp_event_count;
-       if (count > pfm_current->num_cnt)
+       else if (inp->pfp_event_count >= PFMLIB_MAX_PMCS)
+               return PFMLIB_ERR_INVAL;
+       else if (inp->pfp_event_count > pfm_current->num_cnt)
                return PFMLIB_ERR_NOASSIGN;
+       else
+               count = inp->pfp_event_count;
 
        /*
         * check that event and unit masks descriptors are correct
@@ -666,8 +670,10 @@ pfm_dispatch_events(pfmlib_input_param_t *inp, void 
*model_in, pfmlib_output_par
                if (ret != PFMLIB_SUCCESS)
                        return ret;
        }
+
        /* reset output data structure */
-       memset(outp, 0, sizeof(*outp));
+       if (outp)
+               memset(outp, 0, sizeof(*outp));
 
        return pfm_current->dispatch_events(inp, model_in, outp, model_out);
 }
-- 
1.5.3.7



-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
perfmon2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel

Reply via email to