1206089Sfabient/*- 2206089Sfabient * Copyright (c) 2010 Fabien Thomas 3206089Sfabient * All rights reserved. 4206089Sfabient * 5206089Sfabient * Redistribution and use in source and binary forms, with or without 6206089Sfabient * modification, are permitted provided that the following conditions 7206089Sfabient * are met: 8206089Sfabient * 1. Redistributions of source code must retain the above copyright 9206089Sfabient * notice, this list of conditions and the following disclaimer. 10206089Sfabient * 2. Redistributions in binary form must reproduce the above copyright 11206089Sfabient * notice, this list of conditions and the following disclaimer in the 12206089Sfabient * documentation and/or other materials provided with the distribution. 13206089Sfabient * 14206089Sfabient * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15206089Sfabient * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16206089Sfabient * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17206089Sfabient * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18206089Sfabient * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19206089Sfabient * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20206089Sfabient * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21206089Sfabient * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22206089Sfabient * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23206089Sfabient * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24206089Sfabient * SUCH DAMAGE. 25206089Sfabient */ 26206089Sfabient 27206089Sfabient/* 28206089Sfabient * Intel Uncore PMCs. 29206089Sfabient */ 30206089Sfabient 31206089Sfabient#include <sys/cdefs.h> 32206089Sfabient__FBSDID("$FreeBSD$"); 33206089Sfabient 34206089Sfabient#include <sys/param.h> 35206089Sfabient#include <sys/bus.h> 36206089Sfabient#include <sys/pmc.h> 37206089Sfabient#include <sys/pmckern.h> 38206089Sfabient#include <sys/systm.h> 39206089Sfabient 40206089Sfabient#include <machine/intr_machdep.h> 41206089Sfabient#include <machine/apicvar.h> 42206089Sfabient#include <machine/cpu.h> 43206089Sfabient#include <machine/cpufunc.h> 44206089Sfabient#include <machine/specialreg.h> 45206089Sfabient 46206089Sfabient#define UCF_PMC_CAPS \ 47206089Sfabient (PMC_CAP_READ | PMC_CAP_WRITE) 48206089Sfabient 49206089Sfabient#define UCP_PMC_CAPS \ 50206089Sfabient (PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE | \ 51206089Sfabient PMC_CAP_INVERT | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE) 52206089Sfabient 53234046Sdavide#define SELECTSEL(x) \ 54249655Shiren (((x) == PMC_CPU_INTEL_SANDYBRIDGE || (x) == PMC_CPU_INTEL_HASWELL) ? \ 55249655Shiren UCP_CB0_EVSEL0 : UCP_EVSEL0) 56234046Sdavide 57234046Sdavide#define SELECTOFF(x) \ 58249655Shiren (((x) == PMC_CPU_INTEL_SANDYBRIDGE || (x) == PMC_CPU_INTEL_HASWELL) ? \ 59249655Shiren UCF_OFFSET_SB : UCF_OFFSET) 60234046Sdavide 61206089Sfabientstatic enum pmc_cputype uncore_cputype; 62206089Sfabient 63206089Sfabientstruct uncore_cpu { 64206089Sfabient volatile uint32_t pc_resync; 65206089Sfabient volatile uint32_t pc_ucfctrl; /* Fixed function control. */ 66206089Sfabient volatile uint64_t pc_globalctrl; /* Global control register. */ 67206089Sfabient struct pmc_hw pc_uncorepmcs[]; 68206089Sfabient}; 69206089Sfabient 70206089Sfabientstatic struct uncore_cpu **uncore_pcpu; 71206089Sfabient 72206089Sfabientstatic uint64_t uncore_pmcmask; 73206089Sfabient 74206089Sfabientstatic int uncore_ucf_ri; /* relative index of fixed counters */ 75206089Sfabientstatic int uncore_ucf_width; 76206089Sfabientstatic int uncore_ucf_npmc; 77206089Sfabient 78206089Sfabientstatic int uncore_ucp_width; 79206089Sfabientstatic int uncore_ucp_npmc; 80206089Sfabient 81206089Sfabientstatic int 82206089Sfabientuncore_pcpu_noop(struct pmc_mdep *md, int cpu) 83206089Sfabient{ 84206089Sfabient (void) md; 85206089Sfabient (void) cpu; 86206089Sfabient return (0); 87206089Sfabient} 88206089Sfabient 89206089Sfabientstatic int 90206089Sfabientuncore_pcpu_init(struct pmc_mdep *md, int cpu) 91206089Sfabient{ 92206089Sfabient struct pmc_cpu *pc; 93206089Sfabient struct uncore_cpu *cc; 94206089Sfabient struct pmc_hw *phw; 95206089Sfabient int uncore_ri, n, npmc; 96206089Sfabient 97206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 98206089Sfabient ("[ucf,%d] insane cpu number %d", __LINE__, cpu)); 99206089Sfabient 100206089Sfabient PMCDBG(MDP,INI,1,"uncore-init cpu=%d", cpu); 101206089Sfabient 102206089Sfabient uncore_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_ri; 103206089Sfabient npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_num; 104206089Sfabient npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCF].pcd_num; 105206089Sfabient 106206089Sfabient cc = malloc(sizeof(struct uncore_cpu) + npmc * sizeof(struct pmc_hw), 107206089Sfabient M_PMC, M_WAITOK | M_ZERO); 108206089Sfabient 109206089Sfabient uncore_pcpu[cpu] = cc; 110206089Sfabient pc = pmc_pcpu[cpu]; 111206089Sfabient 112206089Sfabient KASSERT(pc != NULL && cc != NULL, 113206089Sfabient ("[uncore,%d] NULL per-cpu structures cpu=%d", __LINE__, cpu)); 114206089Sfabient 115206089Sfabient for (n = 0, phw = cc->pc_uncorepmcs; n < npmc; n++, phw++) { 116206089Sfabient phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | 117206089Sfabient PMC_PHW_CPU_TO_STATE(cpu) | 118206089Sfabient PMC_PHW_INDEX_TO_STATE(n + uncore_ri); 119206089Sfabient phw->phw_pmc = NULL; 120206089Sfabient pc->pc_hwpmcs[n + uncore_ri] = phw; 121206089Sfabient } 122206089Sfabient 123206089Sfabient return (0); 124206089Sfabient} 125206089Sfabient 126206089Sfabientstatic int 127206089Sfabientuncore_pcpu_fini(struct pmc_mdep *md, int cpu) 128206089Sfabient{ 129206089Sfabient int uncore_ri, n, npmc; 130206089Sfabient struct pmc_cpu *pc; 131206089Sfabient struct uncore_cpu *cc; 132206089Sfabient 133206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 134206089Sfabient ("[uncore,%d] insane cpu number (%d)", __LINE__, cpu)); 135206089Sfabient 136206089Sfabient PMCDBG(MDP,INI,1,"uncore-pcpu-fini cpu=%d", cpu); 137206089Sfabient 138206089Sfabient if ((cc = uncore_pcpu[cpu]) == NULL) 139206089Sfabient return (0); 140206089Sfabient 141206089Sfabient uncore_pcpu[cpu] = NULL; 142206089Sfabient 143206089Sfabient pc = pmc_pcpu[cpu]; 144206089Sfabient 145206089Sfabient KASSERT(pc != NULL, ("[uncore,%d] NULL per-cpu %d state", __LINE__, 146206089Sfabient cpu)); 147206089Sfabient 148206089Sfabient npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_num; 149206089Sfabient uncore_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_ri; 150206089Sfabient 151234046Sdavide for (n = 0; n < npmc; n++) 152234046Sdavide wrmsr(SELECTSEL(uncore_cputype) + n, 0); 153206089Sfabient 154206089Sfabient wrmsr(UCF_CTRL, 0); 155206089Sfabient npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCF].pcd_num; 156206089Sfabient 157206089Sfabient for (n = 0; n < npmc; n++) 158206089Sfabient pc->pc_hwpmcs[n + uncore_ri] = NULL; 159206089Sfabient 160206089Sfabient free(cc, M_PMC); 161206089Sfabient 162206089Sfabient return (0); 163206089Sfabient} 164206089Sfabient 165206089Sfabient/* 166206089Sfabient * Fixed function counters. 167206089Sfabient */ 168206089Sfabient 169206089Sfabientstatic pmc_value_t 170206089Sfabientucf_perfctr_value_to_reload_count(pmc_value_t v) 171206089Sfabient{ 172206089Sfabient v &= (1ULL << uncore_ucf_width) - 1; 173206089Sfabient return (1ULL << uncore_ucf_width) - v; 174206089Sfabient} 175206089Sfabient 176206089Sfabientstatic pmc_value_t 177206089Sfabientucf_reload_count_to_perfctr_value(pmc_value_t rlc) 178206089Sfabient{ 179206089Sfabient return (1ULL << uncore_ucf_width) - rlc; 180206089Sfabient} 181206089Sfabient 182206089Sfabientstatic int 183206089Sfabientucf_allocate_pmc(int cpu, int ri, struct pmc *pm, 184206089Sfabient const struct pmc_op_pmcallocate *a) 185206089Sfabient{ 186206089Sfabient enum pmc_event ev; 187206089Sfabient uint32_t caps, flags; 188206089Sfabient 189206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 190206089Sfabient ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 191206089Sfabient 192206089Sfabient PMCDBG(MDP,ALL,1, "ucf-allocate ri=%d reqcaps=0x%x", ri, pm->pm_caps); 193206089Sfabient 194206089Sfabient if (ri < 0 || ri > uncore_ucf_npmc) 195206089Sfabient return (EINVAL); 196206089Sfabient 197206089Sfabient caps = a->pm_caps; 198206089Sfabient 199206089Sfabient if (a->pm_class != PMC_CLASS_UCF || 200206089Sfabient (caps & UCF_PMC_CAPS) != caps) 201206089Sfabient return (EINVAL); 202206089Sfabient 203206089Sfabient ev = pm->pm_event; 204206089Sfabient if (ev < PMC_EV_UCF_FIRST || ev > PMC_EV_UCF_LAST) 205206089Sfabient return (EINVAL); 206206089Sfabient 207206089Sfabient flags = UCF_EN; 208206089Sfabient 209206089Sfabient pm->pm_md.pm_ucf.pm_ucf_ctrl = (flags << (ri * 4)); 210206089Sfabient 211206089Sfabient PMCDBG(MDP,ALL,2, "ucf-allocate config=0x%jx", 212206089Sfabient (uintmax_t) pm->pm_md.pm_ucf.pm_ucf_ctrl); 213206089Sfabient 214206089Sfabient return (0); 215206089Sfabient} 216206089Sfabient 217206089Sfabientstatic int 218206089Sfabientucf_config_pmc(int cpu, int ri, struct pmc *pm) 219206089Sfabient{ 220206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 221206089Sfabient ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 222206089Sfabient 223206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 224206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 225206089Sfabient 226206089Sfabient PMCDBG(MDP,CFG,1, "ucf-config cpu=%d ri=%d pm=%p", cpu, ri, pm); 227206089Sfabient 228206089Sfabient KASSERT(uncore_pcpu[cpu] != NULL, ("[uncore,%d] null per-cpu %d", __LINE__, 229206089Sfabient cpu)); 230206089Sfabient 231206089Sfabient uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc = pm; 232206089Sfabient 233206089Sfabient return (0); 234206089Sfabient} 235206089Sfabient 236206089Sfabientstatic int 237206089Sfabientucf_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 238206089Sfabient{ 239206089Sfabient int error; 240206089Sfabient struct pmc_hw *phw; 241206089Sfabient char ucf_name[PMC_NAME_MAX]; 242206089Sfabient 243206089Sfabient phw = &uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri]; 244206089Sfabient 245206089Sfabient (void) snprintf(ucf_name, sizeof(ucf_name), "UCF-%d", ri); 246206089Sfabient if ((error = copystr(ucf_name, pi->pm_name, PMC_NAME_MAX, 247206089Sfabient NULL)) != 0) 248206089Sfabient return (error); 249206089Sfabient 250206089Sfabient pi->pm_class = PMC_CLASS_UCF; 251206089Sfabient 252206089Sfabient if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 253206089Sfabient pi->pm_enabled = TRUE; 254206089Sfabient *ppmc = phw->phw_pmc; 255206089Sfabient } else { 256206089Sfabient pi->pm_enabled = FALSE; 257206089Sfabient *ppmc = NULL; 258206089Sfabient } 259206089Sfabient 260206089Sfabient return (0); 261206089Sfabient} 262206089Sfabient 263206089Sfabientstatic int 264206089Sfabientucf_get_config(int cpu, int ri, struct pmc **ppm) 265206089Sfabient{ 266206089Sfabient *ppm = uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 267206089Sfabient 268206089Sfabient return (0); 269206089Sfabient} 270206089Sfabient 271206089Sfabientstatic int 272206089Sfabientucf_read_pmc(int cpu, int ri, pmc_value_t *v) 273206089Sfabient{ 274206089Sfabient struct pmc *pm; 275206089Sfabient pmc_value_t tmp; 276206089Sfabient 277206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 278206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 279206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 280206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 281206089Sfabient 282206089Sfabient pm = uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 283206089Sfabient 284206089Sfabient KASSERT(pm, 285206089Sfabient ("[uncore,%d] cpu %d ri %d(%d) pmc not configured", __LINE__, cpu, 286206089Sfabient ri, ri + uncore_ucf_ri)); 287206089Sfabient 288206089Sfabient tmp = rdmsr(UCF_CTR0 + ri); 289206089Sfabient 290206089Sfabient if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 291206089Sfabient *v = ucf_perfctr_value_to_reload_count(tmp); 292206089Sfabient else 293206089Sfabient *v = tmp; 294206089Sfabient 295206089Sfabient PMCDBG(MDP,REA,1, "ucf-read cpu=%d ri=%d -> v=%jx", cpu, ri, *v); 296206089Sfabient 297206089Sfabient return (0); 298206089Sfabient} 299206089Sfabient 300206089Sfabientstatic int 301206089Sfabientucf_release_pmc(int cpu, int ri, struct pmc *pmc) 302206089Sfabient{ 303206089Sfabient PMCDBG(MDP,REL,1, "ucf-release cpu=%d ri=%d pm=%p", cpu, ri, pmc); 304206089Sfabient 305206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 306206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 307206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 308206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 309206089Sfabient 310206089Sfabient KASSERT(uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc == NULL, 311206089Sfabient ("[uncore,%d] PHW pmc non-NULL", __LINE__)); 312206089Sfabient 313206089Sfabient return (0); 314206089Sfabient} 315206089Sfabient 316206089Sfabientstatic int 317206089Sfabientucf_start_pmc(int cpu, int ri) 318206089Sfabient{ 319206089Sfabient struct pmc *pm; 320206089Sfabient struct uncore_cpu *ucfc; 321206089Sfabient 322206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 323206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 324206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 325206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 326206089Sfabient 327206089Sfabient PMCDBG(MDP,STA,1,"ucf-start cpu=%d ri=%d", cpu, ri); 328206089Sfabient 329206089Sfabient ucfc = uncore_pcpu[cpu]; 330206089Sfabient pm = ucfc->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 331206089Sfabient 332206089Sfabient ucfc->pc_ucfctrl |= pm->pm_md.pm_ucf.pm_ucf_ctrl; 333206089Sfabient 334206089Sfabient wrmsr(UCF_CTRL, ucfc->pc_ucfctrl); 335206089Sfabient 336206089Sfabient do { 337206089Sfabient ucfc->pc_resync = 0; 338234046Sdavide ucfc->pc_globalctrl |= (1ULL << (ri + SELECTOFF(uncore_cputype))); 339206089Sfabient wrmsr(UC_GLOBAL_CTRL, ucfc->pc_globalctrl); 340206089Sfabient } while (ucfc->pc_resync != 0); 341206089Sfabient 342206089Sfabient PMCDBG(MDP,STA,1,"ucfctrl=%x(%x) globalctrl=%jx(%jx)", 343206089Sfabient ucfc->pc_ucfctrl, (uint32_t) rdmsr(UCF_CTRL), 344206089Sfabient ucfc->pc_globalctrl, rdmsr(UC_GLOBAL_CTRL)); 345206089Sfabient 346206089Sfabient return (0); 347206089Sfabient} 348206089Sfabient 349206089Sfabientstatic int 350206089Sfabientucf_stop_pmc(int cpu, int ri) 351206089Sfabient{ 352206089Sfabient uint32_t fc; 353206089Sfabient struct uncore_cpu *ucfc; 354206089Sfabient 355206089Sfabient PMCDBG(MDP,STO,1,"ucf-stop cpu=%d ri=%d", cpu, ri); 356206089Sfabient 357206089Sfabient ucfc = uncore_pcpu[cpu]; 358206089Sfabient 359206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 360206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 361206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 362206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 363206089Sfabient 364206089Sfabient fc = (UCF_MASK << (ri * 4)); 365206089Sfabient 366206089Sfabient ucfc->pc_ucfctrl &= ~fc; 367206089Sfabient 368206089Sfabient PMCDBG(MDP,STO,1,"ucf-stop ucfctrl=%x", ucfc->pc_ucfctrl); 369206089Sfabient wrmsr(UCF_CTRL, ucfc->pc_ucfctrl); 370206089Sfabient 371206089Sfabient do { 372206089Sfabient ucfc->pc_resync = 0; 373234046Sdavide ucfc->pc_globalctrl &= ~(1ULL << (ri + SELECTOFF(uncore_cputype))); 374206089Sfabient wrmsr(UC_GLOBAL_CTRL, ucfc->pc_globalctrl); 375206089Sfabient } while (ucfc->pc_resync != 0); 376206089Sfabient 377206089Sfabient PMCDBG(MDP,STO,1,"ucfctrl=%x(%x) globalctrl=%jx(%jx)", 378206089Sfabient ucfc->pc_ucfctrl, (uint32_t) rdmsr(UCF_CTRL), 379206089Sfabient ucfc->pc_globalctrl, rdmsr(UC_GLOBAL_CTRL)); 380206089Sfabient 381206089Sfabient return (0); 382206089Sfabient} 383206089Sfabient 384206089Sfabientstatic int 385206089Sfabientucf_write_pmc(int cpu, int ri, pmc_value_t v) 386206089Sfabient{ 387206089Sfabient struct uncore_cpu *cc; 388206089Sfabient struct pmc *pm; 389206089Sfabient 390206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 391206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 392206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 393206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 394206089Sfabient 395206089Sfabient cc = uncore_pcpu[cpu]; 396206089Sfabient pm = cc->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 397206089Sfabient 398206089Sfabient KASSERT(pm, 399206089Sfabient ("[uncore,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, ri)); 400206089Sfabient 401206089Sfabient if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 402206089Sfabient v = ucf_reload_count_to_perfctr_value(v); 403206089Sfabient 404206089Sfabient wrmsr(UCF_CTRL, 0); /* Turn off fixed counters */ 405206089Sfabient wrmsr(UCF_CTR0 + ri, v); 406206089Sfabient wrmsr(UCF_CTRL, cc->pc_ucfctrl); 407206089Sfabient 408206089Sfabient PMCDBG(MDP,WRI,1, "ucf-write cpu=%d ri=%d v=%jx ucfctrl=%jx ", 409206089Sfabient cpu, ri, v, (uintmax_t) rdmsr(UCF_CTRL)); 410206089Sfabient 411206089Sfabient return (0); 412206089Sfabient} 413206089Sfabient 414206089Sfabient 415206089Sfabientstatic void 416206089Sfabientucf_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth) 417206089Sfabient{ 418206089Sfabient struct pmc_classdep *pcd; 419206089Sfabient 420206089Sfabient KASSERT(md != NULL, ("[ucf,%d] md is NULL", __LINE__)); 421206089Sfabient 422206089Sfabient PMCDBG(MDP,INI,1, "%s", "ucf-initialize"); 423206089Sfabient 424206089Sfabient pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCF]; 425206089Sfabient 426206089Sfabient pcd->pcd_caps = UCF_PMC_CAPS; 427206089Sfabient pcd->pcd_class = PMC_CLASS_UCF; 428206089Sfabient pcd->pcd_num = npmc; 429206089Sfabient pcd->pcd_ri = md->pmd_npmc; 430206089Sfabient pcd->pcd_width = pmcwidth; 431206089Sfabient 432206089Sfabient pcd->pcd_allocate_pmc = ucf_allocate_pmc; 433206089Sfabient pcd->pcd_config_pmc = ucf_config_pmc; 434206089Sfabient pcd->pcd_describe = ucf_describe; 435206089Sfabient pcd->pcd_get_config = ucf_get_config; 436206089Sfabient pcd->pcd_get_msr = NULL; 437206089Sfabient pcd->pcd_pcpu_fini = uncore_pcpu_noop; 438206089Sfabient pcd->pcd_pcpu_init = uncore_pcpu_noop; 439206089Sfabient pcd->pcd_read_pmc = ucf_read_pmc; 440206089Sfabient pcd->pcd_release_pmc = ucf_release_pmc; 441206089Sfabient pcd->pcd_start_pmc = ucf_start_pmc; 442206089Sfabient pcd->pcd_stop_pmc = ucf_stop_pmc; 443206089Sfabient pcd->pcd_write_pmc = ucf_write_pmc; 444206089Sfabient 445206089Sfabient md->pmd_npmc += npmc; 446206089Sfabient} 447206089Sfabient 448206089Sfabient/* 449206089Sfabient * Intel programmable PMCs. 450206089Sfabient */ 451206089Sfabient 452206089Sfabient/* 453206089Sfabient * Event descriptor tables. 454206089Sfabient * 455206089Sfabient * For each event id, we track: 456206089Sfabient * 457206089Sfabient * 1. The CPUs that the event is valid for. 458206089Sfabient * 459206089Sfabient * 2. If the event uses a fixed UMASK, the value of the umask field. 460206089Sfabient * If the event doesn't use a fixed UMASK, a mask of legal bits 461206089Sfabient * to check against. 462206089Sfabient */ 463206089Sfabient 464206089Sfabientstruct ucp_event_descr { 465206089Sfabient enum pmc_event ucp_ev; 466206089Sfabient unsigned char ucp_evcode; 467206089Sfabient unsigned char ucp_umask; 468206089Sfabient unsigned char ucp_flags; 469206089Sfabient}; 470206089Sfabient 471206089Sfabient#define UCP_F_I7 (1 << 0) /* CPU: Core i7 */ 472206089Sfabient#define UCP_F_WM (1 << 1) /* CPU: Westmere */ 473234046Sdavide#define UCP_F_SB (1 << 2) /* CPU: Sandy Bridge */ 474249655Shiren#define UCP_F_HW (1 << 3) /* CPU: Haswell */ 475249655Shiren#define UCP_F_FM (1 << 4) /* Fixed mask */ 476206089Sfabient 477206089Sfabient#define UCP_F_ALLCPUS \ 478206089Sfabient (UCP_F_I7 | UCP_F_WM) 479206089Sfabient 480206089Sfabient#define UCP_F_CMASK 0xFF000000 481206089Sfabient 482206089Sfabientstatic struct ucp_event_descr ucp_events[] = { 483206089Sfabient#undef UCPDESCR 484206089Sfabient#define UCPDESCR(N,EV,UM,FLAGS) { \ 485206089Sfabient .ucp_ev = PMC_EV_UCP_EVENT_##N, \ 486206089Sfabient .ucp_evcode = (EV), \ 487206089Sfabient .ucp_umask = (UM), \ 488206089Sfabient .ucp_flags = (FLAGS) \ 489206089Sfabient } 490206089Sfabient 491206089Sfabient UCPDESCR(00H_01H, 0x00, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 492206089Sfabient UCPDESCR(00H_02H, 0x00, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 493206089Sfabient UCPDESCR(00H_04H, 0x00, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 494206089Sfabient 495206089Sfabient UCPDESCR(01H_01H, 0x01, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 496206089Sfabient UCPDESCR(01H_02H, 0x01, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 497206089Sfabient UCPDESCR(01H_04H, 0x01, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 498206089Sfabient 499206089Sfabient UCPDESCR(02H_01H, 0x02, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 500206089Sfabient UCPDESCR(03H_01H, 0x03, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 501206089Sfabient UCPDESCR(03H_02H, 0x03, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 502206089Sfabient UCPDESCR(03H_04H, 0x03, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 503206089Sfabient UCPDESCR(03H_08H, 0x03, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 504206089Sfabient UCPDESCR(03H_10H, 0x03, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 505206089Sfabient UCPDESCR(03H_20H, 0x03, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 506206089Sfabient UCPDESCR(03H_40H, 0x03, 0x40, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 507206089Sfabient 508206089Sfabient UCPDESCR(04H_01H, 0x04, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 509206089Sfabient UCPDESCR(04H_02H, 0x04, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 510206089Sfabient UCPDESCR(04H_04H, 0x04, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 511206089Sfabient UCPDESCR(04H_08H, 0x04, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 512206089Sfabient UCPDESCR(04H_10H, 0x04, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 513206089Sfabient 514206089Sfabient UCPDESCR(05H_01H, 0x05, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 515206089Sfabient UCPDESCR(05H_02H, 0x05, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 516206089Sfabient UCPDESCR(05H_04H, 0x05, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 517206089Sfabient 518206089Sfabient UCPDESCR(06H_01H, 0x06, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 519206089Sfabient UCPDESCR(06H_02H, 0x06, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 520206089Sfabient UCPDESCR(06H_04H, 0x06, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 521206089Sfabient UCPDESCR(06H_08H, 0x06, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 522206089Sfabient UCPDESCR(06H_10H, 0x06, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 523206089Sfabient UCPDESCR(06H_20H, 0x06, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 524206089Sfabient 525206089Sfabient UCPDESCR(07H_01H, 0x07, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 526206089Sfabient UCPDESCR(07H_02H, 0x07, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 527206089Sfabient UCPDESCR(07H_04H, 0x07, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 528206089Sfabient UCPDESCR(07H_08H, 0x07, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 529206089Sfabient UCPDESCR(07H_10H, 0x07, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 530206089Sfabient UCPDESCR(07H_20H, 0x07, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 531206089Sfabient UCPDESCR(07H_24H, 0x07, 0x24, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 532206089Sfabient 533206089Sfabient UCPDESCR(08H_01H, 0x08, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 534206089Sfabient UCPDESCR(08H_02H, 0x08, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 535206089Sfabient UCPDESCR(08H_04H, 0x08, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 536206089Sfabient UCPDESCR(08H_03H, 0x08, 0x03, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 537206089Sfabient 538206089Sfabient UCPDESCR(09H_01H, 0x09, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 539206089Sfabient UCPDESCR(09H_02H, 0x09, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 540206089Sfabient UCPDESCR(09H_04H, 0x09, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 541206089Sfabient UCPDESCR(09H_03H, 0x09, 0x03, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 542206089Sfabient 543206089Sfabient UCPDESCR(0AH_01H, 0x0A, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 544206089Sfabient UCPDESCR(0AH_02H, 0x0A, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 545206089Sfabient UCPDESCR(0AH_04H, 0x0A, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 546206089Sfabient UCPDESCR(0AH_08H, 0x0A, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 547206089Sfabient UCPDESCR(0AH_0FH, 0x0A, 0x0F, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 548206089Sfabient 549206089Sfabient UCPDESCR(0BH_01H, 0x0B, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 550206089Sfabient UCPDESCR(0BH_02H, 0x0B, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 551206089Sfabient UCPDESCR(0BH_04H, 0x0B, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 552206089Sfabient UCPDESCR(0BH_08H, 0x0B, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 553206089Sfabient UCPDESCR(0BH_10H, 0x0B, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 554206089Sfabient UCPDESCR(0BH_1FH, 0x0B, 0x1F, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 555206089Sfabient 556206089Sfabient UCPDESCR(0CH_01H, 0x0C, 0x01, UCP_F_FM | UCP_F_WM), 557206089Sfabient UCPDESCR(0CH_02H, 0x0C, 0x02, UCP_F_FM | UCP_F_WM), 558234041Sdavide UCPDESCR(0CH_04H_E, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 559234041Sdavide UCPDESCR(0CH_04H_F, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 560234041Sdavide UCPDESCR(0CH_04H_M, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 561234041Sdavide UCPDESCR(0CH_04H_S, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 562234041Sdavide UCPDESCR(0CH_08H_E, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 563234041Sdavide UCPDESCR(0CH_08H_F, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 564234041Sdavide UCPDESCR(0CH_08H_M, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 565234041Sdavide UCPDESCR(0CH_08H_S, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 566206089Sfabient 567206089Sfabient UCPDESCR(20H_01H, 0x20, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 568206089Sfabient UCPDESCR(20H_02H, 0x20, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 569206089Sfabient UCPDESCR(20H_04H, 0x20, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 570206089Sfabient UCPDESCR(20H_08H, 0x20, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 571206089Sfabient UCPDESCR(20H_10H, 0x20, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 572206089Sfabient UCPDESCR(20H_20H, 0x20, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 573206089Sfabient 574206089Sfabient UCPDESCR(21H_01H, 0x21, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 575206089Sfabient UCPDESCR(21H_02H, 0x21, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 576206089Sfabient UCPDESCR(21H_04H, 0x21, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 577206089Sfabient 578234046Sdavide UCPDESCR(22H_01H, 0x22, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM | 579249655Shiren UCP_F_SB | UCP_F_HW), 580234046Sdavide UCPDESCR(22H_02H, 0x22, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM | 581249655Shiren UCP_F_SB | UCP_F_HW), 582234046Sdavide UCPDESCR(22H_04H, 0x22, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM | 583249655Shiren UCP_F_SB | UCP_F_HW), 584249655Shiren UCPDESCR(22H_08H, 0x22, 0x08, UCP_F_FM | UCP_F_SB | UCP_F_HW), 585249655Shiren UCPDESCR(22H_10H, 0x22, 0x10, UCP_F_FM | UCP_F_HW), 586249655Shiren UCPDESCR(22H_20H, 0x22, 0x20, UCP_F_FM | UCP_F_SB | UCP_F_HW), 587249655Shiren UCPDESCR(22H_40H, 0x22, 0x40, UCP_F_FM | UCP_F_SB | UCP_F_HW), 588249655Shiren UCPDESCR(22H_80H, 0x22, 0x80, UCP_F_FM | UCP_F_SB | UCP_F_HW), 589206089Sfabient 590206089Sfabient UCPDESCR(23H_01H, 0x23, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 591206089Sfabient UCPDESCR(23H_02H, 0x23, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 592206089Sfabient UCPDESCR(23H_04H, 0x23, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 593206089Sfabient 594206089Sfabient UCPDESCR(24H_02H, 0x24, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 595206089Sfabient UCPDESCR(24H_04H, 0x24, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 596206089Sfabient 597206089Sfabient UCPDESCR(25H_01H, 0x25, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 598206089Sfabient UCPDESCR(25H_02H, 0x25, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 599206089Sfabient UCPDESCR(25H_04H, 0x25, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 600206089Sfabient 601206089Sfabient UCPDESCR(26H_01H, 0x26, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 602206089Sfabient 603206089Sfabient UCPDESCR(27H_01H, 0x27, 0x01, UCP_F_FM | UCP_F_I7), 604206089Sfabient UCPDESCR(27H_02H, 0x27, 0x02, UCP_F_FM | UCP_F_I7), 605206089Sfabient UCPDESCR(27H_04H, 0x27, 0x04, UCP_F_FM | UCP_F_I7), 606206089Sfabient UCPDESCR(27H_08H, 0x27, 0x08, UCP_F_FM | UCP_F_I7), 607206089Sfabient UCPDESCR(27H_10H, 0x27, 0x10, UCP_F_FM | UCP_F_I7), 608206089Sfabient UCPDESCR(27H_20H, 0x27, 0x20, UCP_F_FM | UCP_F_I7), 609206089Sfabient 610206089Sfabient UCPDESCR(28H_01H, 0x28, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 611206089Sfabient UCPDESCR(28H_02H, 0x28, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 612206089Sfabient UCPDESCR(28H_04H, 0x28, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 613206089Sfabient UCPDESCR(28H_08H, 0x28, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 614206089Sfabient UCPDESCR(28H_10H, 0x28, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 615206089Sfabient UCPDESCR(28H_20H, 0x28, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 616206089Sfabient 617206089Sfabient UCPDESCR(29H_01H, 0x29, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 618206089Sfabient UCPDESCR(29H_02H, 0x29, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 619206089Sfabient UCPDESCR(29H_04H, 0x29, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 620206089Sfabient UCPDESCR(29H_08H, 0x29, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 621206089Sfabient UCPDESCR(29H_10H, 0x29, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 622206089Sfabient UCPDESCR(29H_20H, 0x29, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 623206089Sfabient 624206089Sfabient UCPDESCR(2AH_01H, 0x2A, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 625206089Sfabient UCPDESCR(2AH_02H, 0x2A, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 626206089Sfabient UCPDESCR(2AH_04H, 0x2A, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 627206089Sfabient UCPDESCR(2AH_07H, 0x2A, 0x07, UCP_F_FM | UCP_F_WM), 628206089Sfabient 629206089Sfabient UCPDESCR(2BH_01H, 0x2B, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 630206089Sfabient UCPDESCR(2BH_02H, 0x2B, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 631206089Sfabient UCPDESCR(2BH_04H, 0x2B, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 632206089Sfabient UCPDESCR(2BH_07H, 0x2B, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 633206089Sfabient 634206089Sfabient UCPDESCR(2CH_01H, 0x2C, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 635206089Sfabient UCPDESCR(2CH_02H, 0x2C, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 636206089Sfabient UCPDESCR(2CH_04H, 0x2C, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 637206089Sfabient UCPDESCR(2CH_07H, 0x2C, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 638206089Sfabient 639206089Sfabient UCPDESCR(2DH_01H, 0x2D, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 640206089Sfabient UCPDESCR(2DH_02H, 0x2D, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 641206089Sfabient UCPDESCR(2DH_04H, 0x2D, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 642206089Sfabient UCPDESCR(2DH_07H, 0x2D, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 643206089Sfabient 644206089Sfabient UCPDESCR(2EH_01H, 0x2E, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 645206089Sfabient UCPDESCR(2EH_02H, 0x2E, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 646206089Sfabient UCPDESCR(2EH_04H, 0x2E, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 647206089Sfabient UCPDESCR(2EH_07H, 0x2E, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 648206089Sfabient 649206089Sfabient UCPDESCR(2FH_01H, 0x2F, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 650206089Sfabient UCPDESCR(2FH_02H, 0x2F, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 651206089Sfabient UCPDESCR(2FH_04H, 0x2F, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 652206089Sfabient UCPDESCR(2FH_07H, 0x2F, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 653206089Sfabient UCPDESCR(2FH_08H, 0x2F, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 654206089Sfabient UCPDESCR(2FH_10H, 0x2F, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 655206089Sfabient UCPDESCR(2FH_20H, 0x2F, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 656206089Sfabient UCPDESCR(2FH_38H, 0x2F, 0x38, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 657206089Sfabient 658206089Sfabient UCPDESCR(30H_01H, 0x30, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 659206089Sfabient UCPDESCR(30H_02H, 0x30, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 660206089Sfabient UCPDESCR(30H_04H, 0x30, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 661206089Sfabient UCPDESCR(30H_07H, 0x30, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 662206089Sfabient 663206089Sfabient UCPDESCR(31H_01H, 0x31, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 664206089Sfabient UCPDESCR(31H_02H, 0x31, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 665206089Sfabient UCPDESCR(31H_04H, 0x31, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 666206089Sfabient UCPDESCR(31H_07H, 0x31, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 667206089Sfabient 668206089Sfabient UCPDESCR(32H_01H, 0x32, 0x01, UCP_F_FM | UCP_F_WM), 669206089Sfabient UCPDESCR(32H_02H, 0x32, 0x02, UCP_F_FM | UCP_F_WM), 670206089Sfabient UCPDESCR(32H_04H, 0x32, 0x04, UCP_F_FM | UCP_F_WM), 671206089Sfabient UCPDESCR(32H_07H, 0x32, 0x07, UCP_F_FM | UCP_F_WM), 672206089Sfabient 673206089Sfabient UCPDESCR(33H_01H, 0x33, 0x01, UCP_F_FM | UCP_F_WM), 674206089Sfabient UCPDESCR(33H_02H, 0x33, 0x02, UCP_F_FM | UCP_F_WM), 675206089Sfabient UCPDESCR(33H_04H, 0x33, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 676206089Sfabient UCPDESCR(33H_07H, 0x33, 0x07, UCP_F_FM | UCP_F_WM), 677206089Sfabient 678249655Shiren UCPDESCR(34H_01H, 0x34, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 679249655Shiren UCP_F_HW), 680234046Sdavide UCPDESCR(34H_02H, 0x34, 0x02, UCP_F_FM | UCP_F_WM | UCP_F_SB), 681234046Sdavide UCPDESCR(34H_04H, 0x34, 0x04, UCP_F_FM | UCP_F_WM | UCP_F_SB), 682249655Shiren UCPDESCR(34H_06H, 0x34, 0x06, UCP_F_FM | UCP_F_HW), 683249655Shiren UCPDESCR(34H_08H, 0x34, 0x08, UCP_F_FM | UCP_F_WM | UCP_F_SB | 684249655Shiren UCP_F_HW), 685249655Shiren UCPDESCR(34H_10H, 0x34, 0x10, UCP_F_FM | UCP_F_WM | UCP_F_SB | 686249655Shiren UCP_F_HW), 687249655Shiren UCPDESCR(34H_20H, 0x34, 0x20, UCP_F_FM | UCP_F_WM | UCP_F_SB | 688249655Shiren UCP_F_HW), 689249655Shiren UCPDESCR(34H_40H, 0x34, 0x40, UCP_F_FM | UCP_F_SB | UCP_F_HW), 690249655Shiren UCPDESCR(34H_80H, 0x34, 0x80, UCP_F_FM | UCP_F_SB | UCP_F_HW), 691206089Sfabient 692206089Sfabient UCPDESCR(35H_01H, 0x35, 0x01, UCP_F_FM | UCP_F_WM), 693206089Sfabient UCPDESCR(35H_02H, 0x35, 0x02, UCP_F_FM | UCP_F_WM), 694206089Sfabient UCPDESCR(35H_04H, 0x35, 0x04, UCP_F_FM | UCP_F_WM), 695206089Sfabient 696206089Sfabient UCPDESCR(40H_01H, 0x40, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 697206089Sfabient UCPDESCR(40H_02H, 0x40, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 698206089Sfabient UCPDESCR(40H_04H, 0x40, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 699206089Sfabient UCPDESCR(40H_08H, 0x40, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 700206089Sfabient UCPDESCR(40H_10H, 0x40, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 701206089Sfabient UCPDESCR(40H_20H, 0x40, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 702206089Sfabient UCPDESCR(40H_07H, 0x40, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 703206089Sfabient UCPDESCR(40H_38H, 0x40, 0x38, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 704206089Sfabient 705206089Sfabient UCPDESCR(41H_01H, 0x41, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 706206089Sfabient UCPDESCR(41H_02H, 0x41, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 707206089Sfabient UCPDESCR(41H_04H, 0x41, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 708206089Sfabient UCPDESCR(41H_08H, 0x41, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 709206089Sfabient UCPDESCR(41H_10H, 0x41, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 710206089Sfabient UCPDESCR(41H_20H, 0x41, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 711206089Sfabient UCPDESCR(41H_07H, 0x41, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 712206089Sfabient UCPDESCR(41H_38H, 0x41, 0x38, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 713206089Sfabient 714206089Sfabient UCPDESCR(42H_01H, 0x42, 0x01, UCP_F_FM | UCP_F_WM), 715206089Sfabient UCPDESCR(42H_02H, 0x42, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 716206089Sfabient UCPDESCR(42H_04H, 0x42, 0x04, UCP_F_FM | UCP_F_WM), 717206089Sfabient UCPDESCR(42H_08H, 0x42, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 718206089Sfabient 719206089Sfabient UCPDESCR(43H_01H, 0x43, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 720206089Sfabient UCPDESCR(43H_02H, 0x43, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 721206089Sfabient 722206089Sfabient UCPDESCR(60H_01H, 0x60, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 723206089Sfabient UCPDESCR(60H_02H, 0x60, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 724206089Sfabient UCPDESCR(60H_04H, 0x60, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 725206089Sfabient 726206089Sfabient UCPDESCR(61H_01H, 0x61, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 727206089Sfabient UCPDESCR(61H_02H, 0x61, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 728206089Sfabient UCPDESCR(61H_04H, 0x61, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 729206089Sfabient 730206089Sfabient UCPDESCR(62H_01H, 0x62, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 731206089Sfabient UCPDESCR(62H_02H, 0x62, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 732206089Sfabient UCPDESCR(62H_04H, 0x62, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 733206089Sfabient 734206089Sfabient UCPDESCR(63H_01H, 0x63, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 735206089Sfabient UCPDESCR(63H_02H, 0x63, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 736206089Sfabient UCPDESCR(63H_04H, 0x63, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 737206089Sfabient UCPDESCR(63H_08H, 0x63, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 738206089Sfabient UCPDESCR(63H_10H, 0x63, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 739206089Sfabient UCPDESCR(63H_20H, 0x63, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 740206089Sfabient 741206089Sfabient UCPDESCR(64H_01H, 0x64, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 742206089Sfabient UCPDESCR(64H_02H, 0x64, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 743206089Sfabient UCPDESCR(64H_04H, 0x64, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 744206089Sfabient UCPDESCR(64H_08H, 0x64, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 745206089Sfabient UCPDESCR(64H_10H, 0x64, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 746206089Sfabient UCPDESCR(64H_20H, 0x64, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 747206089Sfabient 748206089Sfabient UCPDESCR(65H_01H, 0x65, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 749206089Sfabient UCPDESCR(65H_02H, 0x65, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 750206089Sfabient UCPDESCR(65H_04H, 0x65, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 751206089Sfabient 752206089Sfabient UCPDESCR(66H_01H, 0x66, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 753206089Sfabient UCPDESCR(66H_02H, 0x66, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 754206089Sfabient UCPDESCR(66H_04H, 0x66, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 755206089Sfabient 756206089Sfabient UCPDESCR(67H_01H, 0x67, 0x01, UCP_F_FM | UCP_F_WM), 757250038Shiren 758249655Shiren UCPDESCR(80H_01H, 0x80, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 759249655Shiren UCP_F_HW), 760206089Sfabient UCPDESCR(80H_02H, 0x80, 0x02, UCP_F_FM | UCP_F_WM), 761206089Sfabient UCPDESCR(80H_04H, 0x80, 0x04, UCP_F_FM | UCP_F_WM), 762206089Sfabient UCPDESCR(80H_08H, 0x80, 0x08, UCP_F_FM | UCP_F_WM), 763250038Shiren 764249655Shiren UCPDESCR(81H_01H, 0x81, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 765249655Shiren UCP_F_HW), 766206089Sfabient UCPDESCR(81H_02H, 0x81, 0x02, UCP_F_FM | UCP_F_WM), 767206089Sfabient UCPDESCR(81H_04H, 0x81, 0x04, UCP_F_FM | UCP_F_WM), 768206089Sfabient UCPDESCR(81H_08H, 0x81, 0x08, UCP_F_FM | UCP_F_WM), 769249655Shiren UCPDESCR(81H_20H, 0x81, 0x20, UCP_F_FM | UCP_F_SB | UCP_F_HW), 770249655Shiren UCPDESCR(81H_80H, 0x81, 0x80, UCP_F_FM | UCP_F_SB | UCP_F_HW), 771234046Sdavide 772206089Sfabient UCPDESCR(82H_01H, 0x82, 0x01, UCP_F_FM | UCP_F_WM), 773250038Shiren 774249655Shiren UCPDESCR(83H_01H, 0x83, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 775249655Shiren UCP_F_HW), 776206089Sfabient UCPDESCR(83H_02H, 0x83, 0x02, UCP_F_FM | UCP_F_WM), 777206089Sfabient UCPDESCR(83H_04H, 0x83, 0x04, UCP_F_FM | UCP_F_WM), 778206089Sfabient UCPDESCR(83H_08H, 0x83, 0x08, UCP_F_FM | UCP_F_WM), 779250038Shiren 780249655Shiren UCPDESCR(84H_01H, 0x84, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 781249655Shiren UCP_F_HW), 782206089Sfabient UCPDESCR(84H_02H, 0x84, 0x02, UCP_F_FM | UCP_F_WM), 783206089Sfabient UCPDESCR(84H_04H, 0x84, 0x04, UCP_F_FM | UCP_F_WM), 784206089Sfabient UCPDESCR(84H_08H, 0x84, 0x08, UCP_F_FM | UCP_F_WM), 785206089Sfabient UCPDESCR(85H_02H, 0x85, 0x02, UCP_F_FM | UCP_F_WM), 786206089Sfabient UCPDESCR(86H_01H, 0x86, 0x01, UCP_F_FM | UCP_F_WM) 787206089Sfabient}; 788206089Sfabient 789206089Sfabientstatic const int nucp_events = sizeof(ucp_events) / sizeof(ucp_events[0]); 790206089Sfabient 791206089Sfabientstatic pmc_value_t 792206089Sfabientucp_perfctr_value_to_reload_count(pmc_value_t v) 793206089Sfabient{ 794206089Sfabient v &= (1ULL << uncore_ucp_width) - 1; 795206089Sfabient return (1ULL << uncore_ucp_width) - v; 796206089Sfabient} 797206089Sfabient 798206089Sfabientstatic pmc_value_t 799206089Sfabientucp_reload_count_to_perfctr_value(pmc_value_t rlc) 800206089Sfabient{ 801206089Sfabient return (1ULL << uncore_ucp_width) - rlc; 802206089Sfabient} 803206089Sfabient 804249655Shiren/* 805249655Shiren * Counter specific event information for Sandybridge and Haswell 806249655Shiren */ 807206089Sfabientstatic int 808249655Shirenucp_event_sb_hw_ok_on_counter(enum pmc_event pe, int ri) 809234046Sdavide{ 810234046Sdavide uint32_t mask; 811250038Shiren 812234046Sdavide switch (pe) { 813250038Shiren /* 814234046Sdavide * Events valid only on counter 0. 815234046Sdavide */ 816234046Sdavide case PMC_EV_UCP_EVENT_80H_01H: 817234046Sdavide case PMC_EV_UCP_EVENT_83H_01H: 818234046Sdavide mask = (1 << 0); 819234046Sdavide break; 820250038Shiren 821234046Sdavide default: 822234046Sdavide mask = ~0; /* Any row index is ok. */ 823234046Sdavide } 824250038Shiren 825234046Sdavide return (mask & (1 << ri)); 826234046Sdavide} 827234046Sdavide 828234046Sdavidestatic int 829206089Sfabientucp_allocate_pmc(int cpu, int ri, struct pmc *pm, 830206089Sfabient const struct pmc_op_pmcallocate *a) 831206089Sfabient{ 832206089Sfabient int n; 833206089Sfabient enum pmc_event ev; 834206089Sfabient struct ucp_event_descr *ie; 835206089Sfabient uint32_t caps, config, cpuflag, evsel; 836206089Sfabient 837206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 838206089Sfabient ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 839206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 840206089Sfabient ("[uncore,%d] illegal row-index value %d", __LINE__, ri)); 841206089Sfabient 842206089Sfabient /* check requested capabilities */ 843206089Sfabient caps = a->pm_caps; 844206089Sfabient if ((UCP_PMC_CAPS & caps) != caps) 845206089Sfabient return (EPERM); 846206089Sfabient 847206089Sfabient ev = pm->pm_event; 848206089Sfabient 849234046Sdavide switch (uncore_cputype) { 850249655Shiren case PMC_CPU_INTEL_HASWELL: 851234046Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 852249655Shiren if (ucp_event_sb_hw_ok_on_counter(ev, ri) == 0) 853234046Sdavide return (EINVAL); 854234046Sdavide break; 855234046Sdavide default: 856234046Sdavide break; 857234046Sdavide } 858234046Sdavide 859250038Shiren 860206089Sfabient /* 861206089Sfabient * Look for an event descriptor with matching CPU and event id 862206089Sfabient * fields. 863206089Sfabient */ 864206089Sfabient 865206089Sfabient switch (uncore_cputype) { 866206089Sfabient case PMC_CPU_INTEL_COREI7: 867206089Sfabient cpuflag = UCP_F_I7; 868206089Sfabient break; 869249655Shiren case PMC_CPU_INTEL_HASWELL: 870249655Shiren cpuflag = UCP_F_HW; 871249655Shiren break; 872234046Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 873234046Sdavide cpuflag = UCP_F_SB; 874234046Sdavide break; 875206089Sfabient case PMC_CPU_INTEL_WESTMERE: 876206089Sfabient cpuflag = UCP_F_WM; 877206089Sfabient break; 878206089Sfabient default: 879206089Sfabient return (EINVAL); 880206089Sfabient } 881206089Sfabient 882206089Sfabient for (n = 0, ie = ucp_events; n < nucp_events; n++, ie++) 883206089Sfabient if (ie->ucp_ev == ev && ie->ucp_flags & cpuflag) 884206089Sfabient break; 885206089Sfabient 886206089Sfabient if (n == nucp_events) 887206089Sfabient return (EINVAL); 888206089Sfabient 889206089Sfabient /* 890206089Sfabient * A matching event descriptor has been found, so start 891206089Sfabient * assembling the contents of the event select register. 892206089Sfabient */ 893206089Sfabient evsel = ie->ucp_evcode | UCP_EN; 894206089Sfabient 895206089Sfabient config = a->pm_md.pm_ucp.pm_ucp_config & ~UCP_F_CMASK; 896206089Sfabient 897206089Sfabient /* 898206089Sfabient * If the event uses a fixed umask value, reject any umask 899206089Sfabient * bits set by the user. 900206089Sfabient */ 901206089Sfabient if (ie->ucp_flags & UCP_F_FM) { 902206089Sfabient 903206089Sfabient if (UCP_UMASK(config) != 0) 904206089Sfabient return (EINVAL); 905206089Sfabient 906206089Sfabient evsel |= (ie->ucp_umask << 8); 907206089Sfabient 908206089Sfabient } else 909206089Sfabient return (EINVAL); 910206089Sfabient 911206089Sfabient if (caps & PMC_CAP_THRESHOLD) 912206089Sfabient evsel |= (a->pm_md.pm_ucp.pm_ucp_config & UCP_F_CMASK); 913206089Sfabient if (caps & PMC_CAP_EDGE) 914206089Sfabient evsel |= UCP_EDGE; 915206089Sfabient if (caps & PMC_CAP_INVERT) 916206089Sfabient evsel |= UCP_INV; 917206089Sfabient 918206089Sfabient pm->pm_md.pm_ucp.pm_ucp_evsel = evsel; 919206089Sfabient 920206089Sfabient return (0); 921206089Sfabient} 922206089Sfabient 923206089Sfabientstatic int 924206089Sfabientucp_config_pmc(int cpu, int ri, struct pmc *pm) 925206089Sfabient{ 926206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 927206089Sfabient ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 928206089Sfabient 929206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 930206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 931206089Sfabient 932206089Sfabient PMCDBG(MDP,CFG,1, "ucp-config cpu=%d ri=%d pm=%p", cpu, ri, pm); 933206089Sfabient 934206089Sfabient KASSERT(uncore_pcpu[cpu] != NULL, ("[uncore,%d] null per-cpu %d", __LINE__, 935206089Sfabient cpu)); 936206089Sfabient 937206089Sfabient uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc = pm; 938206089Sfabient 939206089Sfabient return (0); 940206089Sfabient} 941206089Sfabient 942206089Sfabientstatic int 943206089Sfabientucp_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 944206089Sfabient{ 945206089Sfabient int error; 946206089Sfabient struct pmc_hw *phw; 947206089Sfabient char ucp_name[PMC_NAME_MAX]; 948206089Sfabient 949206089Sfabient phw = &uncore_pcpu[cpu]->pc_uncorepmcs[ri]; 950206089Sfabient 951206089Sfabient (void) snprintf(ucp_name, sizeof(ucp_name), "UCP-%d", ri); 952206089Sfabient if ((error = copystr(ucp_name, pi->pm_name, PMC_NAME_MAX, 953206089Sfabient NULL)) != 0) 954206089Sfabient return (error); 955206089Sfabient 956206089Sfabient pi->pm_class = PMC_CLASS_UCP; 957206089Sfabient 958206089Sfabient if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 959206089Sfabient pi->pm_enabled = TRUE; 960206089Sfabient *ppmc = phw->phw_pmc; 961206089Sfabient } else { 962206089Sfabient pi->pm_enabled = FALSE; 963206089Sfabient *ppmc = NULL; 964206089Sfabient } 965206089Sfabient 966206089Sfabient return (0); 967206089Sfabient} 968206089Sfabient 969206089Sfabientstatic int 970206089Sfabientucp_get_config(int cpu, int ri, struct pmc **ppm) 971206089Sfabient{ 972206089Sfabient *ppm = uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc; 973206089Sfabient 974206089Sfabient return (0); 975206089Sfabient} 976206089Sfabient 977206089Sfabientstatic int 978206089Sfabientucp_read_pmc(int cpu, int ri, pmc_value_t *v) 979206089Sfabient{ 980206089Sfabient struct pmc *pm; 981206089Sfabient pmc_value_t tmp; 982206089Sfabient 983206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 984206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 985206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 986206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 987206089Sfabient 988206089Sfabient pm = uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc; 989206089Sfabient 990206089Sfabient KASSERT(pm, 991206089Sfabient ("[uncore,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, 992206089Sfabient ri)); 993206089Sfabient 994206089Sfabient tmp = rdmsr(UCP_PMC0 + ri); 995206089Sfabient if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 996206089Sfabient *v = ucp_perfctr_value_to_reload_count(tmp); 997206089Sfabient else 998206089Sfabient *v = tmp; 999206089Sfabient 1000206089Sfabient PMCDBG(MDP,REA,1, "ucp-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri, 1001206089Sfabient ri, *v); 1002206089Sfabient 1003206089Sfabient return (0); 1004206089Sfabient} 1005206089Sfabient 1006206089Sfabientstatic int 1007206089Sfabientucp_release_pmc(int cpu, int ri, struct pmc *pm) 1008206089Sfabient{ 1009206089Sfabient (void) pm; 1010206089Sfabient 1011206089Sfabient PMCDBG(MDP,REL,1, "ucp-release cpu=%d ri=%d pm=%p", cpu, ri, 1012206089Sfabient pm); 1013206089Sfabient 1014206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1015206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 1016206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1017206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 1018206089Sfabient 1019206089Sfabient KASSERT(uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc 1020206089Sfabient == NULL, ("[uncore,%d] PHW pmc non-NULL", __LINE__)); 1021206089Sfabient 1022206089Sfabient return (0); 1023206089Sfabient} 1024206089Sfabient 1025206089Sfabientstatic int 1026206089Sfabientucp_start_pmc(int cpu, int ri) 1027206089Sfabient{ 1028206089Sfabient struct pmc *pm; 1029206089Sfabient uint32_t evsel; 1030206089Sfabient struct uncore_cpu *cc; 1031206089Sfabient 1032206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1033206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 1034206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1035206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 1036206089Sfabient 1037206089Sfabient cc = uncore_pcpu[cpu]; 1038206089Sfabient pm = cc->pc_uncorepmcs[ri].phw_pmc; 1039206089Sfabient 1040206089Sfabient KASSERT(pm, 1041206089Sfabient ("[uncore,%d] starting cpu%d,ri%d with no pmc configured", 1042206089Sfabient __LINE__, cpu, ri)); 1043206089Sfabient 1044206089Sfabient PMCDBG(MDP,STA,1, "ucp-start cpu=%d ri=%d", cpu, ri); 1045206089Sfabient 1046206089Sfabient evsel = pm->pm_md.pm_ucp.pm_ucp_evsel; 1047206089Sfabient 1048250038Shiren PMCDBG(MDP,STA,2, 1049250038Shiren "ucp-start/2 cpu=%d ri=%d evselmsr=0x%x evsel=0x%x", 1050250038Shiren cpu, ri, SELECTSEL(uncore_cputype) + ri, evsel); 1051206089Sfabient 1052234041Sdavide /* Event specific configuration. */ 1053234041Sdavide switch (pm->pm_event) { 1054234041Sdavide case PMC_EV_UCP_EVENT_0CH_04H_E: 1055237444Sgnn case PMC_EV_UCP_EVENT_0CH_08H_E: 1056234041Sdavide wrmsr(MSR_GQ_SNOOP_MESF,0x2); 1057234041Sdavide break; 1058234041Sdavide case PMC_EV_UCP_EVENT_0CH_04H_F: 1059237444Sgnn case PMC_EV_UCP_EVENT_0CH_08H_F: 1060234041Sdavide wrmsr(MSR_GQ_SNOOP_MESF,0x8); 1061234041Sdavide break; 1062234041Sdavide case PMC_EV_UCP_EVENT_0CH_04H_M: 1063237444Sgnn case PMC_EV_UCP_EVENT_0CH_08H_M: 1064234041Sdavide wrmsr(MSR_GQ_SNOOP_MESF,0x1); 1065234041Sdavide break; 1066234041Sdavide case PMC_EV_UCP_EVENT_0CH_04H_S: 1067234041Sdavide case PMC_EV_UCP_EVENT_0CH_08H_S: 1068234041Sdavide wrmsr(MSR_GQ_SNOOP_MESF,0x4); 1069234041Sdavide break; 1070250038Shiren default: 1071234041Sdavide break; 1072234041Sdavide } 1073234041Sdavide 1074234046Sdavide wrmsr(SELECTSEL(uncore_cputype) + ri, evsel); 1075250038Shiren 1076206089Sfabient do { 1077206089Sfabient cc->pc_resync = 0; 1078206089Sfabient cc->pc_globalctrl |= (1ULL << ri); 1079206089Sfabient wrmsr(UC_GLOBAL_CTRL, cc->pc_globalctrl); 1080206089Sfabient } while (cc->pc_resync != 0); 1081206089Sfabient 1082206089Sfabient return (0); 1083206089Sfabient} 1084206089Sfabient 1085206089Sfabientstatic int 1086206089Sfabientucp_stop_pmc(int cpu, int ri) 1087206089Sfabient{ 1088206089Sfabient struct pmc *pm; 1089206089Sfabient struct uncore_cpu *cc; 1090206089Sfabient 1091206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1092206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 1093206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1094206089Sfabient ("[uncore,%d] illegal row index %d", __LINE__, ri)); 1095206089Sfabient 1096206089Sfabient cc = uncore_pcpu[cpu]; 1097206089Sfabient pm = cc->pc_uncorepmcs[ri].phw_pmc; 1098206089Sfabient 1099206089Sfabient KASSERT(pm, 1100206089Sfabient ("[uncore,%d] cpu%d ri%d no configured PMC to stop", __LINE__, 1101206089Sfabient cpu, ri)); 1102206089Sfabient 1103206089Sfabient PMCDBG(MDP,STO,1, "ucp-stop cpu=%d ri=%d", cpu, ri); 1104206089Sfabient 1105234046Sdavide /* stop hw. */ 1106234046Sdavide wrmsr(SELECTSEL(uncore_cputype) + ri, 0); 1107206089Sfabient 1108206089Sfabient do { 1109206089Sfabient cc->pc_resync = 0; 1110206089Sfabient cc->pc_globalctrl &= ~(1ULL << ri); 1111206089Sfabient wrmsr(UC_GLOBAL_CTRL, cc->pc_globalctrl); 1112206089Sfabient } while (cc->pc_resync != 0); 1113206089Sfabient 1114206089Sfabient return (0); 1115206089Sfabient} 1116206089Sfabient 1117206089Sfabientstatic int 1118206089Sfabientucp_write_pmc(int cpu, int ri, pmc_value_t v) 1119206089Sfabient{ 1120206089Sfabient struct pmc *pm; 1121206089Sfabient struct uncore_cpu *cc; 1122206089Sfabient 1123206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1124206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 1125206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1126206089Sfabient ("[uncore,%d] illegal row index %d", __LINE__, ri)); 1127206089Sfabient 1128206089Sfabient cc = uncore_pcpu[cpu]; 1129206089Sfabient pm = cc->pc_uncorepmcs[ri].phw_pmc; 1130206089Sfabient 1131206089Sfabient KASSERT(pm, 1132206089Sfabient ("[uncore,%d] cpu%d ri%d no configured PMC to stop", __LINE__, 1133206089Sfabient cpu, ri)); 1134206089Sfabient 1135206089Sfabient PMCDBG(MDP,WRI,1, "ucp-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri, 1136206089Sfabient UCP_PMC0 + ri, v); 1137206089Sfabient 1138206089Sfabient if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 1139206089Sfabient v = ucp_reload_count_to_perfctr_value(v); 1140206089Sfabient 1141206089Sfabient /* 1142206089Sfabient * Write the new value to the counter. The counter will be in 1143206089Sfabient * a stopped state when the pcd_write() entry point is called. 1144206089Sfabient */ 1145206089Sfabient 1146206089Sfabient wrmsr(UCP_PMC0 + ri, v); 1147206089Sfabient 1148206089Sfabient return (0); 1149206089Sfabient} 1150206089Sfabient 1151206089Sfabient 1152206089Sfabientstatic void 1153206089Sfabientucp_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth) 1154206089Sfabient{ 1155206089Sfabient struct pmc_classdep *pcd; 1156206089Sfabient 1157206089Sfabient KASSERT(md != NULL, ("[ucp,%d] md is NULL", __LINE__)); 1158206089Sfabient 1159206089Sfabient PMCDBG(MDP,INI,1, "%s", "ucp-initialize"); 1160206089Sfabient 1161206089Sfabient pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP]; 1162206089Sfabient 1163206089Sfabient pcd->pcd_caps = UCP_PMC_CAPS; 1164206089Sfabient pcd->pcd_class = PMC_CLASS_UCP; 1165206089Sfabient pcd->pcd_num = npmc; 1166206089Sfabient pcd->pcd_ri = md->pmd_npmc; 1167206089Sfabient pcd->pcd_width = pmcwidth; 1168206089Sfabient 1169206089Sfabient pcd->pcd_allocate_pmc = ucp_allocate_pmc; 1170206089Sfabient pcd->pcd_config_pmc = ucp_config_pmc; 1171206089Sfabient pcd->pcd_describe = ucp_describe; 1172206089Sfabient pcd->pcd_get_config = ucp_get_config; 1173206089Sfabient pcd->pcd_get_msr = NULL; 1174206089Sfabient pcd->pcd_pcpu_fini = uncore_pcpu_fini; 1175206089Sfabient pcd->pcd_pcpu_init = uncore_pcpu_init; 1176206089Sfabient pcd->pcd_read_pmc = ucp_read_pmc; 1177206089Sfabient pcd->pcd_release_pmc = ucp_release_pmc; 1178206089Sfabient pcd->pcd_start_pmc = ucp_start_pmc; 1179206089Sfabient pcd->pcd_stop_pmc = ucp_stop_pmc; 1180206089Sfabient pcd->pcd_write_pmc = ucp_write_pmc; 1181206089Sfabient 1182206089Sfabient md->pmd_npmc += npmc; 1183206089Sfabient} 1184206089Sfabient 1185206089Sfabientint 1186206089Sfabientpmc_uncore_initialize(struct pmc_mdep *md, int maxcpu) 1187206089Sfabient{ 1188206089Sfabient uncore_cputype = md->pmd_cputype; 1189206089Sfabient uncore_pmcmask = 0; 1190206089Sfabient 1191206089Sfabient /* 1192206089Sfabient * Initialize programmable counters. 1193206089Sfabient */ 1194206089Sfabient 1195206089Sfabient uncore_ucp_npmc = 8; 1196206089Sfabient uncore_ucp_width = 48; 1197206089Sfabient 1198206089Sfabient uncore_pmcmask |= ((1ULL << uncore_ucp_npmc) - 1); 1199206089Sfabient 1200206089Sfabient ucp_initialize(md, maxcpu, uncore_ucp_npmc, uncore_ucp_width); 1201206089Sfabient 1202206089Sfabient /* 1203206089Sfabient * Initialize fixed function counters, if present. 1204206089Sfabient */ 1205206089Sfabient uncore_ucf_ri = uncore_ucp_npmc; 1206206089Sfabient uncore_ucf_npmc = 1; 1207206089Sfabient uncore_ucf_width = 48; 1208206089Sfabient 1209206089Sfabient ucf_initialize(md, maxcpu, uncore_ucf_npmc, uncore_ucf_width); 1210234046Sdavide uncore_pmcmask |= ((1ULL << uncore_ucf_npmc) - 1) << SELECTOFF(uncore_cputype); 1211206089Sfabient 1212206089Sfabient PMCDBG(MDP,INI,1,"uncore-init pmcmask=0x%jx ucfri=%d", uncore_pmcmask, 1213206089Sfabient uncore_ucf_ri); 1214206089Sfabient 1215206089Sfabient uncore_pcpu = malloc(sizeof(struct uncore_cpu **) * maxcpu, M_PMC, 1216206089Sfabient M_ZERO | M_WAITOK); 1217206089Sfabient 1218206089Sfabient return (0); 1219206089Sfabient} 1220206089Sfabient 1221206089Sfabientvoid 1222206089Sfabientpmc_uncore_finalize(struct pmc_mdep *md) 1223206089Sfabient{ 1224206089Sfabient PMCDBG(MDP,INI,1, "%s", "uncore-finalize"); 1225206089Sfabient 1226206089Sfabient free(uncore_pcpu, M_PMC); 1227206089Sfabient uncore_pcpu = NULL; 1228206089Sfabient} 1229