1e829eb6dSJoseph Koshy /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 4e829eb6dSJoseph Koshy * Copyright (c) 2008 Joseph Koshy 5e829eb6dSJoseph Koshy * All rights reserved. 6e829eb6dSJoseph Koshy * 7e829eb6dSJoseph Koshy * Redistribution and use in source and binary forms, with or without 8e829eb6dSJoseph Koshy * modification, are permitted provided that the following conditions 9e829eb6dSJoseph Koshy * are met: 10e829eb6dSJoseph Koshy * 1. Redistributions of source code must retain the above copyright 11e829eb6dSJoseph Koshy * notice, this list of conditions and the following disclaimer. 12e829eb6dSJoseph Koshy * 2. Redistributions in binary form must reproduce the above copyright 13e829eb6dSJoseph Koshy * notice, this list of conditions and the following disclaimer in the 14e829eb6dSJoseph Koshy * documentation and/or other materials provided with the distribution. 15e829eb6dSJoseph Koshy * 16e829eb6dSJoseph Koshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17e829eb6dSJoseph Koshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18e829eb6dSJoseph Koshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19e829eb6dSJoseph Koshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20e829eb6dSJoseph Koshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21e829eb6dSJoseph Koshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22e829eb6dSJoseph Koshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23e829eb6dSJoseph Koshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24e829eb6dSJoseph Koshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25e829eb6dSJoseph Koshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26e829eb6dSJoseph Koshy * SUCH DAMAGE. 27e829eb6dSJoseph Koshy */ 28e829eb6dSJoseph Koshy 29e829eb6dSJoseph Koshy #include <sys/cdefs.h> 30e829eb6dSJoseph Koshy #include <sys/param.h> 31e829eb6dSJoseph Koshy #include <sys/pmc.h> 32e829eb6dSJoseph Koshy #include <sys/pmckern.h> 33e829eb6dSJoseph Koshy #include <sys/systm.h> 34e829eb6dSJoseph Koshy 35e829eb6dSJoseph Koshy #include <machine/specialreg.h> 36e829eb6dSJoseph Koshy 37e829eb6dSJoseph Koshy /* 38e829eb6dSJoseph Koshy * TSC support. 39e829eb6dSJoseph Koshy */ 40e829eb6dSJoseph Koshy 41e829eb6dSJoseph Koshy #define TSC_CAPS PMC_CAP_READ 42e829eb6dSJoseph Koshy 43e829eb6dSJoseph Koshy struct tsc_descr { 44e829eb6dSJoseph Koshy struct pmc_descr pm_descr; /* "base class" */ 45e829eb6dSJoseph Koshy }; 46e829eb6dSJoseph Koshy 47e829eb6dSJoseph Koshy static struct tsc_descr tsc_pmcdesc[TSC_NPMCS] = 48e829eb6dSJoseph Koshy { 49e829eb6dSJoseph Koshy { 50e829eb6dSJoseph Koshy .pm_descr = 51e829eb6dSJoseph Koshy { 52e829eb6dSJoseph Koshy .pd_name = "TSC", 53e829eb6dSJoseph Koshy .pd_class = PMC_CLASS_TSC, 54e829eb6dSJoseph Koshy .pd_caps = TSC_CAPS, 55e829eb6dSJoseph Koshy .pd_width = 64 56e829eb6dSJoseph Koshy } 57e829eb6dSJoseph Koshy } 58e829eb6dSJoseph Koshy }; 59e829eb6dSJoseph Koshy 60e829eb6dSJoseph Koshy /* 61e829eb6dSJoseph Koshy * Per-CPU data structure for TSCs. 62e829eb6dSJoseph Koshy */ 63e829eb6dSJoseph Koshy 64e829eb6dSJoseph Koshy struct tsc_cpu { 65e829eb6dSJoseph Koshy struct pmc_hw tc_hw; 66e829eb6dSJoseph Koshy }; 67e829eb6dSJoseph Koshy 68e829eb6dSJoseph Koshy static struct tsc_cpu **tsc_pcpu; 69e829eb6dSJoseph Koshy 70e829eb6dSJoseph Koshy static int 71a35453b9SMitchell Horne tsc_allocate_pmc(int cpu __diagused, int ri __diagused, struct pmc *pm __unused, 72e829eb6dSJoseph Koshy const struct pmc_op_pmcallocate *a) 73e829eb6dSJoseph Koshy { 74e829eb6dSJoseph Koshy 75e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 76e829eb6dSJoseph Koshy ("[tsc,%d] illegal CPU value %d", __LINE__, cpu)); 77e829eb6dSJoseph Koshy KASSERT(ri >= 0 && ri < TSC_NPMCS, 78e829eb6dSJoseph Koshy ("[tsc,%d] illegal row index %d", __LINE__, ri)); 79e829eb6dSJoseph Koshy 80e829eb6dSJoseph Koshy if (a->pm_class != PMC_CLASS_TSC) 81e829eb6dSJoseph Koshy return (EINVAL); 82e829eb6dSJoseph Koshy 83e829eb6dSJoseph Koshy if (a->pm_ev != PMC_EV_TSC_TSC || 84e829eb6dSJoseph Koshy a->pm_mode != PMC_MODE_SC) 85e829eb6dSJoseph Koshy return (EINVAL); 86e829eb6dSJoseph Koshy 87e829eb6dSJoseph Koshy return (0); 88e829eb6dSJoseph Koshy } 89e829eb6dSJoseph Koshy 90e829eb6dSJoseph Koshy static int 91e829eb6dSJoseph Koshy tsc_config_pmc(int cpu, int ri, struct pmc *pm) 92e829eb6dSJoseph Koshy { 93e829eb6dSJoseph Koshy struct pmc_hw *phw; 94e829eb6dSJoseph Koshy 954a3690dfSJohn Baldwin PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); 96e829eb6dSJoseph Koshy 97e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 98e829eb6dSJoseph Koshy ("[tsc,%d] illegal CPU value %d", __LINE__, cpu)); 99e829eb6dSJoseph Koshy KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri)); 100e829eb6dSJoseph Koshy 101e829eb6dSJoseph Koshy phw = &tsc_pcpu[cpu]->tc_hw; 102e829eb6dSJoseph Koshy 103e829eb6dSJoseph Koshy KASSERT(pm == NULL || phw->phw_pmc == NULL, 104e829eb6dSJoseph Koshy ("[tsc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", __LINE__, 105e829eb6dSJoseph Koshy pm, phw->phw_pmc)); 106e829eb6dSJoseph Koshy 107e829eb6dSJoseph Koshy phw->phw_pmc = pm; 108e829eb6dSJoseph Koshy 109e829eb6dSJoseph Koshy return (0); 110e829eb6dSJoseph Koshy } 111e829eb6dSJoseph Koshy 112e829eb6dSJoseph Koshy static int 113e829eb6dSJoseph Koshy tsc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 114e829eb6dSJoseph Koshy { 115e829eb6dSJoseph Koshy const struct tsc_descr *pd; 116e829eb6dSJoseph Koshy struct pmc_hw *phw; 117e829eb6dSJoseph Koshy 118e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 119e829eb6dSJoseph Koshy ("[tsc,%d] illegal CPU %d", __LINE__, cpu)); 120e829eb6dSJoseph Koshy KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri)); 121e829eb6dSJoseph Koshy 122e829eb6dSJoseph Koshy phw = &tsc_pcpu[cpu]->tc_hw; 123e829eb6dSJoseph Koshy pd = &tsc_pmcdesc[ri]; 124e829eb6dSJoseph Koshy 12531610e34SMitchell Horne strlcpy(pi->pm_name, pd->pm_descr.pd_name, sizeof(pi->pm_name)); 126e829eb6dSJoseph Koshy pi->pm_class = pd->pm_descr.pd_class; 127e829eb6dSJoseph Koshy 128e829eb6dSJoseph Koshy if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 129e829eb6dSJoseph Koshy pi->pm_enabled = TRUE; 130e829eb6dSJoseph Koshy *ppmc = phw->phw_pmc; 131e829eb6dSJoseph Koshy } else { 132e829eb6dSJoseph Koshy pi->pm_enabled = FALSE; 133e829eb6dSJoseph Koshy *ppmc = NULL; 134e829eb6dSJoseph Koshy } 135e829eb6dSJoseph Koshy 136e829eb6dSJoseph Koshy return (0); 137e829eb6dSJoseph Koshy } 138e829eb6dSJoseph Koshy 139e829eb6dSJoseph Koshy static int 140a35453b9SMitchell Horne tsc_get_config(int cpu, int ri __diagused, struct pmc **ppm) 141e829eb6dSJoseph Koshy { 142e829eb6dSJoseph Koshy 143e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 144e829eb6dSJoseph Koshy ("[tsc,%d] illegal CPU %d", __LINE__, cpu)); 145e829eb6dSJoseph Koshy KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri)); 146e829eb6dSJoseph Koshy 147e829eb6dSJoseph Koshy *ppm = tsc_pcpu[cpu]->tc_hw.phw_pmc; 148e829eb6dSJoseph Koshy 149e829eb6dSJoseph Koshy return (0); 150e829eb6dSJoseph Koshy } 151e829eb6dSJoseph Koshy 152e829eb6dSJoseph Koshy static int 153a35453b9SMitchell Horne tsc_get_msr(int ri __diagused, uint32_t *msr) 154e829eb6dSJoseph Koshy { 155e829eb6dSJoseph Koshy 156e829eb6dSJoseph Koshy KASSERT(ri >= 0 && ri < TSC_NPMCS, 157e829eb6dSJoseph Koshy ("[tsc,%d] ri %d out of range", __LINE__, ri)); 158e829eb6dSJoseph Koshy 159e829eb6dSJoseph Koshy *msr = MSR_TSC; 160e829eb6dSJoseph Koshy 161e829eb6dSJoseph Koshy return (0); 162e829eb6dSJoseph Koshy } 163e829eb6dSJoseph Koshy 164e829eb6dSJoseph Koshy static int 165e829eb6dSJoseph Koshy tsc_pcpu_fini(struct pmc_mdep *md, int cpu) 166e829eb6dSJoseph Koshy { 167e829eb6dSJoseph Koshy int ri; 168e829eb6dSJoseph Koshy struct pmc_cpu *pc; 169e829eb6dSJoseph Koshy 170e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 171e829eb6dSJoseph Koshy ("[tsc,%d] illegal cpu %d", __LINE__, cpu)); 172e829eb6dSJoseph Koshy KASSERT(tsc_pcpu[cpu] != NULL, ("[tsc,%d] null pcpu", __LINE__)); 173e829eb6dSJoseph Koshy 174e829eb6dSJoseph Koshy free(tsc_pcpu[cpu], M_PMC); 175e829eb6dSJoseph Koshy tsc_pcpu[cpu] = NULL; 176e829eb6dSJoseph Koshy 177e829eb6dSJoseph Koshy ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_TSC].pcd_ri; 178e829eb6dSJoseph Koshy 179e829eb6dSJoseph Koshy pc = pmc_pcpu[cpu]; 180e829eb6dSJoseph Koshy pc->pc_hwpmcs[ri] = NULL; 181e829eb6dSJoseph Koshy 182e829eb6dSJoseph Koshy return (0); 183e829eb6dSJoseph Koshy } 184e829eb6dSJoseph Koshy 185e829eb6dSJoseph Koshy static int 186e829eb6dSJoseph Koshy tsc_pcpu_init(struct pmc_mdep *md, int cpu) 187e829eb6dSJoseph Koshy { 188e829eb6dSJoseph Koshy int ri; 189e829eb6dSJoseph Koshy struct pmc_cpu *pc; 190e829eb6dSJoseph Koshy struct tsc_cpu *tsc_pc; 191e829eb6dSJoseph Koshy 192e829eb6dSJoseph Koshy 193e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 194e829eb6dSJoseph Koshy ("[tsc,%d] illegal cpu %d", __LINE__, cpu)); 195e829eb6dSJoseph Koshy KASSERT(tsc_pcpu, ("[tsc,%d] null pcpu", __LINE__)); 196e829eb6dSJoseph Koshy KASSERT(tsc_pcpu[cpu] == NULL, ("[tsc,%d] non-null per-cpu", 197e829eb6dSJoseph Koshy __LINE__)); 198e829eb6dSJoseph Koshy 199e829eb6dSJoseph Koshy tsc_pc = malloc(sizeof(struct tsc_cpu), M_PMC, M_WAITOK|M_ZERO); 200e829eb6dSJoseph Koshy 201e829eb6dSJoseph Koshy tsc_pc->tc_hw.phw_state = PMC_PHW_FLAG_IS_ENABLED | 202e829eb6dSJoseph Koshy PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(0) | 203e829eb6dSJoseph Koshy PMC_PHW_FLAG_IS_SHAREABLE; 204e829eb6dSJoseph Koshy 205e829eb6dSJoseph Koshy tsc_pcpu[cpu] = tsc_pc; 206e829eb6dSJoseph Koshy 207e829eb6dSJoseph Koshy ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_TSC].pcd_ri; 208e829eb6dSJoseph Koshy 209e829eb6dSJoseph Koshy KASSERT(pmc_pcpu, ("[tsc,%d] null generic pcpu", __LINE__)); 210e829eb6dSJoseph Koshy 211e829eb6dSJoseph Koshy pc = pmc_pcpu[cpu]; 212e829eb6dSJoseph Koshy 213e829eb6dSJoseph Koshy KASSERT(pc, ("[tsc,%d] null generic per-cpu", __LINE__)); 214e829eb6dSJoseph Koshy 215e829eb6dSJoseph Koshy pc->pc_hwpmcs[ri] = &tsc_pc->tc_hw; 216e829eb6dSJoseph Koshy 217e829eb6dSJoseph Koshy return (0); 218e829eb6dSJoseph Koshy } 219e829eb6dSJoseph Koshy 220e829eb6dSJoseph Koshy static int 22139f92a76SMitchell Horne tsc_read_pmc(int cpu, int ri, struct pmc *pm, pmc_value_t *v) 222e829eb6dSJoseph Koshy { 223aee6e7dcSMateusz Guzik enum pmc_mode mode __diagused; 224e829eb6dSJoseph Koshy 225e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 226e829eb6dSJoseph Koshy ("[tsc,%d] illegal CPU value %d", __LINE__, cpu)); 227e829eb6dSJoseph Koshy KASSERT(ri == 0, ("[tsc,%d] illegal ri %d", __LINE__, ri)); 228e829eb6dSJoseph Koshy 229e829eb6dSJoseph Koshy mode = PMC_TO_MODE(pm); 230e829eb6dSJoseph Koshy 231e829eb6dSJoseph Koshy KASSERT(mode == PMC_MODE_SC, 232e829eb6dSJoseph Koshy ("[tsc,%d] illegal pmc mode %d", __LINE__, mode)); 233e829eb6dSJoseph Koshy 2344a3690dfSJohn Baldwin PMCDBG1(MDP,REA,1,"tsc-read id=%d", ri); 235e829eb6dSJoseph Koshy 236e829eb6dSJoseph Koshy *v = rdtsc(); 237e829eb6dSJoseph Koshy 238e829eb6dSJoseph Koshy return (0); 239e829eb6dSJoseph Koshy } 240e829eb6dSJoseph Koshy 241e829eb6dSJoseph Koshy static int 242a35453b9SMitchell Horne tsc_release_pmc(int cpu, int ri __diagused, struct pmc *pmc __unused) 243e829eb6dSJoseph Koshy { 244aee6e7dcSMateusz Guzik struct pmc_hw *phw __diagused; 245e829eb6dSJoseph Koshy 246e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 247e829eb6dSJoseph Koshy ("[tsc,%d] illegal CPU value %d", __LINE__, cpu)); 248e829eb6dSJoseph Koshy KASSERT(ri == 0, 249e829eb6dSJoseph Koshy ("[tsc,%d] illegal row-index %d", __LINE__, ri)); 250e829eb6dSJoseph Koshy 251e829eb6dSJoseph Koshy phw = &tsc_pcpu[cpu]->tc_hw; 252e829eb6dSJoseph Koshy 253e829eb6dSJoseph Koshy KASSERT(phw->phw_pmc == NULL, 254e829eb6dSJoseph Koshy ("[tsc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); 255e829eb6dSJoseph Koshy 256e829eb6dSJoseph Koshy /* 257e829eb6dSJoseph Koshy * Nothing to do. 258e829eb6dSJoseph Koshy */ 259e829eb6dSJoseph Koshy return (0); 260e829eb6dSJoseph Koshy } 261e829eb6dSJoseph Koshy 262e829eb6dSJoseph Koshy static int 26339f92a76SMitchell Horne tsc_start_pmc(int cpu __diagused, int ri __diagused, struct pmc *pm __unused) 264e829eb6dSJoseph Koshy { 265e829eb6dSJoseph Koshy 266e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 267e829eb6dSJoseph Koshy ("[tsc,%d] illegal CPU value %d", __LINE__, cpu)); 268e829eb6dSJoseph Koshy KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri)); 269e829eb6dSJoseph Koshy 270e829eb6dSJoseph Koshy return (0); /* TSCs are always running. */ 271e829eb6dSJoseph Koshy } 272e829eb6dSJoseph Koshy 273e829eb6dSJoseph Koshy static int 27439f92a76SMitchell Horne tsc_stop_pmc(int cpu __diagused, int ri __diagused, struct pmc *pm __unused) 275e829eb6dSJoseph Koshy { 276e829eb6dSJoseph Koshy 277e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 278e829eb6dSJoseph Koshy ("[tsc,%d] illegal CPU value %d", __LINE__, cpu)); 279e829eb6dSJoseph Koshy KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri)); 280e829eb6dSJoseph Koshy 281e829eb6dSJoseph Koshy return (0); /* Cannot actually stop a TSC. */ 282e829eb6dSJoseph Koshy } 283e829eb6dSJoseph Koshy 284e829eb6dSJoseph Koshy static int 28539f92a76SMitchell Horne tsc_write_pmc(int cpu __diagused, int ri __diagused, struct pmc *pm __unused, 28639f92a76SMitchell Horne pmc_value_t v __unused) 287e829eb6dSJoseph Koshy { 288e829eb6dSJoseph Koshy 289e829eb6dSJoseph Koshy KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 290e829eb6dSJoseph Koshy ("[tsc,%d] illegal CPU value %d", __LINE__, cpu)); 291e829eb6dSJoseph Koshy KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri)); 292e829eb6dSJoseph Koshy 293e829eb6dSJoseph Koshy /* 294e829eb6dSJoseph Koshy * The TSCs are used as timecounters by the kernel, so even 295e829eb6dSJoseph Koshy * though some i386 CPUs support writeable TSCs, we don't 296e829eb6dSJoseph Koshy * support writing changing TSC values through the HWPMC API. 297e829eb6dSJoseph Koshy */ 298e829eb6dSJoseph Koshy return (0); 299e829eb6dSJoseph Koshy } 300e829eb6dSJoseph Koshy 301e829eb6dSJoseph Koshy int 302e829eb6dSJoseph Koshy pmc_tsc_initialize(struct pmc_mdep *md, int maxcpu) 303e829eb6dSJoseph Koshy { 304e829eb6dSJoseph Koshy struct pmc_classdep *pcd; 305e829eb6dSJoseph Koshy 306e829eb6dSJoseph Koshy KASSERT(md != NULL, ("[tsc,%d] md is NULL", __LINE__)); 307e829eb6dSJoseph Koshy KASSERT(md->pmd_nclass >= 1, ("[tsc,%d] dubious md->nclass %d", 308e829eb6dSJoseph Koshy __LINE__, md->pmd_nclass)); 309e829eb6dSJoseph Koshy 310e829eb6dSJoseph Koshy tsc_pcpu = malloc(sizeof(struct tsc_cpu *) * maxcpu, M_PMC, 311e829eb6dSJoseph Koshy M_ZERO|M_WAITOK); 312e829eb6dSJoseph Koshy 313e829eb6dSJoseph Koshy pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_TSC]; 314e829eb6dSJoseph Koshy 315e829eb6dSJoseph Koshy pcd->pcd_caps = PMC_CAP_READ; 316e829eb6dSJoseph Koshy pcd->pcd_class = PMC_CLASS_TSC; 317e829eb6dSJoseph Koshy pcd->pcd_num = TSC_NPMCS; 318e829eb6dSJoseph Koshy pcd->pcd_ri = md->pmd_npmc; 319e829eb6dSJoseph Koshy pcd->pcd_width = 64; 320e829eb6dSJoseph Koshy 321e829eb6dSJoseph Koshy pcd->pcd_allocate_pmc = tsc_allocate_pmc; 322e829eb6dSJoseph Koshy pcd->pcd_config_pmc = tsc_config_pmc; 323e829eb6dSJoseph Koshy pcd->pcd_describe = tsc_describe; 324e829eb6dSJoseph Koshy pcd->pcd_get_config = tsc_get_config; 325e829eb6dSJoseph Koshy pcd->pcd_get_msr = tsc_get_msr; 326e829eb6dSJoseph Koshy pcd->pcd_pcpu_init = tsc_pcpu_init; 327e829eb6dSJoseph Koshy pcd->pcd_pcpu_fini = tsc_pcpu_fini; 328e829eb6dSJoseph Koshy pcd->pcd_read_pmc = tsc_read_pmc; 329e829eb6dSJoseph Koshy pcd->pcd_release_pmc = tsc_release_pmc; 330e829eb6dSJoseph Koshy pcd->pcd_start_pmc = tsc_start_pmc; 331e829eb6dSJoseph Koshy pcd->pcd_stop_pmc = tsc_stop_pmc; 332e829eb6dSJoseph Koshy pcd->pcd_write_pmc = tsc_write_pmc; 333e829eb6dSJoseph Koshy 334e829eb6dSJoseph Koshy md->pmd_npmc += TSC_NPMCS; 335e829eb6dSJoseph Koshy 336e829eb6dSJoseph Koshy return (0); 337e829eb6dSJoseph Koshy } 338e829eb6dSJoseph Koshy 339e829eb6dSJoseph Koshy void 340a35453b9SMitchell Horne pmc_tsc_finalize(struct pmc_mdep *md __diagused) 341e829eb6dSJoseph Koshy { 342*90a6ea5cSMitchell Horne PMCDBG0(MDP, INI, 1, "tsc-finalize"); 343e829eb6dSJoseph Koshy 344*90a6ea5cSMitchell Horne for (int i = 0; i < pmc_cpu_max(); i++) 345e829eb6dSJoseph Koshy KASSERT(tsc_pcpu[i] == NULL, ("[tsc,%d] non-null pcpu cpu %d", 346e829eb6dSJoseph Koshy __LINE__, i)); 347e829eb6dSJoseph Koshy 348e829eb6dSJoseph Koshy free(tsc_pcpu, M_PMC); 349e829eb6dSJoseph Koshy tsc_pcpu = NULL; 350e829eb6dSJoseph Koshy } 351