Author: br
Date: Wed Sep 18 16:13:50 2019
New Revision: 352487
URL: https://svnweb.freebsd.org/changeset/base/352487

Log:
  Add support for BERI statcounters.
  
  BERI stands for Bluespec Extensible RISC Implementation, based on MIPS.
  
  BERI has not implemented standard MIPS perfomance monitoring counters,
  instead it provides statistical counters.
  
  BERI statcounters have a several limitations:
  - They can't be written
  - They don't support start/stop operation
  - None of hardware interrupt is provided on a counter overflow.
  
  So make it separate to hwpmc_mips module and support process/system
  counting mode only.
  
  Sponsored by: DARPA, AFRL

Added:
  head/sys/dev/hwpmc/hwpmc_beri.c   (contents, props changed)
  head/sys/dev/hwpmc/hwpmc_beri.h   (contents, props changed)
Modified:
  head/lib/libpmc/libpmc.c
  head/sys/conf/files.mips
  head/sys/dev/hwpmc/pmc_events.h
  head/sys/sys/pmc.h

Modified: head/lib/libpmc/libpmc.c
==============================================================================
--- head/lib/libpmc/libpmc.c    Wed Sep 18 16:13:10 2019        (r352486)
+++ head/lib/libpmc/libpmc.c    Wed Sep 18 16:13:50 2019        (r352487)
@@ -143,6 +143,7 @@ PMC_CLASSDEP_TABLE(k8, K8);
 PMC_CLASSDEP_TABLE(xscale, XSCALE);
 PMC_CLASSDEP_TABLE(armv7, ARMV7);
 PMC_CLASSDEP_TABLE(armv8, ARMV8);
+PMC_CLASSDEP_TABLE(beri, BERI);
 PMC_CLASSDEP_TABLE(mips24k, MIPS24K);
 PMC_CLASSDEP_TABLE(mips74k, MIPS74K);
 PMC_CLASSDEP_TABLE(octeon, OCTEON);
@@ -187,6 +188,7 @@ static const struct pmc_event_descr cortex_a57_event_t
 
 PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC);
 PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE);
+PMC_MDEP_TABLE(beri, BERI, PMC_CLASS_SOFT, PMC_CLASS_BERI);
 PMC_MDEP_TABLE(cortex_a8, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7);
 PMC_MDEP_TABLE(cortex_a9, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7);
 PMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8);
@@ -235,6 +237,7 @@ PMC_CLASS_TABLE_DESC(cortex_a53, ARMV8, cortex_a53, ar
 PMC_CLASS_TABLE_DESC(cortex_a57, ARMV8, cortex_a57, arm64);
 #endif
 #if defined(__mips__)
+PMC_CLASS_TABLE_DESC(beri, BERI, beri, mips);
 PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips);
 PMC_CLASS_TABLE_DESC(mips74k, MIPS74K, mips74k, mips);
 PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips);
@@ -829,6 +832,11 @@ arm64_allocate_pmc(enum pmc_event pe, char *ctrspec __
 
 #if defined(__mips__)
 
+static struct pmc_event_alias beri_aliases[] = {
+       EV_ALIAS("instructions",        "INST"),
+       EV_ALIAS(NULL, NULL)
+};
+
 static struct pmc_event_alias mips24k_aliases[] = {
        EV_ALIAS("instructions",        "INSTR_EXECUTED"),
        EV_ALIAS("branches",            "BRANCH_COMPLETED"),
@@ -1267,6 +1275,10 @@ pmc_event_names_of_class(enum pmc_class cl, const char
                        break;
                }
                break;
+       case PMC_CLASS_BERI:
+               ev = beri_event_table;
+               count = PMC_EVENT_TABLE_SIZE(beri);
+               break;
        case PMC_CLASS_MIPS24K:
                ev = mips24k_event_table;
                count = PMC_EVENT_TABLE_SIZE(mips24k);
@@ -1508,6 +1520,10 @@ pmc_init(void)
                break;
 #endif
 #if defined(__mips__)
+       case PMC_CPU_MIPS_BERI:
+               PMC_MDEP_INIT(beri);
+               pmc_class_table[n] = &beri_class_table_descr;
+               break;
        case PMC_CPU_MIPS_24K:
                PMC_MDEP_INIT(mips24k);
                pmc_class_table[n] = &mips24k_class_table_descr;
@@ -1645,6 +1661,9 @@ _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype
                default:        /* Unknown CPU type. */
                        break;
                }
+       } else if (pe >= PMC_EV_BERI_FIRST && pe <= PMC_EV_BERI_LAST) {
+               ev = beri_event_table;
+               evfence = beri_event_table + PMC_EVENT_TABLE_SIZE(beri);
        } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) {
                ev = mips24k_event_table;
                evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k);

Modified: head/sys/conf/files.mips
==============================================================================
--- head/sys/conf/files.mips    Wed Sep 18 16:13:10 2019        (r352486)
+++ head/sys/conf/files.mips    Wed Sep 18 16:13:50 2019        (r352487)
@@ -91,7 +91,9 @@ dev/nvram2env/nvram2env_mips.c                optional        
nvram2env
 dev/nvram2env/nvram2env.c              optional        nvram2env
 
 # hwpmc support
-dev/hwpmc/hwpmc_mips.c                 optional        hwpmc
+dev/hwpmc/hwpmc_beri.c                 optional        hwpmc_beri
+dev/hwpmc/hwpmc_mips.c                 optional        hwpmc_mips24k | \
+       hwpmc_mips74k
 dev/hwpmc/hwpmc_mips24k.c              optional        hwpmc_mips24k
 dev/hwpmc/hwpmc_mips74k.c              optional        hwpmc_mips74k
 

Added: head/sys/dev/hwpmc/hwpmc_beri.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/hwpmc/hwpmc_beri.c     Wed Sep 18 16:13:50 2019        
(r352487)
@@ -0,0 +1,540 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Ruslan Bukin <b...@bsdpad.com>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_hwpmc_hooks.h"
+
+#include <sys/param.h>
+#include <sys/pmckern.h>
+
+#include <dev/hwpmc/hwpmc_beri.h>
+
+#define        BERI_NCOUNTERS  56
+#define        BERI_PMC_CAPS   (PMC_CAP_USER | PMC_CAP_SYSTEM | \
+                        PMC_CAP_READ | PMC_CAP_WRITE )
+
+struct beri_event_code_map {
+       uint32_t        pe_ev;       /* enum value */
+       uint64_t        (*get_func)(void);
+};
+
+const struct beri_event_code_map beri_event_codes[BERI_NCOUNTERS] = {
+       { PMC_EV_BERI_CYCLE,
+               statcounters_get_cycle_count },
+       { PMC_EV_BERI_INST,
+               statcounters_get_inst_count },
+       { PMC_EV_BERI_INST_USER,
+               statcounters_get_inst_user_count },
+       { PMC_EV_BERI_INST_KERNEL,
+               statcounters_get_inst_kernel_count },
+       { PMC_EV_BERI_IMPRECISE_SETBOUNDS,
+               statcounters_get_imprecise_setbounds_count },
+       { PMC_EV_BERI_UNREPRESENTABLE_CAPS,
+               statcounters_get_unrepresentable_caps_count },
+       { PMC_EV_BERI_ITLB_MISS,
+               statcounters_get_itlb_miss_count },
+       { PMC_EV_BERI_DTLB_MISS,
+               statcounters_get_dtlb_miss_count },
+       { PMC_EV_BERI_ICACHE_WRITE_HIT,
+               statcounters_get_icache_write_hit_count },
+       { PMC_EV_BERI_ICACHE_WRITE_MISS,
+               statcounters_get_icache_write_miss_count },
+       { PMC_EV_BERI_ICACHE_READ_HIT,
+               statcounters_get_icache_read_hit_count },
+       { PMC_EV_BERI_ICACHE_READ_MISS,
+               statcounters_get_icache_read_miss_count },
+       { PMC_EV_BERI_ICACHE_EVICT,
+               statcounters_get_icache_evict_count },
+       { PMC_EV_BERI_DCACHE_WRITE_HIT,
+               statcounters_get_dcache_write_hit_count },
+       { PMC_EV_BERI_DCACHE_WRITE_MISS,
+               statcounters_get_dcache_write_miss_count },
+       { PMC_EV_BERI_DCACHE_READ_HIT,
+               statcounters_get_dcache_read_hit_count },
+       { PMC_EV_BERI_DCACHE_READ_MISS,
+               statcounters_get_dcache_read_miss_count },
+       { PMC_EV_BERI_DCACHE_EVICT,
+               statcounters_get_dcache_evict_count },
+       { PMC_EV_BERI_DCACHE_SET_TAG_WRITE,
+               statcounters_get_dcache_set_tag_write_count },
+       { PMC_EV_BERI_DCACHE_SET_TAG_READ,
+               statcounters_get_dcache_set_tag_read_count },
+       { PMC_EV_BERI_L2CACHE_WRITE_HIT,
+               statcounters_get_l2cache_write_hit_count },
+       { PMC_EV_BERI_L2CACHE_WRITE_MISS,
+               statcounters_get_l2cache_write_miss_count },
+       { PMC_EV_BERI_L2CACHE_READ_HIT,
+               statcounters_get_l2cache_read_hit_count },
+       { PMC_EV_BERI_L2CACHE_READ_MISS,
+               statcounters_get_l2cache_read_miss_count },
+       { PMC_EV_BERI_L2CACHE_EVICT,
+               statcounters_get_l2cache_evict_count },
+       { PMC_EV_BERI_L2CACHE_SET_TAG_WRITE,
+               statcounters_get_l2cache_set_tag_write_count },
+       { PMC_EV_BERI_L2CACHE_SET_TAG_READ,
+               statcounters_get_l2cache_set_tag_read_count },
+       { PMC_EV_BERI_MEM_BYTE_READ,
+               statcounters_get_mem_byte_read_count },
+       { PMC_EV_BERI_MEM_BYTE_WRITE,
+               statcounters_get_mem_byte_write_count },
+       { PMC_EV_BERI_MEM_HWORD_READ,
+               statcounters_get_mem_hword_read_count },
+       { PMC_EV_BERI_MEM_HWORD_WRITE,
+               statcounters_get_mem_hword_write_count },
+       { PMC_EV_BERI_MEM_WORD_READ,
+               statcounters_get_mem_word_read_count },
+       { PMC_EV_BERI_MEM_WORD_WRITE,
+               statcounters_get_mem_word_write_count },
+       { PMC_EV_BERI_MEM_DWORD_READ,
+               statcounters_get_mem_dword_read_count },
+       { PMC_EV_BERI_MEM_DWORD_WRITE,
+               statcounters_get_mem_dword_write_count },
+       { PMC_EV_BERI_MEM_CAP_READ,
+               statcounters_get_mem_cap_read_count },
+       { PMC_EV_BERI_MEM_CAP_WRITE,
+               statcounters_get_mem_cap_write_count },
+       { PMC_EV_BERI_MEM_CAP_READ_TAG_SET,
+               statcounters_get_mem_cap_read_tag_set_count },
+       { PMC_EV_BERI_MEM_CAP_WRITE_TAG_SET,
+               statcounters_get_mem_cap_write_tag_set_count },
+       { PMC_EV_BERI_TAGCACHE_WRITE_HIT,
+               statcounters_get_tagcache_write_hit_count },
+       { PMC_EV_BERI_TAGCACHE_WRITE_MISS,
+               statcounters_get_tagcache_write_miss_count },
+       { PMC_EV_BERI_TAGCACHE_READ_HIT,
+               statcounters_get_tagcache_read_hit_count },
+       { PMC_EV_BERI_TAGCACHE_READ_MISS,
+               statcounters_get_tagcache_read_miss_count },
+       { PMC_EV_BERI_TAGCACHE_EVICT,
+               statcounters_get_tagcache_evict_count },
+       { PMC_EV_BERI_L2CACHEMASTER_READ_REQ,
+               statcounters_get_l2cachemaster_read_req_count },
+       { PMC_EV_BERI_L2CACHEMASTER_WRITE_REQ,
+               statcounters_get_l2cachemaster_write_req_count },
+       { PMC_EV_BERI_L2CACHEMASTER_WRITE_REQ_FLIT,
+               statcounters_get_l2cachemaster_write_req_flit_count },
+       { PMC_EV_BERI_L2CACHEMASTER_READ_RSP,
+               statcounters_get_l2cachemaster_read_rsp_count },
+       { PMC_EV_BERI_L2CACHEMASTER_READ_RSP_FLIT,
+               statcounters_get_l2cachemaster_read_rsp_flit_count },
+       { PMC_EV_BERI_L2CACHEMASTER_WRITE_RSP,
+               statcounters_get_l2cachemaster_write_rsp_count },
+       { PMC_EV_BERI_TAGCACHEMASTER_READ_REQ,
+               statcounters_get_tagcachemaster_read_req_count },
+       { PMC_EV_BERI_TAGCACHEMASTER_WRITE_REQ,
+               statcounters_get_tagcachemaster_write_req_count },
+       { PMC_EV_BERI_TAGCACHEMASTER_WRITE_REQ_FLIT,
+               statcounters_get_tagcachemaster_write_req_flit_count },
+       { PMC_EV_BERI_TAGCACHEMASTER_READ_RSP,
+               statcounters_get_tagcachemaster_read_rsp_count },
+       { PMC_EV_BERI_TAGCACHEMASTER_READ_RSP_FLIT,
+               statcounters_get_tagcachemaster_read_rsp_flit_count },
+       { PMC_EV_BERI_TAGCACHEMASTER_WRITE_RSP,
+               statcounters_get_tagcachemaster_write_rsp_count },
+};
+
+struct mips_pmc_spec beri_pmc_spec = {
+       .ps_cpuclass = PMC_CLASS_BERI,
+       .ps_cputype = PMC_CPU_MIPS_BERI,
+       .ps_capabilities = BERI_PMC_CAPS,
+       .ps_counter_width = 64
+};
+
+/*
+ * Per-processor information.
+ */
+struct beri_cpu {
+       struct pmc_hw   *pc_beripmcs;
+       uint64_t        start_values[BERI_NCOUNTERS];
+       uint64_t        stop_values[BERI_NCOUNTERS];
+       uint64_t        saved_values[BERI_NCOUNTERS];
+};
+
+int beri_npmcs;
+static struct beri_cpu **beri_pcpu;
+
+static int
+beri_allocate_pmc(int cpu, int ri, struct pmc *pm,
+  const struct pmc_op_pmcallocate *a)
+{
+       uint32_t config;
+       int i;
+
+       KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+           ("[beri,%d] illegal CPU value %d", __LINE__, cpu));
+       KASSERT(ri >= 0 && ri < beri_npmcs,
+           ("[beri,%d] illegal row index %d", __LINE__, ri));
+
+       if (a->pm_class != beri_pmc_spec.ps_cpuclass)
+               return (EINVAL);
+
+       for (i = 0; i < BERI_NCOUNTERS; i++) {
+               if (beri_event_codes[i].pe_ev == a->pm_ev) {
+                       config = i;
+                       break;
+               }
+       }
+
+       if (i == BERI_NCOUNTERS)
+               return (EINVAL);
+
+       pm->pm_md.pm_mips_evsel = config;
+
+       PMCDBG2(MDP,ALL,2,"beri-allocate ri=%d -> config=0x%x", ri, config);
+
+       return (0);
+}
+
+static int
+beri_read_pmc(int cpu, int ri, pmc_value_t *v)
+{
+       uint32_t config;
+       struct pmc *pm;
+       pmc_value_t new;
+       pmc_value_t start_val;
+       pmc_value_t stop_val;
+       pmc_value_t saved_val;
+       pmc_value_t result;
+
+       KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+           ("[beri,%d] illegal CPU value %d", __LINE__, cpu));
+       KASSERT(ri >= 0 && ri < beri_npmcs,
+           ("[beri,%d] illegal row index %d", __LINE__, ri));
+
+       pm = beri_pcpu[cpu]->pc_beripmcs[ri].phw_pmc;
+       config = pm->pm_md.pm_mips_evsel;
+
+       start_val = beri_pcpu[cpu]->start_values[config];
+       if (PMC_IS_SYSTEM_MODE(PMC_TO_MODE(pm))) {
+               stop_val = beri_event_codes[config].get_func();
+       } else
+               stop_val = beri_pcpu[cpu]->stop_values[config];
+
+       if (start_val <= stop_val)
+               result = stop_val - start_val;
+       else {
+               if (config == 0) /* CYCLE counter is 48 bit */
+                       result = 0x00ffffffffffffffUL;
+               else
+                       result = 0xffffffffffffffffUL;
+               result -= start_val;
+               result += stop_val;
+       }
+
+       saved_val = beri_pcpu[cpu]->saved_values[config];
+
+       *v = result + saved_val;
+
+       return (0);
+}
+
+static int
+beri_write_pmc(int cpu, int ri, pmc_value_t v)
+{
+       struct pmc *pm;
+       uint32_t config;
+
+       KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+           ("[beri,%d] illegal CPU value %d", __LINE__, cpu));
+       KASSERT(ri >= 0 && ri < beri_npmcs,
+           ("[beri,%d] illegal row-index %d", __LINE__, ri));
+
+       pm = beri_pcpu[cpu]->pc_beripmcs[ri].phw_pmc;
+       config = pm->pm_md.pm_mips_evsel;
+
+       if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+               v = (1UL << (beri_pmc_spec.ps_counter_width - 1)) - v;
+       
+       PMCDBG3(MDP,WRI,1,"beri-write cpu=%d ri=%d v=%jx", cpu, ri, v);
+
+       if (PMC_IS_SYSTEM_MODE(PMC_TO_MODE(pm)))
+               beri_pcpu[cpu]->saved_values[config] = 0;
+       else
+               beri_pcpu[cpu]->saved_values[config] = v;
+
+       return (0);
+}
+
+static int
+beri_config_pmc(int cpu, int ri, struct pmc *pm)
+{
+       struct pmc_hw *phw;
+
+       PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
+
+       KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+           ("[beri,%d] illegal CPU value %d", __LINE__, cpu));
+       KASSERT(ri >= 0 && ri < beri_npmcs,
+           ("[beri,%d] illegal row-index %d", __LINE__, ri));
+
+       phw = &beri_pcpu[cpu]->pc_beripmcs[ri];
+
+       KASSERT(pm == NULL || phw->phw_pmc == NULL,
+           ("[beri,%d] pm=%p phw->pm=%p hwpmc not unconfigured",
+           __LINE__, pm, phw->phw_pmc));
+
+       phw->phw_pmc = pm;
+
+       return (0);
+}
+
+static int
+beri_start_pmc(int cpu, int ri)
+{
+       uint32_t config;
+        struct pmc *pm;
+        struct pmc_hw *phw;
+       pmc_value_t v;
+
+       phw = &beri_pcpu[cpu]->pc_beripmcs[ri];
+       pm = phw->phw_pmc;
+       config = pm->pm_md.pm_mips_evsel;
+
+       v = beri_event_codes[config].get_func();
+       beri_pcpu[cpu]->start_values[config] = v;
+
+       return (0);
+}
+
+static int
+beri_stop_pmc(int cpu, int ri)
+{
+       uint32_t config;
+        struct pmc *pm;
+        struct pmc_hw *phw;
+       pmc_value_t v;
+
+       phw = &beri_pcpu[cpu]->pc_beripmcs[ri];
+       pm = phw->phw_pmc;
+       config = pm->pm_md.pm_mips_evsel;
+
+       v = beri_event_codes[config].get_func();
+       beri_pcpu[cpu]->stop_values[config] = v;
+
+       return (0);
+}
+
+static int
+beri_release_pmc(int cpu, int ri, struct pmc *pmc)
+{
+       struct pmc_hw *phw;
+
+       KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+           ("[beri,%d] illegal CPU value %d", __LINE__, cpu));
+       KASSERT(ri >= 0 && ri < beri_npmcs,
+           ("[beri,%d] illegal row-index %d", __LINE__, ri));
+
+       phw = &beri_pcpu[cpu]->pc_beripmcs[ri];
+       KASSERT(phw->phw_pmc == NULL,
+           ("[beri,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
+
+       return (0);
+}
+
+static int
+beri_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
+{
+       struct pmc_hw *phw;
+       char beri_name[PMC_NAME_MAX];
+       int error;
+
+       KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+           ("[beri,%d], illegal CPU %d", __LINE__, cpu));
+       KASSERT(ri >= 0 && ri < beri_npmcs,
+           ("[beri,%d] row-index %d out of range", __LINE__, ri));
+
+       phw = &beri_pcpu[cpu]->pc_beripmcs[ri];
+       snprintf(beri_name, sizeof(beri_name), "MIPS-%d", ri);
+       if ((error = copystr(beri_name, pi->pm_name, PMC_NAME_MAX,
+           NULL)) != 0)
+               return error;
+       pi->pm_class = beri_pmc_spec.ps_cpuclass;
+       if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
+               pi->pm_enabled = TRUE;
+               *ppmc = phw->phw_pmc;
+       } else {
+               pi->pm_enabled = FALSE;
+               *ppmc = NULL;
+       }
+
+       return (0);
+}
+
+static int
+beri_get_config(int cpu, int ri, struct pmc **ppm)
+{
+
+       *ppm = beri_pcpu[cpu]->pc_beripmcs[ri].phw_pmc;
+
+       return (0);
+}
+
+static int
+beri_pmc_switch_in(struct pmc_cpu *pc, struct pmc_process *pp)
+{
+
+       return (0);
+}
+
+static int
+beri_pmc_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
+{
+
+       return (0);
+}
+
+static int
+beri_pcpu_init(struct pmc_mdep *md, int cpu)
+{
+       int first_ri, i;
+       struct pmc_cpu *pc;
+       struct beri_cpu *pac;
+       struct pmc_hw  *phw;
+
+       KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+           ("[beri,%d] wrong cpu number %d", __LINE__, cpu));
+       PMCDBG1(MDP,INI,1,"beri-init cpu=%d", cpu);
+
+       beri_pcpu[cpu] = pac = malloc(sizeof(struct beri_cpu), M_PMC,
+           M_WAITOK|M_ZERO);
+       pac->pc_beripmcs = malloc(sizeof(struct pmc_hw) * beri_npmcs,
+           M_PMC, M_WAITOK|M_ZERO);
+       pc = pmc_pcpu[cpu];
+       first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_MIPS].pcd_ri;
+       KASSERT(pc != NULL, ("[beri,%d] NULL per-cpu pointer", __LINE__));
+
+       for (i = 0, phw = pac->pc_beripmcs; i < beri_npmcs; i++, phw++) {
+               phw->phw_state = PMC_PHW_FLAG_IS_ENABLED |
+                   PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i);
+               phw->phw_pmc = NULL;
+               pc->pc_hwpmcs[i + first_ri] = phw;
+       }
+
+       return (0);
+}
+
+static int
+beri_pcpu_fini(struct pmc_mdep *md, int cpu)
+{
+
+       return (0);
+}
+
+struct pmc_mdep *
+pmc_beri_initialize()
+{
+       struct pmc_mdep *pmc_mdep;
+       struct pmc_classdep *pcd;
+       
+       snprintf(pmc_cpuid, sizeof(pmc_cpuid), "beri");
+
+       beri_npmcs = 2;
+       
+       PMCDBG1(MDP,INI,1,"beri-init npmcs=%d", beri_npmcs);
+
+       /*
+        * Allocate space for pointers to PMC HW descriptors and for
+        * the MDEP structure used by MI code.
+        */
+       beri_pcpu = malloc(sizeof(struct beri_cpu *) * pmc_cpu_max(), M_PMC,
+                          M_WAITOK|M_ZERO);
+
+       /* Just one class */
+       pmc_mdep = pmc_mdep_alloc(1);
+
+       pmc_mdep->pmd_cputype = beri_pmc_spec.ps_cputype;
+
+       pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_MIPS];
+       pcd->pcd_caps = beri_pmc_spec.ps_capabilities;
+       pcd->pcd_class = beri_pmc_spec.ps_cpuclass;
+       pcd->pcd_num = beri_npmcs;
+       pcd->pcd_ri = pmc_mdep->pmd_npmc;
+       pcd->pcd_width = beri_pmc_spec.ps_counter_width;
+
+       pcd->pcd_allocate_pmc   = beri_allocate_pmc;
+       pcd->pcd_config_pmc     = beri_config_pmc;
+       pcd->pcd_pcpu_fini      = beri_pcpu_fini;
+       pcd->pcd_pcpu_init      = beri_pcpu_init;
+       pcd->pcd_describe       = beri_describe;
+       pcd->pcd_get_config     = beri_get_config;
+       pcd->pcd_read_pmc       = beri_read_pmc;
+       pcd->pcd_release_pmc    = beri_release_pmc;
+       pcd->pcd_start_pmc      = beri_start_pmc;
+       pcd->pcd_stop_pmc       = beri_stop_pmc;
+       pcd->pcd_write_pmc      = beri_write_pmc;
+
+       pmc_mdep->pmd_intr       = NULL;
+       pmc_mdep->pmd_switch_in  = beri_pmc_switch_in;
+       pmc_mdep->pmd_switch_out = beri_pmc_switch_out;
+       
+       pmc_mdep->pmd_npmc += beri_npmcs;
+
+       return (pmc_mdep);
+}
+
+void
+pmc_beri_finalize(struct pmc_mdep *md)
+{
+
+}
+
+struct pmc_mdep *
+pmc_md_initialize()
+{
+
+       return (pmc_beri_initialize());
+}
+
+void
+pmc_md_finalize(struct pmc_mdep *md)
+{
+
+       return (pmc_beri_finalize(md));
+}
+
+int
+pmc_save_kernel_callchain(uintptr_t *cc, int nframes,
+    struct trapframe *tf)
+{
+
+       return (0);
+}
+
+int
+pmc_save_user_callchain(uintptr_t *cc, int nframes,
+    struct trapframe *tf)
+{
+
+       return (0);
+}

Added: head/sys/dev/hwpmc/hwpmc_beri.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/hwpmc/hwpmc_beri.h     Wed Sep 18 16:13:50 2019        
(r352487)
@@ -0,0 +1,107 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Alex Richardson
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef        _DEV_HWPMC_HWPMC_BERI_H_
+#define        _DEV_HWPMC_HWPMC_BERI_H_
+
+#define STATCOUNTER_ITEM(name, X, Y)                           \
+static inline uint64_t statcounters_get_##name##_count(void)   \
+{                                                              \
+       uint64_t ret;                                           \
+       __asm __volatile(                                       \
+                       ".word (0x1f << 26) | (0x0 << 21) |     \
+                               (12 << 16) | ("#X" << 11) |     \
+                               ( "#Y"  << 6) | 0x3b\n\t"       \
+                       "move %0,$12" : "=r" (ret) :: "$12");   \
+       return (ret);                                           \
+}
+
+STATCOUNTER_ITEM(cycle,2,0)
+STATCOUNTER_ITEM(inst,4,0)
+STATCOUNTER_ITEM(inst_user,4,1)
+STATCOUNTER_ITEM(inst_kernel,4,2)
+STATCOUNTER_ITEM(imprecise_setbounds,4,3)
+STATCOUNTER_ITEM(unrepresentable_caps,4,4)
+STATCOUNTER_ITEM(itlb_miss,5,0)
+STATCOUNTER_ITEM(dtlb_miss,6,0)
+STATCOUNTER_ITEM(icache_write_hit,8,0)
+STATCOUNTER_ITEM(icache_write_miss,8,1)
+STATCOUNTER_ITEM(icache_read_hit,8,2)
+STATCOUNTER_ITEM(icache_read_miss,8,3)
+STATCOUNTER_ITEM(icache_evict,8,6)
+STATCOUNTER_ITEM(dcache_write_hit,9,0)
+STATCOUNTER_ITEM(dcache_write_miss,9,1)
+STATCOUNTER_ITEM(dcache_read_hit,9,2)
+STATCOUNTER_ITEM(dcache_read_miss,9,3)
+STATCOUNTER_ITEM(dcache_evict,9,6)
+STATCOUNTER_ITEM(dcache_set_tag_write,9,8)
+STATCOUNTER_ITEM(dcache_set_tag_read,9,9)
+STATCOUNTER_ITEM(l2cache_write_hit,10,0)
+STATCOUNTER_ITEM(l2cache_write_miss,10,1)
+STATCOUNTER_ITEM(l2cache_read_hit,10,2)
+STATCOUNTER_ITEM(l2cache_read_miss,10,3)
+STATCOUNTER_ITEM(l2cache_evict,10,6)
+STATCOUNTER_ITEM(l2cache_set_tag_write,10,8)
+STATCOUNTER_ITEM(l2cache_set_tag_read,10,9)
+STATCOUNTER_ITEM(mem_byte_read,11,0)
+STATCOUNTER_ITEM(mem_byte_write,11,1)
+STATCOUNTER_ITEM(mem_hword_read,11,2)
+STATCOUNTER_ITEM(mem_hword_write,11,3)
+STATCOUNTER_ITEM(mem_word_read,11,4)
+STATCOUNTER_ITEM(mem_word_write,11,5)
+STATCOUNTER_ITEM(mem_dword_read,11,6)
+STATCOUNTER_ITEM(mem_dword_write,11,7)
+STATCOUNTER_ITEM(mem_cap_read,11,8)
+STATCOUNTER_ITEM(mem_cap_write,11,9)
+STATCOUNTER_ITEM(mem_cap_read_tag_set,11,10)
+STATCOUNTER_ITEM(mem_cap_write_tag_set,11,11)
+STATCOUNTER_ITEM(tagcache_write_hit,12,0)
+STATCOUNTER_ITEM(tagcache_write_miss,12,1)
+STATCOUNTER_ITEM(tagcache_read_hit,12,2)
+STATCOUNTER_ITEM(tagcache_read_miss,12,3)
+STATCOUNTER_ITEM(tagcache_evict,12,6)
+STATCOUNTER_ITEM(l2cachemaster_read_req,13,0)
+STATCOUNTER_ITEM(l2cachemaster_write_req,13,1)
+STATCOUNTER_ITEM(l2cachemaster_write_req_flit,13,2)
+STATCOUNTER_ITEM(l2cachemaster_read_rsp,13,3)
+STATCOUNTER_ITEM(l2cachemaster_read_rsp_flit,13,4)
+STATCOUNTER_ITEM(l2cachemaster_write_rsp,13,5)
+STATCOUNTER_ITEM(tagcachemaster_read_req,14,0)
+STATCOUNTER_ITEM(tagcachemaster_write_req,14,1)
+STATCOUNTER_ITEM(tagcachemaster_write_req_flit,14,2)
+STATCOUNTER_ITEM(tagcachemaster_read_rsp,14,3)
+STATCOUNTER_ITEM(tagcachemaster_read_rsp_flit,14,4)
+STATCOUNTER_ITEM(tagcachemaster_write_rsp,14,5)
+
+#endif /* !_DEV_HWPMC_HWPMC_BERI_H_ */

Modified: head/sys/dev/hwpmc/pmc_events.h
==============================================================================
--- head/sys/dev/hwpmc/pmc_events.h     Wed Sep 18 16:13:10 2019        
(r352486)
+++ head/sys/dev/hwpmc/pmc_events.h     Wed Sep 18 16:13:50 2019        
(r352487)
@@ -1246,6 +1246,67 @@ __PMC_EV_ALIAS("unhalted-core-cycles",           
IAP_ARCH_UNH_C
 #define        PMC_EV_MIPS74K_FIRST    PMC_EV_MIPS74K_CYCLES
 #define        PMC_EV_MIPS74K_LAST     PMC_EV_MIPS74K_WBB_25_50_FULL
 
+#define __PMC_EV_BERI()                                        \
+       __PMC_EV(BERI, CYCLE)                           \
+       __PMC_EV(BERI, INST)                            \
+       __PMC_EV(BERI, INST_USER)                       \
+       __PMC_EV(BERI, INST_KERNEL)                     \
+       __PMC_EV(BERI, IMPRECISE_SETBOUNDS)             \
+       __PMC_EV(BERI, UNREPRESENTABLE_CAPS)            \
+       __PMC_EV(BERI, ITLB_MISS)                       \
+       __PMC_EV(BERI, DTLB_MISS)                       \
+       __PMC_EV(BERI, ICACHE_WRITE_HIT)                \
+       __PMC_EV(BERI, ICACHE_WRITE_MISS)               \
+       __PMC_EV(BERI, ICACHE_READ_HIT)                 \
+       __PMC_EV(BERI, ICACHE_READ_MISS)                \
+       __PMC_EV(BERI, ICACHE_EVICT)                    \
+       __PMC_EV(BERI, DCACHE_WRITE_HIT)                \
+       __PMC_EV(BERI, DCACHE_WRITE_MISS)               \
+       __PMC_EV(BERI, DCACHE_READ_HIT)                 \
+       __PMC_EV(BERI, DCACHE_READ_MISS)                \
+       __PMC_EV(BERI, DCACHE_EVICT)                    \
+       __PMC_EV(BERI, DCACHE_SET_TAG_WRITE)            \
+       __PMC_EV(BERI, DCACHE_SET_TAG_READ)             \
+       __PMC_EV(BERI, L2CACHE_WRITE_HIT)               \
+       __PMC_EV(BERI, L2CACHE_WRITE_MISS)              \
+       __PMC_EV(BERI, L2CACHE_READ_HIT)                \
+       __PMC_EV(BERI, L2CACHE_READ_MISS)               \
+       __PMC_EV(BERI, L2CACHE_EVICT)                   \
+       __PMC_EV(BERI, L2CACHE_SET_TAG_WRITE)           \
+       __PMC_EV(BERI, L2CACHE_SET_TAG_READ)            \
+       __PMC_EV(BERI, MEM_BYTE_READ)                   \
+       __PMC_EV(BERI, MEM_BYTE_WRITE)                  \
+       __PMC_EV(BERI, MEM_HWORD_READ)                  \
+       __PMC_EV(BERI, MEM_HWORD_WRITE)                 \
+       __PMC_EV(BERI, MEM_WORD_READ)                   \
+       __PMC_EV(BERI, MEM_WORD_WRITE)                  \
+       __PMC_EV(BERI, MEM_DWORD_READ)                  \
+       __PMC_EV(BERI, MEM_DWORD_WRITE)                 \
+       __PMC_EV(BERI, MEM_CAP_READ)                    \
+       __PMC_EV(BERI, MEM_CAP_WRITE)                   \
+       __PMC_EV(BERI, MEM_CAP_READ_TAG_SET)            \
+       __PMC_EV(BERI, MEM_CAP_WRITE_TAG_SET)           \
+       __PMC_EV(BERI, TAGCACHE_WRITE_HIT)              \
+       __PMC_EV(BERI, TAGCACHE_WRITE_MISS)             \
+       __PMC_EV(BERI, TAGCACHE_READ_HIT)               \
+       __PMC_EV(BERI, TAGCACHE_READ_MISS)              \
+       __PMC_EV(BERI, TAGCACHE_EVICT)                  \
+       __PMC_EV(BERI, L2CACHEMASTER_READ_REQ)          \
+       __PMC_EV(BERI, L2CACHEMASTER_WRITE_REQ)         \
+       __PMC_EV(BERI, L2CACHEMASTER_WRITE_REQ_FLIT)    \
+       __PMC_EV(BERI, L2CACHEMASTER_READ_RSP)          \
+       __PMC_EV(BERI, L2CACHEMASTER_READ_RSP_FLIT)     \
+       __PMC_EV(BERI, L2CACHEMASTER_WRITE_RSP)         \
+       __PMC_EV(BERI, TAGCACHEMASTER_READ_REQ)         \
+       __PMC_EV(BERI, TAGCACHEMASTER_WRITE_REQ)        \
+       __PMC_EV(BERI, TAGCACHEMASTER_WRITE_REQ_FLIT)   \
+       __PMC_EV(BERI, TAGCACHEMASTER_READ_RSP)         \
+       __PMC_EV(BERI, TAGCACHEMASTER_READ_RSP_FLIT)    \
+       __PMC_EV(BERI, TAGCACHEMASTER_WRITE_RSP)
+
+#define        PMC_EV_BERI_FIRST       PMC_EV_BERI_CYCLE
+#define        PMC_EV_BERI_LAST        PMC_EV_BERI_TAGCACHEMASTER_WRITE_RSP
+
 /*
  * Cavium Octeon counters. Obtained from cvmx-core.h
  */
@@ -1774,6 +1835,7 @@ __PMC_EV_ALIAS("unhalted-core-cycles",            
IAP_ARCH_UNH_C
  * 0x11300     0x00FF          MIPS 24K events
  * 0x11400     0x00FF          Octeon events
  * 0x11500     0x00FF          MIPS 74K events
+ * 0x11600     0x00FF          BERI statcounters
  * 0x13000     0x00FF          MPC7450 events
  * 0x13100     0x00FF          IBM PPC970 events
  * 0x13300     0x00FF          Freescale e500 events
@@ -1798,6 +1860,8 @@ __PMC_EV_ALIAS("unhalted-core-cycles",            
IAP_ARCH_UNH_C
        __PMC_EV_OCTEON()                       \
        __PMC_EV_BLOCK(MIPS74K, 0x11500)        \
        __PMC_EV_MIPS74K()                      \
+       __PMC_EV_BLOCK(BERI,    0x11600)        \
+       __PMC_EV_BERI()                         \
        __PMC_EV_BLOCK(UCP,     0x12080)        \
        __PMC_EV_UCP()                          \
        __PMC_EV_BLOCK(PPC7450, 0x13000)        \

Modified: head/sys/sys/pmc.h
==============================================================================
--- head/sys/sys/pmc.h  Wed Sep 18 16:13:10 2019        (r352486)
+++ head/sys/sys/pmc.h  Wed Sep 18 16:13:50 2019        (r352487)
@@ -114,6 +114,7 @@ extern char pmc_cpuid[PMC_CPUID_LEN];
        __PMC_CPU(MIPS_24K,     0x200,  "MIPS 24K")             \
        __PMC_CPU(MIPS_OCTEON,  0x201,  "Cavium Octeon")        \
        __PMC_CPU(MIPS_74K,     0x202,  "MIPS 74K")             \
+       __PMC_CPU(MIPS_BERI,    0x203,  "BERI")                 \
        __PMC_CPU(PPC_7450,     0x300,  "PowerPC MPC7450")      \
        __PMC_CPU(PPC_E500,     0x340,  "PowerPC e500 Core")    \
        __PMC_CPU(PPC_970,      0x380,  "IBM PowerPC 970")      \
@@ -160,7 +161,8 @@ enum pmc_cputype {
        __PMC_CLASS(ARMV7,      0x10,   "ARMv7")                        \
        __PMC_CLASS(ARMV8,      0x11,   "ARMv8")                        \
        __PMC_CLASS(MIPS74K,    0x12,   "MIPS 74K")                     \
-       __PMC_CLASS(E500,       0x13,   "Freescale e500 class")
+       __PMC_CLASS(E500,       0x13,   "Freescale e500 class")         \
+       __PMC_CLASS(BERI,       0x14,   "MIPS BERI")
 
 enum pmc_class {
 #undef  __PMC_CLASS
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to