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> 41280455Srrs#if (__FreeBSD_version >= 1100000) 42280455Srrs#include <x86/apicvar.h> 43280455Srrs#else 44206089Sfabient#include <machine/apicvar.h> 45280455Srrs#endif 46206089Sfabient#include <machine/cpu.h> 47206089Sfabient#include <machine/cpufunc.h> 48206089Sfabient#include <machine/specialreg.h> 49206089Sfabient 50206089Sfabient#define UCF_PMC_CAPS \ 51206089Sfabient (PMC_CAP_READ | PMC_CAP_WRITE) 52206089Sfabient 53206089Sfabient#define UCP_PMC_CAPS \ 54206089Sfabient (PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE | \ 55206089Sfabient PMC_CAP_INVERT | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE) 56206089Sfabient 57232366Sdavide#define SELECTSEL(x) \ 58248842Ssbruno (((x) == PMC_CPU_INTEL_SANDYBRIDGE || (x) == PMC_CPU_INTEL_HASWELL) ? \ 59248842Ssbruno UCP_CB0_EVSEL0 : UCP_EVSEL0) 60232366Sdavide 61232366Sdavide#define SELECTOFF(x) \ 62248842Ssbruno (((x) == PMC_CPU_INTEL_SANDYBRIDGE || (x) == PMC_CPU_INTEL_HASWELL) ? \ 63248842Ssbruno UCF_OFFSET_SB : UCF_OFFSET) 64232366Sdavide 65206089Sfabientstatic enum pmc_cputype uncore_cputype; 66206089Sfabient 67206089Sfabientstruct uncore_cpu { 68206089Sfabient volatile uint32_t pc_resync; 69206089Sfabient volatile uint32_t pc_ucfctrl; /* Fixed function control. */ 70206089Sfabient volatile uint64_t pc_globalctrl; /* Global control register. */ 71206089Sfabient struct pmc_hw pc_uncorepmcs[]; 72206089Sfabient}; 73206089Sfabient 74206089Sfabientstatic struct uncore_cpu **uncore_pcpu; 75206089Sfabient 76206089Sfabientstatic uint64_t uncore_pmcmask; 77206089Sfabient 78206089Sfabientstatic int uncore_ucf_ri; /* relative index of fixed counters */ 79206089Sfabientstatic int uncore_ucf_width; 80206089Sfabientstatic int uncore_ucf_npmc; 81206089Sfabient 82206089Sfabientstatic int uncore_ucp_width; 83206089Sfabientstatic int uncore_ucp_npmc; 84206089Sfabient 85206089Sfabientstatic int 86206089Sfabientuncore_pcpu_noop(struct pmc_mdep *md, int cpu) 87206089Sfabient{ 88206089Sfabient (void) md; 89206089Sfabient (void) cpu; 90206089Sfabient return (0); 91206089Sfabient} 92206089Sfabient 93206089Sfabientstatic int 94206089Sfabientuncore_pcpu_init(struct pmc_mdep *md, int cpu) 95206089Sfabient{ 96206089Sfabient struct pmc_cpu *pc; 97206089Sfabient struct uncore_cpu *cc; 98206089Sfabient struct pmc_hw *phw; 99206089Sfabient int uncore_ri, n, npmc; 100206089Sfabient 101206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 102206089Sfabient ("[ucf,%d] insane cpu number %d", __LINE__, cpu)); 103206089Sfabient 104283884Sjhb PMCDBG1(MDP,INI,1,"uncore-init cpu=%d", cpu); 105206089Sfabient 106206089Sfabient uncore_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_ri; 107206089Sfabient npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_num; 108206089Sfabient npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCF].pcd_num; 109206089Sfabient 110206089Sfabient cc = malloc(sizeof(struct uncore_cpu) + npmc * sizeof(struct pmc_hw), 111206089Sfabient M_PMC, M_WAITOK | M_ZERO); 112206089Sfabient 113206089Sfabient uncore_pcpu[cpu] = cc; 114206089Sfabient pc = pmc_pcpu[cpu]; 115206089Sfabient 116206089Sfabient KASSERT(pc != NULL && cc != NULL, 117206089Sfabient ("[uncore,%d] NULL per-cpu structures cpu=%d", __LINE__, cpu)); 118206089Sfabient 119206089Sfabient for (n = 0, phw = cc->pc_uncorepmcs; n < npmc; n++, phw++) { 120206089Sfabient phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | 121206089Sfabient PMC_PHW_CPU_TO_STATE(cpu) | 122206089Sfabient PMC_PHW_INDEX_TO_STATE(n + uncore_ri); 123206089Sfabient phw->phw_pmc = NULL; 124206089Sfabient pc->pc_hwpmcs[n + uncore_ri] = phw; 125206089Sfabient } 126206089Sfabient 127206089Sfabient return (0); 128206089Sfabient} 129206089Sfabient 130206089Sfabientstatic int 131206089Sfabientuncore_pcpu_fini(struct pmc_mdep *md, int cpu) 132206089Sfabient{ 133206089Sfabient int uncore_ri, n, npmc; 134206089Sfabient struct pmc_cpu *pc; 135206089Sfabient struct uncore_cpu *cc; 136206089Sfabient 137206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 138206089Sfabient ("[uncore,%d] insane cpu number (%d)", __LINE__, cpu)); 139206089Sfabient 140283884Sjhb PMCDBG1(MDP,INI,1,"uncore-pcpu-fini cpu=%d", cpu); 141206089Sfabient 142206089Sfabient if ((cc = uncore_pcpu[cpu]) == NULL) 143206089Sfabient return (0); 144206089Sfabient 145206089Sfabient uncore_pcpu[cpu] = NULL; 146206089Sfabient 147206089Sfabient pc = pmc_pcpu[cpu]; 148206089Sfabient 149206089Sfabient KASSERT(pc != NULL, ("[uncore,%d] NULL per-cpu %d state", __LINE__, 150206089Sfabient cpu)); 151206089Sfabient 152206089Sfabient npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_num; 153206089Sfabient uncore_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_ri; 154206089Sfabient 155232366Sdavide for (n = 0; n < npmc; n++) 156232366Sdavide wrmsr(SELECTSEL(uncore_cputype) + n, 0); 157206089Sfabient 158206089Sfabient wrmsr(UCF_CTRL, 0); 159206089Sfabient npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCF].pcd_num; 160206089Sfabient 161206089Sfabient for (n = 0; n < npmc; n++) 162206089Sfabient pc->pc_hwpmcs[n + uncore_ri] = NULL; 163206089Sfabient 164206089Sfabient free(cc, M_PMC); 165206089Sfabient 166206089Sfabient return (0); 167206089Sfabient} 168206089Sfabient 169206089Sfabient/* 170206089Sfabient * Fixed function counters. 171206089Sfabient */ 172206089Sfabient 173206089Sfabientstatic pmc_value_t 174206089Sfabientucf_perfctr_value_to_reload_count(pmc_value_t v) 175206089Sfabient{ 176206089Sfabient v &= (1ULL << uncore_ucf_width) - 1; 177206089Sfabient return (1ULL << uncore_ucf_width) - v; 178206089Sfabient} 179206089Sfabient 180206089Sfabientstatic pmc_value_t 181206089Sfabientucf_reload_count_to_perfctr_value(pmc_value_t rlc) 182206089Sfabient{ 183206089Sfabient return (1ULL << uncore_ucf_width) - rlc; 184206089Sfabient} 185206089Sfabient 186206089Sfabientstatic int 187206089Sfabientucf_allocate_pmc(int cpu, int ri, struct pmc *pm, 188206089Sfabient const struct pmc_op_pmcallocate *a) 189206089Sfabient{ 190206089Sfabient enum pmc_event ev; 191206089Sfabient uint32_t caps, flags; 192206089Sfabient 193206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 194206089Sfabient ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 195206089Sfabient 196283884Sjhb PMCDBG2(MDP,ALL,1, "ucf-allocate ri=%d reqcaps=0x%x", ri, pm->pm_caps); 197206089Sfabient 198206089Sfabient if (ri < 0 || ri > uncore_ucf_npmc) 199206089Sfabient return (EINVAL); 200206089Sfabient 201206089Sfabient caps = a->pm_caps; 202206089Sfabient 203206089Sfabient if (a->pm_class != PMC_CLASS_UCF || 204206089Sfabient (caps & UCF_PMC_CAPS) != caps) 205206089Sfabient return (EINVAL); 206206089Sfabient 207206089Sfabient ev = pm->pm_event; 208206089Sfabient if (ev < PMC_EV_UCF_FIRST || ev > PMC_EV_UCF_LAST) 209206089Sfabient return (EINVAL); 210206089Sfabient 211206089Sfabient flags = UCF_EN; 212206089Sfabient 213206089Sfabient pm->pm_md.pm_ucf.pm_ucf_ctrl = (flags << (ri * 4)); 214206089Sfabient 215283884Sjhb PMCDBG1(MDP,ALL,2, "ucf-allocate config=0x%jx", 216206089Sfabient (uintmax_t) pm->pm_md.pm_ucf.pm_ucf_ctrl); 217206089Sfabient 218206089Sfabient return (0); 219206089Sfabient} 220206089Sfabient 221206089Sfabientstatic int 222206089Sfabientucf_config_pmc(int cpu, int ri, struct pmc *pm) 223206089Sfabient{ 224206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 225206089Sfabient ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 226206089Sfabient 227206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 228206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 229206089Sfabient 230283884Sjhb PMCDBG3(MDP,CFG,1, "ucf-config cpu=%d ri=%d pm=%p", cpu, ri, pm); 231206089Sfabient 232206089Sfabient KASSERT(uncore_pcpu[cpu] != NULL, ("[uncore,%d] null per-cpu %d", __LINE__, 233206089Sfabient cpu)); 234206089Sfabient 235206089Sfabient uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc = pm; 236206089Sfabient 237206089Sfabient return (0); 238206089Sfabient} 239206089Sfabient 240206089Sfabientstatic int 241206089Sfabientucf_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 242206089Sfabient{ 243206089Sfabient int error; 244206089Sfabient struct pmc_hw *phw; 245206089Sfabient char ucf_name[PMC_NAME_MAX]; 246206089Sfabient 247206089Sfabient phw = &uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri]; 248206089Sfabient 249206089Sfabient (void) snprintf(ucf_name, sizeof(ucf_name), "UCF-%d", ri); 250206089Sfabient if ((error = copystr(ucf_name, pi->pm_name, PMC_NAME_MAX, 251206089Sfabient NULL)) != 0) 252206089Sfabient return (error); 253206089Sfabient 254206089Sfabient pi->pm_class = PMC_CLASS_UCF; 255206089Sfabient 256206089Sfabient if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 257206089Sfabient pi->pm_enabled = TRUE; 258206089Sfabient *ppmc = phw->phw_pmc; 259206089Sfabient } else { 260206089Sfabient pi->pm_enabled = FALSE; 261206089Sfabient *ppmc = NULL; 262206089Sfabient } 263206089Sfabient 264206089Sfabient return (0); 265206089Sfabient} 266206089Sfabient 267206089Sfabientstatic int 268206089Sfabientucf_get_config(int cpu, int ri, struct pmc **ppm) 269206089Sfabient{ 270206089Sfabient *ppm = uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 271206089Sfabient 272206089Sfabient return (0); 273206089Sfabient} 274206089Sfabient 275206089Sfabientstatic int 276206089Sfabientucf_read_pmc(int cpu, int ri, pmc_value_t *v) 277206089Sfabient{ 278206089Sfabient struct pmc *pm; 279206089Sfabient pmc_value_t tmp; 280206089Sfabient 281206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 282206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 283206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 284206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 285206089Sfabient 286206089Sfabient pm = uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 287206089Sfabient 288206089Sfabient KASSERT(pm, 289206089Sfabient ("[uncore,%d] cpu %d ri %d(%d) pmc not configured", __LINE__, cpu, 290206089Sfabient ri, ri + uncore_ucf_ri)); 291206089Sfabient 292206089Sfabient tmp = rdmsr(UCF_CTR0 + ri); 293206089Sfabient 294206089Sfabient if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 295206089Sfabient *v = ucf_perfctr_value_to_reload_count(tmp); 296206089Sfabient else 297206089Sfabient *v = tmp; 298206089Sfabient 299283884Sjhb PMCDBG3(MDP,REA,1, "ucf-read cpu=%d ri=%d -> v=%jx", cpu, ri, *v); 300206089Sfabient 301206089Sfabient return (0); 302206089Sfabient} 303206089Sfabient 304206089Sfabientstatic int 305206089Sfabientucf_release_pmc(int cpu, int ri, struct pmc *pmc) 306206089Sfabient{ 307283884Sjhb PMCDBG3(MDP,REL,1, "ucf-release cpu=%d ri=%d pm=%p", cpu, ri, pmc); 308206089Sfabient 309206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 310206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 311206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 312206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 313206089Sfabient 314206089Sfabient KASSERT(uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc == NULL, 315206089Sfabient ("[uncore,%d] PHW pmc non-NULL", __LINE__)); 316206089Sfabient 317206089Sfabient return (0); 318206089Sfabient} 319206089Sfabient 320206089Sfabientstatic int 321206089Sfabientucf_start_pmc(int cpu, int ri) 322206089Sfabient{ 323206089Sfabient struct pmc *pm; 324206089Sfabient struct uncore_cpu *ucfc; 325206089Sfabient 326206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 327206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 328206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 329206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 330206089Sfabient 331283884Sjhb PMCDBG2(MDP,STA,1,"ucf-start cpu=%d ri=%d", cpu, ri); 332206089Sfabient 333206089Sfabient ucfc = uncore_pcpu[cpu]; 334206089Sfabient pm = ucfc->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 335206089Sfabient 336206089Sfabient ucfc->pc_ucfctrl |= pm->pm_md.pm_ucf.pm_ucf_ctrl; 337206089Sfabient 338206089Sfabient wrmsr(UCF_CTRL, ucfc->pc_ucfctrl); 339206089Sfabient 340206089Sfabient do { 341206089Sfabient ucfc->pc_resync = 0; 342232366Sdavide ucfc->pc_globalctrl |= (1ULL << (ri + SELECTOFF(uncore_cputype))); 343206089Sfabient wrmsr(UC_GLOBAL_CTRL, ucfc->pc_globalctrl); 344206089Sfabient } while (ucfc->pc_resync != 0); 345206089Sfabient 346283884Sjhb PMCDBG4(MDP,STA,1,"ucfctrl=%x(%x) globalctrl=%jx(%jx)", 347206089Sfabient ucfc->pc_ucfctrl, (uint32_t) rdmsr(UCF_CTRL), 348206089Sfabient ucfc->pc_globalctrl, rdmsr(UC_GLOBAL_CTRL)); 349206089Sfabient 350206089Sfabient return (0); 351206089Sfabient} 352206089Sfabient 353206089Sfabientstatic int 354206089Sfabientucf_stop_pmc(int cpu, int ri) 355206089Sfabient{ 356206089Sfabient uint32_t fc; 357206089Sfabient struct uncore_cpu *ucfc; 358206089Sfabient 359283884Sjhb PMCDBG2(MDP,STO,1,"ucf-stop cpu=%d ri=%d", cpu, ri); 360206089Sfabient 361206089Sfabient ucfc = uncore_pcpu[cpu]; 362206089Sfabient 363206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 364206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 365206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 366206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 367206089Sfabient 368206089Sfabient fc = (UCF_MASK << (ri * 4)); 369206089Sfabient 370206089Sfabient ucfc->pc_ucfctrl &= ~fc; 371206089Sfabient 372283884Sjhb PMCDBG1(MDP,STO,1,"ucf-stop ucfctrl=%x", ucfc->pc_ucfctrl); 373206089Sfabient wrmsr(UCF_CTRL, ucfc->pc_ucfctrl); 374206089Sfabient 375206089Sfabient do { 376206089Sfabient ucfc->pc_resync = 0; 377232366Sdavide ucfc->pc_globalctrl &= ~(1ULL << (ri + SELECTOFF(uncore_cputype))); 378206089Sfabient wrmsr(UC_GLOBAL_CTRL, ucfc->pc_globalctrl); 379206089Sfabient } while (ucfc->pc_resync != 0); 380206089Sfabient 381283884Sjhb PMCDBG4(MDP,STO,1,"ucfctrl=%x(%x) globalctrl=%jx(%jx)", 382206089Sfabient ucfc->pc_ucfctrl, (uint32_t) rdmsr(UCF_CTRL), 383206089Sfabient ucfc->pc_globalctrl, rdmsr(UC_GLOBAL_CTRL)); 384206089Sfabient 385206089Sfabient return (0); 386206089Sfabient} 387206089Sfabient 388206089Sfabientstatic int 389206089Sfabientucf_write_pmc(int cpu, int ri, pmc_value_t v) 390206089Sfabient{ 391206089Sfabient struct uncore_cpu *cc; 392206089Sfabient struct pmc *pm; 393206089Sfabient 394206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 395206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 396206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 397206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 398206089Sfabient 399206089Sfabient cc = uncore_pcpu[cpu]; 400206089Sfabient pm = cc->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 401206089Sfabient 402206089Sfabient KASSERT(pm, 403206089Sfabient ("[uncore,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, ri)); 404206089Sfabient 405206089Sfabient if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 406206089Sfabient v = ucf_reload_count_to_perfctr_value(v); 407206089Sfabient 408206089Sfabient wrmsr(UCF_CTRL, 0); /* Turn off fixed counters */ 409206089Sfabient wrmsr(UCF_CTR0 + ri, v); 410206089Sfabient wrmsr(UCF_CTRL, cc->pc_ucfctrl); 411206089Sfabient 412283884Sjhb PMCDBG4(MDP,WRI,1, "ucf-write cpu=%d ri=%d v=%jx ucfctrl=%jx ", 413206089Sfabient cpu, ri, v, (uintmax_t) rdmsr(UCF_CTRL)); 414206089Sfabient 415206089Sfabient return (0); 416206089Sfabient} 417206089Sfabient 418206089Sfabient 419206089Sfabientstatic void 420206089Sfabientucf_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth) 421206089Sfabient{ 422206089Sfabient struct pmc_classdep *pcd; 423206089Sfabient 424206089Sfabient KASSERT(md != NULL, ("[ucf,%d] md is NULL", __LINE__)); 425206089Sfabient 426283884Sjhb PMCDBG0(MDP,INI,1, "ucf-initialize"); 427206089Sfabient 428206089Sfabient pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCF]; 429206089Sfabient 430206089Sfabient pcd->pcd_caps = UCF_PMC_CAPS; 431206089Sfabient pcd->pcd_class = PMC_CLASS_UCF; 432206089Sfabient pcd->pcd_num = npmc; 433206089Sfabient pcd->pcd_ri = md->pmd_npmc; 434206089Sfabient pcd->pcd_width = pmcwidth; 435206089Sfabient 436206089Sfabient pcd->pcd_allocate_pmc = ucf_allocate_pmc; 437206089Sfabient pcd->pcd_config_pmc = ucf_config_pmc; 438206089Sfabient pcd->pcd_describe = ucf_describe; 439206089Sfabient pcd->pcd_get_config = ucf_get_config; 440206089Sfabient pcd->pcd_get_msr = NULL; 441206089Sfabient pcd->pcd_pcpu_fini = uncore_pcpu_noop; 442206089Sfabient pcd->pcd_pcpu_init = uncore_pcpu_noop; 443206089Sfabient pcd->pcd_read_pmc = ucf_read_pmc; 444206089Sfabient pcd->pcd_release_pmc = ucf_release_pmc; 445206089Sfabient pcd->pcd_start_pmc = ucf_start_pmc; 446206089Sfabient pcd->pcd_stop_pmc = ucf_stop_pmc; 447206089Sfabient pcd->pcd_write_pmc = ucf_write_pmc; 448206089Sfabient 449206089Sfabient md->pmd_npmc += npmc; 450206089Sfabient} 451206089Sfabient 452206089Sfabient/* 453206089Sfabient * Intel programmable PMCs. 454206089Sfabient */ 455206089Sfabient 456206089Sfabient/* 457206089Sfabient * Event descriptor tables. 458206089Sfabient * 459206089Sfabient * For each event id, we track: 460206089Sfabient * 461206089Sfabient * 1. The CPUs that the event is valid for. 462206089Sfabient * 463206089Sfabient * 2. If the event uses a fixed UMASK, the value of the umask field. 464206089Sfabient * If the event doesn't use a fixed UMASK, a mask of legal bits 465206089Sfabient * to check against. 466206089Sfabient */ 467206089Sfabient 468206089Sfabientstruct ucp_event_descr { 469206089Sfabient enum pmc_event ucp_ev; 470206089Sfabient unsigned char ucp_evcode; 471206089Sfabient unsigned char ucp_umask; 472206089Sfabient unsigned char ucp_flags; 473206089Sfabient}; 474206089Sfabient 475206089Sfabient#define UCP_F_I7 (1 << 0) /* CPU: Core i7 */ 476206089Sfabient#define UCP_F_WM (1 << 1) /* CPU: Westmere */ 477232366Sdavide#define UCP_F_SB (1 << 2) /* CPU: Sandy Bridge */ 478248842Ssbruno#define UCP_F_HW (1 << 3) /* CPU: Haswell */ 479248842Ssbruno#define UCP_F_FM (1 << 4) /* Fixed mask */ 480206089Sfabient 481206089Sfabient#define UCP_F_ALLCPUS \ 482206089Sfabient (UCP_F_I7 | UCP_F_WM) 483206089Sfabient 484206089Sfabient#define UCP_F_CMASK 0xFF000000 485206089Sfabient 486206089Sfabientstatic struct ucp_event_descr ucp_events[] = { 487206089Sfabient#undef UCPDESCR 488206089Sfabient#define UCPDESCR(N,EV,UM,FLAGS) { \ 489206089Sfabient .ucp_ev = PMC_EV_UCP_EVENT_##N, \ 490206089Sfabient .ucp_evcode = (EV), \ 491206089Sfabient .ucp_umask = (UM), \ 492206089Sfabient .ucp_flags = (FLAGS) \ 493206089Sfabient } 494206089Sfabient 495206089Sfabient UCPDESCR(00H_01H, 0x00, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 496206089Sfabient UCPDESCR(00H_02H, 0x00, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 497206089Sfabient UCPDESCR(00H_04H, 0x00, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 498206089Sfabient 499206089Sfabient UCPDESCR(01H_01H, 0x01, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 500206089Sfabient UCPDESCR(01H_02H, 0x01, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 501206089Sfabient UCPDESCR(01H_04H, 0x01, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 502206089Sfabient 503206089Sfabient UCPDESCR(02H_01H, 0x02, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 504206089Sfabient UCPDESCR(03H_01H, 0x03, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 505206089Sfabient UCPDESCR(03H_02H, 0x03, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 506206089Sfabient UCPDESCR(03H_04H, 0x03, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 507206089Sfabient UCPDESCR(03H_08H, 0x03, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 508206089Sfabient UCPDESCR(03H_10H, 0x03, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 509206089Sfabient UCPDESCR(03H_20H, 0x03, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 510206089Sfabient UCPDESCR(03H_40H, 0x03, 0x40, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 511206089Sfabient 512206089Sfabient UCPDESCR(04H_01H, 0x04, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 513206089Sfabient UCPDESCR(04H_02H, 0x04, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 514206089Sfabient UCPDESCR(04H_04H, 0x04, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 515206089Sfabient UCPDESCR(04H_08H, 0x04, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 516206089Sfabient UCPDESCR(04H_10H, 0x04, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 517206089Sfabient 518206089Sfabient UCPDESCR(05H_01H, 0x05, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 519206089Sfabient UCPDESCR(05H_02H, 0x05, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 520206089Sfabient UCPDESCR(05H_04H, 0x05, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 521206089Sfabient 522206089Sfabient UCPDESCR(06H_01H, 0x06, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 523206089Sfabient UCPDESCR(06H_02H, 0x06, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 524206089Sfabient UCPDESCR(06H_04H, 0x06, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 525206089Sfabient UCPDESCR(06H_08H, 0x06, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 526206089Sfabient UCPDESCR(06H_10H, 0x06, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 527206089Sfabient UCPDESCR(06H_20H, 0x06, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 528206089Sfabient 529206089Sfabient UCPDESCR(07H_01H, 0x07, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 530206089Sfabient UCPDESCR(07H_02H, 0x07, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 531206089Sfabient UCPDESCR(07H_04H, 0x07, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 532206089Sfabient UCPDESCR(07H_08H, 0x07, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 533206089Sfabient UCPDESCR(07H_10H, 0x07, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 534206089Sfabient UCPDESCR(07H_20H, 0x07, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 535206089Sfabient UCPDESCR(07H_24H, 0x07, 0x24, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 536206089Sfabient 537206089Sfabient UCPDESCR(08H_01H, 0x08, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 538206089Sfabient UCPDESCR(08H_02H, 0x08, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 539206089Sfabient UCPDESCR(08H_04H, 0x08, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 540206089Sfabient UCPDESCR(08H_03H, 0x08, 0x03, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 541206089Sfabient 542206089Sfabient UCPDESCR(09H_01H, 0x09, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 543206089Sfabient UCPDESCR(09H_02H, 0x09, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 544206089Sfabient UCPDESCR(09H_04H, 0x09, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 545206089Sfabient UCPDESCR(09H_03H, 0x09, 0x03, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 546206089Sfabient 547206089Sfabient UCPDESCR(0AH_01H, 0x0A, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 548206089Sfabient UCPDESCR(0AH_02H, 0x0A, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 549206089Sfabient UCPDESCR(0AH_04H, 0x0A, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 550206089Sfabient UCPDESCR(0AH_08H, 0x0A, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 551206089Sfabient UCPDESCR(0AH_0FH, 0x0A, 0x0F, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 552206089Sfabient 553206089Sfabient UCPDESCR(0BH_01H, 0x0B, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 554206089Sfabient UCPDESCR(0BH_02H, 0x0B, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 555206089Sfabient UCPDESCR(0BH_04H, 0x0B, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 556206089Sfabient UCPDESCR(0BH_08H, 0x0B, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 557206089Sfabient UCPDESCR(0BH_10H, 0x0B, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 558206089Sfabient UCPDESCR(0BH_1FH, 0x0B, 0x1F, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 559206089Sfabient 560206089Sfabient UCPDESCR(0CH_01H, 0x0C, 0x01, UCP_F_FM | UCP_F_WM), 561206089Sfabient UCPDESCR(0CH_02H, 0x0C, 0x02, UCP_F_FM | UCP_F_WM), 562229469Sfabient UCPDESCR(0CH_04H_E, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 563229469Sfabient UCPDESCR(0CH_04H_F, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 564229469Sfabient UCPDESCR(0CH_04H_M, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 565229469Sfabient UCPDESCR(0CH_04H_S, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 566229469Sfabient UCPDESCR(0CH_08H_E, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 567229469Sfabient UCPDESCR(0CH_08H_F, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 568229469Sfabient UCPDESCR(0CH_08H_M, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 569229469Sfabient UCPDESCR(0CH_08H_S, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 570206089Sfabient 571206089Sfabient UCPDESCR(20H_01H, 0x20, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 572206089Sfabient UCPDESCR(20H_02H, 0x20, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 573206089Sfabient UCPDESCR(20H_04H, 0x20, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 574206089Sfabient UCPDESCR(20H_08H, 0x20, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 575206089Sfabient UCPDESCR(20H_10H, 0x20, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 576206089Sfabient UCPDESCR(20H_20H, 0x20, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 577206089Sfabient 578206089Sfabient UCPDESCR(21H_01H, 0x21, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 579206089Sfabient UCPDESCR(21H_02H, 0x21, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 580206089Sfabient UCPDESCR(21H_04H, 0x21, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 581206089Sfabient 582232366Sdavide UCPDESCR(22H_01H, 0x22, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM | 583248842Ssbruno UCP_F_SB | UCP_F_HW), 584232366Sdavide UCPDESCR(22H_02H, 0x22, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM | 585248842Ssbruno UCP_F_SB | UCP_F_HW), 586232366Sdavide UCPDESCR(22H_04H, 0x22, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM | 587248842Ssbruno UCP_F_SB | UCP_F_HW), 588248842Ssbruno UCPDESCR(22H_08H, 0x22, 0x08, UCP_F_FM | UCP_F_SB | UCP_F_HW), 589248842Ssbruno UCPDESCR(22H_10H, 0x22, 0x10, UCP_F_FM | UCP_F_HW), 590248842Ssbruno UCPDESCR(22H_20H, 0x22, 0x20, UCP_F_FM | UCP_F_SB | UCP_F_HW), 591248842Ssbruno UCPDESCR(22H_40H, 0x22, 0x40, UCP_F_FM | UCP_F_SB | UCP_F_HW), 592248842Ssbruno UCPDESCR(22H_80H, 0x22, 0x80, UCP_F_FM | UCP_F_SB | UCP_F_HW), 593206089Sfabient 594206089Sfabient UCPDESCR(23H_01H, 0x23, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 595206089Sfabient UCPDESCR(23H_02H, 0x23, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 596206089Sfabient UCPDESCR(23H_04H, 0x23, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 597206089Sfabient 598206089Sfabient UCPDESCR(24H_02H, 0x24, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 599206089Sfabient UCPDESCR(24H_04H, 0x24, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 600206089Sfabient 601206089Sfabient UCPDESCR(25H_01H, 0x25, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 602206089Sfabient UCPDESCR(25H_02H, 0x25, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 603206089Sfabient UCPDESCR(25H_04H, 0x25, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 604206089Sfabient 605206089Sfabient UCPDESCR(26H_01H, 0x26, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 606206089Sfabient 607206089Sfabient UCPDESCR(27H_01H, 0x27, 0x01, UCP_F_FM | UCP_F_I7), 608206089Sfabient UCPDESCR(27H_02H, 0x27, 0x02, UCP_F_FM | UCP_F_I7), 609206089Sfabient UCPDESCR(27H_04H, 0x27, 0x04, UCP_F_FM | UCP_F_I7), 610206089Sfabient UCPDESCR(27H_08H, 0x27, 0x08, UCP_F_FM | UCP_F_I7), 611206089Sfabient UCPDESCR(27H_10H, 0x27, 0x10, UCP_F_FM | UCP_F_I7), 612206089Sfabient UCPDESCR(27H_20H, 0x27, 0x20, UCP_F_FM | UCP_F_I7), 613206089Sfabient 614206089Sfabient UCPDESCR(28H_01H, 0x28, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 615206089Sfabient UCPDESCR(28H_02H, 0x28, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 616206089Sfabient UCPDESCR(28H_04H, 0x28, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 617206089Sfabient UCPDESCR(28H_08H, 0x28, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 618206089Sfabient UCPDESCR(28H_10H, 0x28, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 619206089Sfabient UCPDESCR(28H_20H, 0x28, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 620206089Sfabient 621206089Sfabient UCPDESCR(29H_01H, 0x29, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 622206089Sfabient UCPDESCR(29H_02H, 0x29, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 623206089Sfabient UCPDESCR(29H_04H, 0x29, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 624206089Sfabient UCPDESCR(29H_08H, 0x29, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 625206089Sfabient UCPDESCR(29H_10H, 0x29, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 626206089Sfabient UCPDESCR(29H_20H, 0x29, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 627206089Sfabient 628206089Sfabient UCPDESCR(2AH_01H, 0x2A, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 629206089Sfabient UCPDESCR(2AH_02H, 0x2A, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 630206089Sfabient UCPDESCR(2AH_04H, 0x2A, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 631206089Sfabient UCPDESCR(2AH_07H, 0x2A, 0x07, UCP_F_FM | UCP_F_WM), 632206089Sfabient 633206089Sfabient UCPDESCR(2BH_01H, 0x2B, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 634206089Sfabient UCPDESCR(2BH_02H, 0x2B, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 635206089Sfabient UCPDESCR(2BH_04H, 0x2B, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 636206089Sfabient UCPDESCR(2BH_07H, 0x2B, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 637206089Sfabient 638206089Sfabient UCPDESCR(2CH_01H, 0x2C, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 639206089Sfabient UCPDESCR(2CH_02H, 0x2C, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 640206089Sfabient UCPDESCR(2CH_04H, 0x2C, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 641206089Sfabient UCPDESCR(2CH_07H, 0x2C, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 642206089Sfabient 643206089Sfabient UCPDESCR(2DH_01H, 0x2D, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 644206089Sfabient UCPDESCR(2DH_02H, 0x2D, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 645206089Sfabient UCPDESCR(2DH_04H, 0x2D, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 646206089Sfabient UCPDESCR(2DH_07H, 0x2D, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 647206089Sfabient 648206089Sfabient UCPDESCR(2EH_01H, 0x2E, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 649206089Sfabient UCPDESCR(2EH_02H, 0x2E, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 650206089Sfabient UCPDESCR(2EH_04H, 0x2E, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 651206089Sfabient UCPDESCR(2EH_07H, 0x2E, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 652206089Sfabient 653206089Sfabient UCPDESCR(2FH_01H, 0x2F, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 654206089Sfabient UCPDESCR(2FH_02H, 0x2F, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 655206089Sfabient UCPDESCR(2FH_04H, 0x2F, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 656206089Sfabient UCPDESCR(2FH_07H, 0x2F, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 657206089Sfabient UCPDESCR(2FH_08H, 0x2F, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 658206089Sfabient UCPDESCR(2FH_10H, 0x2F, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 659206089Sfabient UCPDESCR(2FH_20H, 0x2F, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 660206089Sfabient UCPDESCR(2FH_38H, 0x2F, 0x38, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 661206089Sfabient 662206089Sfabient UCPDESCR(30H_01H, 0x30, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 663206089Sfabient UCPDESCR(30H_02H, 0x30, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 664206089Sfabient UCPDESCR(30H_04H, 0x30, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 665206089Sfabient UCPDESCR(30H_07H, 0x30, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 666206089Sfabient 667206089Sfabient UCPDESCR(31H_01H, 0x31, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 668206089Sfabient UCPDESCR(31H_02H, 0x31, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 669206089Sfabient UCPDESCR(31H_04H, 0x31, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 670206089Sfabient UCPDESCR(31H_07H, 0x31, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 671206089Sfabient 672206089Sfabient UCPDESCR(32H_01H, 0x32, 0x01, UCP_F_FM | UCP_F_WM), 673206089Sfabient UCPDESCR(32H_02H, 0x32, 0x02, UCP_F_FM | UCP_F_WM), 674206089Sfabient UCPDESCR(32H_04H, 0x32, 0x04, UCP_F_FM | UCP_F_WM), 675206089Sfabient UCPDESCR(32H_07H, 0x32, 0x07, UCP_F_FM | UCP_F_WM), 676206089Sfabient 677206089Sfabient UCPDESCR(33H_01H, 0x33, 0x01, UCP_F_FM | UCP_F_WM), 678206089Sfabient UCPDESCR(33H_02H, 0x33, 0x02, UCP_F_FM | UCP_F_WM), 679206089Sfabient UCPDESCR(33H_04H, 0x33, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 680206089Sfabient UCPDESCR(33H_07H, 0x33, 0x07, UCP_F_FM | UCP_F_WM), 681206089Sfabient 682248842Ssbruno UCPDESCR(34H_01H, 0x34, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 683248842Ssbruno UCP_F_HW), 684232366Sdavide UCPDESCR(34H_02H, 0x34, 0x02, UCP_F_FM | UCP_F_WM | UCP_F_SB), 685232366Sdavide UCPDESCR(34H_04H, 0x34, 0x04, UCP_F_FM | UCP_F_WM | UCP_F_SB), 686248842Ssbruno UCPDESCR(34H_06H, 0x34, 0x06, UCP_F_FM | UCP_F_HW), 687248842Ssbruno UCPDESCR(34H_08H, 0x34, 0x08, UCP_F_FM | UCP_F_WM | UCP_F_SB | 688248842Ssbruno UCP_F_HW), 689248842Ssbruno UCPDESCR(34H_10H, 0x34, 0x10, UCP_F_FM | UCP_F_WM | UCP_F_SB | 690248842Ssbruno UCP_F_HW), 691248842Ssbruno UCPDESCR(34H_20H, 0x34, 0x20, UCP_F_FM | UCP_F_WM | UCP_F_SB | 692248842Ssbruno UCP_F_HW), 693248842Ssbruno UCPDESCR(34H_40H, 0x34, 0x40, UCP_F_FM | UCP_F_SB | UCP_F_HW), 694248842Ssbruno UCPDESCR(34H_80H, 0x34, 0x80, UCP_F_FM | UCP_F_SB | UCP_F_HW), 695206089Sfabient 696206089Sfabient UCPDESCR(35H_01H, 0x35, 0x01, UCP_F_FM | UCP_F_WM), 697206089Sfabient UCPDESCR(35H_02H, 0x35, 0x02, UCP_F_FM | UCP_F_WM), 698206089Sfabient UCPDESCR(35H_04H, 0x35, 0x04, UCP_F_FM | UCP_F_WM), 699206089Sfabient 700206089Sfabient UCPDESCR(40H_01H, 0x40, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 701206089Sfabient UCPDESCR(40H_02H, 0x40, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 702206089Sfabient UCPDESCR(40H_04H, 0x40, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 703206089Sfabient UCPDESCR(40H_08H, 0x40, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 704206089Sfabient UCPDESCR(40H_10H, 0x40, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 705206089Sfabient UCPDESCR(40H_20H, 0x40, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 706206089Sfabient UCPDESCR(40H_07H, 0x40, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 707206089Sfabient UCPDESCR(40H_38H, 0x40, 0x38, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 708206089Sfabient 709206089Sfabient UCPDESCR(41H_01H, 0x41, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 710206089Sfabient UCPDESCR(41H_02H, 0x41, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 711206089Sfabient UCPDESCR(41H_04H, 0x41, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 712206089Sfabient UCPDESCR(41H_08H, 0x41, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 713206089Sfabient UCPDESCR(41H_10H, 0x41, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 714206089Sfabient UCPDESCR(41H_20H, 0x41, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 715206089Sfabient UCPDESCR(41H_07H, 0x41, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 716206089Sfabient UCPDESCR(41H_38H, 0x41, 0x38, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 717206089Sfabient 718206089Sfabient UCPDESCR(42H_01H, 0x42, 0x01, UCP_F_FM | UCP_F_WM), 719206089Sfabient UCPDESCR(42H_02H, 0x42, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 720206089Sfabient UCPDESCR(42H_04H, 0x42, 0x04, UCP_F_FM | UCP_F_WM), 721206089Sfabient UCPDESCR(42H_08H, 0x42, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 722206089Sfabient 723206089Sfabient UCPDESCR(43H_01H, 0x43, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 724206089Sfabient UCPDESCR(43H_02H, 0x43, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 725206089Sfabient 726206089Sfabient UCPDESCR(60H_01H, 0x60, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 727206089Sfabient UCPDESCR(60H_02H, 0x60, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 728206089Sfabient UCPDESCR(60H_04H, 0x60, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 729206089Sfabient 730206089Sfabient UCPDESCR(61H_01H, 0x61, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 731206089Sfabient UCPDESCR(61H_02H, 0x61, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 732206089Sfabient UCPDESCR(61H_04H, 0x61, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 733206089Sfabient 734206089Sfabient UCPDESCR(62H_01H, 0x62, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 735206089Sfabient UCPDESCR(62H_02H, 0x62, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 736206089Sfabient UCPDESCR(62H_04H, 0x62, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 737206089Sfabient 738206089Sfabient UCPDESCR(63H_01H, 0x63, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 739206089Sfabient UCPDESCR(63H_02H, 0x63, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 740206089Sfabient UCPDESCR(63H_04H, 0x63, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 741206089Sfabient UCPDESCR(63H_08H, 0x63, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 742206089Sfabient UCPDESCR(63H_10H, 0x63, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 743206089Sfabient UCPDESCR(63H_20H, 0x63, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 744206089Sfabient 745206089Sfabient UCPDESCR(64H_01H, 0x64, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 746206089Sfabient UCPDESCR(64H_02H, 0x64, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 747206089Sfabient UCPDESCR(64H_04H, 0x64, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 748206089Sfabient UCPDESCR(64H_08H, 0x64, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 749206089Sfabient UCPDESCR(64H_10H, 0x64, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 750206089Sfabient UCPDESCR(64H_20H, 0x64, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 751206089Sfabient 752206089Sfabient UCPDESCR(65H_01H, 0x65, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 753206089Sfabient UCPDESCR(65H_02H, 0x65, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 754206089Sfabient UCPDESCR(65H_04H, 0x65, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 755206089Sfabient 756206089Sfabient UCPDESCR(66H_01H, 0x66, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 757206089Sfabient UCPDESCR(66H_02H, 0x66, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 758206089Sfabient UCPDESCR(66H_04H, 0x66, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 759206089Sfabient 760206089Sfabient UCPDESCR(67H_01H, 0x67, 0x01, UCP_F_FM | UCP_F_WM), 761249069Ssbruno 762248842Ssbruno UCPDESCR(80H_01H, 0x80, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 763248842Ssbruno UCP_F_HW), 764206089Sfabient UCPDESCR(80H_02H, 0x80, 0x02, UCP_F_FM | UCP_F_WM), 765206089Sfabient UCPDESCR(80H_04H, 0x80, 0x04, UCP_F_FM | UCP_F_WM), 766206089Sfabient UCPDESCR(80H_08H, 0x80, 0x08, UCP_F_FM | UCP_F_WM), 767249069Ssbruno 768248842Ssbruno UCPDESCR(81H_01H, 0x81, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 769248842Ssbruno UCP_F_HW), 770206089Sfabient UCPDESCR(81H_02H, 0x81, 0x02, UCP_F_FM | UCP_F_WM), 771206089Sfabient UCPDESCR(81H_04H, 0x81, 0x04, UCP_F_FM | UCP_F_WM), 772206089Sfabient UCPDESCR(81H_08H, 0x81, 0x08, UCP_F_FM | UCP_F_WM), 773248842Ssbruno UCPDESCR(81H_20H, 0x81, 0x20, UCP_F_FM | UCP_F_SB | UCP_F_HW), 774248842Ssbruno UCPDESCR(81H_80H, 0x81, 0x80, UCP_F_FM | UCP_F_SB | UCP_F_HW), 775232366Sdavide 776206089Sfabient UCPDESCR(82H_01H, 0x82, 0x01, UCP_F_FM | UCP_F_WM), 777249069Ssbruno 778248842Ssbruno UCPDESCR(83H_01H, 0x83, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 779248842Ssbruno UCP_F_HW), 780206089Sfabient UCPDESCR(83H_02H, 0x83, 0x02, UCP_F_FM | UCP_F_WM), 781206089Sfabient UCPDESCR(83H_04H, 0x83, 0x04, UCP_F_FM | UCP_F_WM), 782206089Sfabient UCPDESCR(83H_08H, 0x83, 0x08, UCP_F_FM | UCP_F_WM), 783249069Ssbruno 784248842Ssbruno UCPDESCR(84H_01H, 0x84, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 785248842Ssbruno UCP_F_HW), 786206089Sfabient UCPDESCR(84H_02H, 0x84, 0x02, UCP_F_FM | UCP_F_WM), 787206089Sfabient UCPDESCR(84H_04H, 0x84, 0x04, UCP_F_FM | UCP_F_WM), 788206089Sfabient UCPDESCR(84H_08H, 0x84, 0x08, UCP_F_FM | UCP_F_WM), 789206089Sfabient UCPDESCR(85H_02H, 0x85, 0x02, UCP_F_FM | UCP_F_WM), 790206089Sfabient UCPDESCR(86H_01H, 0x86, 0x01, UCP_F_FM | UCP_F_WM) 791206089Sfabient}; 792206089Sfabient 793206089Sfabientstatic const int nucp_events = sizeof(ucp_events) / sizeof(ucp_events[0]); 794206089Sfabient 795206089Sfabientstatic pmc_value_t 796206089Sfabientucp_perfctr_value_to_reload_count(pmc_value_t v) 797206089Sfabient{ 798206089Sfabient v &= (1ULL << uncore_ucp_width) - 1; 799206089Sfabient return (1ULL << uncore_ucp_width) - v; 800206089Sfabient} 801206089Sfabient 802206089Sfabientstatic pmc_value_t 803206089Sfabientucp_reload_count_to_perfctr_value(pmc_value_t rlc) 804206089Sfabient{ 805206089Sfabient return (1ULL << uncore_ucp_width) - rlc; 806206089Sfabient} 807206089Sfabient 808248842Ssbruno/* 809248842Ssbruno * Counter specific event information for Sandybridge and Haswell 810248842Ssbruno */ 811206089Sfabientstatic int 812248842Ssbrunoucp_event_sb_hw_ok_on_counter(enum pmc_event pe, int ri) 813232366Sdavide{ 814232366Sdavide uint32_t mask; 815249069Ssbruno 816232366Sdavide switch (pe) { 817249069Ssbruno /* 818232366Sdavide * Events valid only on counter 0. 819232366Sdavide */ 820232366Sdavide case PMC_EV_UCP_EVENT_80H_01H: 821232366Sdavide case PMC_EV_UCP_EVENT_83H_01H: 822232366Sdavide mask = (1 << 0); 823232366Sdavide break; 824249069Ssbruno 825232366Sdavide default: 826232366Sdavide mask = ~0; /* Any row index is ok. */ 827232366Sdavide } 828249069Ssbruno 829232366Sdavide return (mask & (1 << ri)); 830232366Sdavide} 831232366Sdavide 832232366Sdavidestatic int 833206089Sfabientucp_allocate_pmc(int cpu, int ri, struct pmc *pm, 834206089Sfabient const struct pmc_op_pmcallocate *a) 835206089Sfabient{ 836206089Sfabient int n; 837206089Sfabient enum pmc_event ev; 838206089Sfabient struct ucp_event_descr *ie; 839206089Sfabient uint32_t caps, config, cpuflag, evsel; 840206089Sfabient 841206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 842206089Sfabient ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 843206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 844206089Sfabient ("[uncore,%d] illegal row-index value %d", __LINE__, ri)); 845206089Sfabient 846206089Sfabient /* check requested capabilities */ 847206089Sfabient caps = a->pm_caps; 848206089Sfabient if ((UCP_PMC_CAPS & caps) != caps) 849206089Sfabient return (EPERM); 850206089Sfabient 851206089Sfabient ev = pm->pm_event; 852206089Sfabient 853232366Sdavide switch (uncore_cputype) { 854248842Ssbruno case PMC_CPU_INTEL_HASWELL: 855232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 856248842Ssbruno if (ucp_event_sb_hw_ok_on_counter(ev, ri) == 0) 857232366Sdavide return (EINVAL); 858232366Sdavide break; 859232366Sdavide default: 860232366Sdavide break; 861232366Sdavide } 862232366Sdavide 863249069Ssbruno 864206089Sfabient /* 865206089Sfabient * Look for an event descriptor with matching CPU and event id 866206089Sfabient * fields. 867206089Sfabient */ 868206089Sfabient 869206089Sfabient switch (uncore_cputype) { 870206089Sfabient case PMC_CPU_INTEL_COREI7: 871206089Sfabient cpuflag = UCP_F_I7; 872206089Sfabient break; 873248842Ssbruno case PMC_CPU_INTEL_HASWELL: 874248842Ssbruno cpuflag = UCP_F_HW; 875248842Ssbruno break; 876232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 877232366Sdavide cpuflag = UCP_F_SB; 878232366Sdavide break; 879206089Sfabient case PMC_CPU_INTEL_WESTMERE: 880206089Sfabient cpuflag = UCP_F_WM; 881206089Sfabient break; 882206089Sfabient default: 883206089Sfabient return (EINVAL); 884206089Sfabient } 885206089Sfabient 886206089Sfabient for (n = 0, ie = ucp_events; n < nucp_events; n++, ie++) 887206089Sfabient if (ie->ucp_ev == ev && ie->ucp_flags & cpuflag) 888206089Sfabient break; 889206089Sfabient 890206089Sfabient if (n == nucp_events) 891206089Sfabient return (EINVAL); 892206089Sfabient 893206089Sfabient /* 894206089Sfabient * A matching event descriptor has been found, so start 895206089Sfabient * assembling the contents of the event select register. 896206089Sfabient */ 897206089Sfabient evsel = ie->ucp_evcode | UCP_EN; 898206089Sfabient 899206089Sfabient config = a->pm_md.pm_ucp.pm_ucp_config & ~UCP_F_CMASK; 900206089Sfabient 901206089Sfabient /* 902206089Sfabient * If the event uses a fixed umask value, reject any umask 903206089Sfabient * bits set by the user. 904206089Sfabient */ 905206089Sfabient if (ie->ucp_flags & UCP_F_FM) { 906206089Sfabient 907206089Sfabient if (UCP_UMASK(config) != 0) 908206089Sfabient return (EINVAL); 909206089Sfabient 910206089Sfabient evsel |= (ie->ucp_umask << 8); 911206089Sfabient 912206089Sfabient } else 913206089Sfabient return (EINVAL); 914206089Sfabient 915206089Sfabient if (caps & PMC_CAP_THRESHOLD) 916206089Sfabient evsel |= (a->pm_md.pm_ucp.pm_ucp_config & UCP_F_CMASK); 917206089Sfabient if (caps & PMC_CAP_EDGE) 918206089Sfabient evsel |= UCP_EDGE; 919206089Sfabient if (caps & PMC_CAP_INVERT) 920206089Sfabient evsel |= UCP_INV; 921206089Sfabient 922206089Sfabient pm->pm_md.pm_ucp.pm_ucp_evsel = evsel; 923206089Sfabient 924206089Sfabient return (0); 925206089Sfabient} 926206089Sfabient 927206089Sfabientstatic int 928206089Sfabientucp_config_pmc(int cpu, int ri, struct pmc *pm) 929206089Sfabient{ 930206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 931206089Sfabient ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 932206089Sfabient 933206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 934206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 935206089Sfabient 936283884Sjhb PMCDBG3(MDP,CFG,1, "ucp-config cpu=%d ri=%d pm=%p", cpu, ri, pm); 937206089Sfabient 938206089Sfabient KASSERT(uncore_pcpu[cpu] != NULL, ("[uncore,%d] null per-cpu %d", __LINE__, 939206089Sfabient cpu)); 940206089Sfabient 941206089Sfabient uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc = pm; 942206089Sfabient 943206089Sfabient return (0); 944206089Sfabient} 945206089Sfabient 946206089Sfabientstatic int 947206089Sfabientucp_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 948206089Sfabient{ 949206089Sfabient int error; 950206089Sfabient struct pmc_hw *phw; 951206089Sfabient char ucp_name[PMC_NAME_MAX]; 952206089Sfabient 953206089Sfabient phw = &uncore_pcpu[cpu]->pc_uncorepmcs[ri]; 954206089Sfabient 955206089Sfabient (void) snprintf(ucp_name, sizeof(ucp_name), "UCP-%d", ri); 956206089Sfabient if ((error = copystr(ucp_name, pi->pm_name, PMC_NAME_MAX, 957206089Sfabient NULL)) != 0) 958206089Sfabient return (error); 959206089Sfabient 960206089Sfabient pi->pm_class = PMC_CLASS_UCP; 961206089Sfabient 962206089Sfabient if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 963206089Sfabient pi->pm_enabled = TRUE; 964206089Sfabient *ppmc = phw->phw_pmc; 965206089Sfabient } else { 966206089Sfabient pi->pm_enabled = FALSE; 967206089Sfabient *ppmc = NULL; 968206089Sfabient } 969206089Sfabient 970206089Sfabient return (0); 971206089Sfabient} 972206089Sfabient 973206089Sfabientstatic int 974206089Sfabientucp_get_config(int cpu, int ri, struct pmc **ppm) 975206089Sfabient{ 976206089Sfabient *ppm = uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc; 977206089Sfabient 978206089Sfabient return (0); 979206089Sfabient} 980206089Sfabient 981206089Sfabientstatic int 982206089Sfabientucp_read_pmc(int cpu, int ri, pmc_value_t *v) 983206089Sfabient{ 984206089Sfabient struct pmc *pm; 985206089Sfabient pmc_value_t tmp; 986206089Sfabient 987206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 988206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 989206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 990206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 991206089Sfabient 992206089Sfabient pm = uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc; 993206089Sfabient 994206089Sfabient KASSERT(pm, 995206089Sfabient ("[uncore,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, 996206089Sfabient ri)); 997206089Sfabient 998206089Sfabient tmp = rdmsr(UCP_PMC0 + ri); 999206089Sfabient if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 1000206089Sfabient *v = ucp_perfctr_value_to_reload_count(tmp); 1001206089Sfabient else 1002206089Sfabient *v = tmp; 1003206089Sfabient 1004283884Sjhb PMCDBG4(MDP,REA,1, "ucp-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri, 1005206089Sfabient ri, *v); 1006206089Sfabient 1007206089Sfabient return (0); 1008206089Sfabient} 1009206089Sfabient 1010206089Sfabientstatic int 1011206089Sfabientucp_release_pmc(int cpu, int ri, struct pmc *pm) 1012206089Sfabient{ 1013206089Sfabient (void) pm; 1014206089Sfabient 1015283884Sjhb PMCDBG3(MDP,REL,1, "ucp-release cpu=%d ri=%d pm=%p", cpu, ri, 1016206089Sfabient pm); 1017206089Sfabient 1018206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1019206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 1020206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1021206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 1022206089Sfabient 1023206089Sfabient KASSERT(uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc 1024206089Sfabient == NULL, ("[uncore,%d] PHW pmc non-NULL", __LINE__)); 1025206089Sfabient 1026206089Sfabient return (0); 1027206089Sfabient} 1028206089Sfabient 1029206089Sfabientstatic int 1030206089Sfabientucp_start_pmc(int cpu, int ri) 1031206089Sfabient{ 1032206089Sfabient struct pmc *pm; 1033206089Sfabient uint32_t evsel; 1034206089Sfabient struct uncore_cpu *cc; 1035206089Sfabient 1036206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1037206089Sfabient ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 1038206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1039206089Sfabient ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 1040206089Sfabient 1041206089Sfabient cc = uncore_pcpu[cpu]; 1042206089Sfabient pm = cc->pc_uncorepmcs[ri].phw_pmc; 1043206089Sfabient 1044206089Sfabient KASSERT(pm, 1045206089Sfabient ("[uncore,%d] starting cpu%d,ri%d with no pmc configured", 1046206089Sfabient __LINE__, cpu, ri)); 1047206089Sfabient 1048283884Sjhb PMCDBG2(MDP,STA,1, "ucp-start cpu=%d ri=%d", cpu, ri); 1049206089Sfabient 1050206089Sfabient evsel = pm->pm_md.pm_ucp.pm_ucp_evsel; 1051206089Sfabient 1052283884Sjhb PMCDBG4(MDP,STA,2, 1053249069Ssbruno "ucp-start/2 cpu=%d ri=%d evselmsr=0x%x evsel=0x%x", 1054249069Ssbruno cpu, ri, SELECTSEL(uncore_cputype) + ri, evsel); 1055206089Sfabient 1056229469Sfabient /* Event specific configuration. */ 1057229469Sfabient switch (pm->pm_event) { 1058229469Sfabient case PMC_EV_UCP_EVENT_0CH_04H_E: 1059230063Sgnn case PMC_EV_UCP_EVENT_0CH_08H_E: 1060229469Sfabient wrmsr(MSR_GQ_SNOOP_MESF,0x2); 1061229469Sfabient break; 1062229469Sfabient case PMC_EV_UCP_EVENT_0CH_04H_F: 1063230063Sgnn case PMC_EV_UCP_EVENT_0CH_08H_F: 1064229469Sfabient wrmsr(MSR_GQ_SNOOP_MESF,0x8); 1065229469Sfabient break; 1066229469Sfabient case PMC_EV_UCP_EVENT_0CH_04H_M: 1067230063Sgnn case PMC_EV_UCP_EVENT_0CH_08H_M: 1068229469Sfabient wrmsr(MSR_GQ_SNOOP_MESF,0x1); 1069229469Sfabient break; 1070229469Sfabient case PMC_EV_UCP_EVENT_0CH_04H_S: 1071229469Sfabient case PMC_EV_UCP_EVENT_0CH_08H_S: 1072229469Sfabient wrmsr(MSR_GQ_SNOOP_MESF,0x4); 1073229469Sfabient break; 1074249069Ssbruno default: 1075229469Sfabient break; 1076229469Sfabient } 1077229469Sfabient 1078232366Sdavide wrmsr(SELECTSEL(uncore_cputype) + ri, evsel); 1079249069Ssbruno 1080206089Sfabient do { 1081206089Sfabient cc->pc_resync = 0; 1082206089Sfabient cc->pc_globalctrl |= (1ULL << ri); 1083206089Sfabient wrmsr(UC_GLOBAL_CTRL, cc->pc_globalctrl); 1084206089Sfabient } while (cc->pc_resync != 0); 1085206089Sfabient 1086206089Sfabient return (0); 1087206089Sfabient} 1088206089Sfabient 1089206089Sfabientstatic int 1090206089Sfabientucp_stop_pmc(int cpu, int ri) 1091206089Sfabient{ 1092206089Sfabient struct pmc *pm; 1093206089Sfabient struct uncore_cpu *cc; 1094206089Sfabient 1095206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1096206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 1097206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1098206089Sfabient ("[uncore,%d] illegal row index %d", __LINE__, ri)); 1099206089Sfabient 1100206089Sfabient cc = uncore_pcpu[cpu]; 1101206089Sfabient pm = cc->pc_uncorepmcs[ri].phw_pmc; 1102206089Sfabient 1103206089Sfabient KASSERT(pm, 1104206089Sfabient ("[uncore,%d] cpu%d ri%d no configured PMC to stop", __LINE__, 1105206089Sfabient cpu, ri)); 1106206089Sfabient 1107283884Sjhb PMCDBG2(MDP,STO,1, "ucp-stop cpu=%d ri=%d", cpu, ri); 1108206089Sfabient 1109232366Sdavide /* stop hw. */ 1110232366Sdavide wrmsr(SELECTSEL(uncore_cputype) + ri, 0); 1111206089Sfabient 1112206089Sfabient do { 1113206089Sfabient cc->pc_resync = 0; 1114206089Sfabient cc->pc_globalctrl &= ~(1ULL << ri); 1115206089Sfabient wrmsr(UC_GLOBAL_CTRL, cc->pc_globalctrl); 1116206089Sfabient } while (cc->pc_resync != 0); 1117206089Sfabient 1118206089Sfabient return (0); 1119206089Sfabient} 1120206089Sfabient 1121206089Sfabientstatic int 1122206089Sfabientucp_write_pmc(int cpu, int ri, pmc_value_t v) 1123206089Sfabient{ 1124206089Sfabient struct pmc *pm; 1125206089Sfabient struct uncore_cpu *cc; 1126206089Sfabient 1127206089Sfabient KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1128206089Sfabient ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 1129206089Sfabient KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1130206089Sfabient ("[uncore,%d] illegal row index %d", __LINE__, ri)); 1131206089Sfabient 1132206089Sfabient cc = uncore_pcpu[cpu]; 1133206089Sfabient pm = cc->pc_uncorepmcs[ri].phw_pmc; 1134206089Sfabient 1135206089Sfabient KASSERT(pm, 1136206089Sfabient ("[uncore,%d] cpu%d ri%d no configured PMC to stop", __LINE__, 1137206089Sfabient cpu, ri)); 1138206089Sfabient 1139283884Sjhb PMCDBG4(MDP,WRI,1, "ucp-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri, 1140206089Sfabient UCP_PMC0 + ri, v); 1141206089Sfabient 1142206089Sfabient if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 1143206089Sfabient v = ucp_reload_count_to_perfctr_value(v); 1144206089Sfabient 1145206089Sfabient /* 1146206089Sfabient * Write the new value to the counter. The counter will be in 1147206089Sfabient * a stopped state when the pcd_write() entry point is called. 1148206089Sfabient */ 1149206089Sfabient 1150206089Sfabient wrmsr(UCP_PMC0 + ri, v); 1151206089Sfabient 1152206089Sfabient return (0); 1153206089Sfabient} 1154206089Sfabient 1155206089Sfabient 1156206089Sfabientstatic void 1157206089Sfabientucp_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth) 1158206089Sfabient{ 1159206089Sfabient struct pmc_classdep *pcd; 1160206089Sfabient 1161206089Sfabient KASSERT(md != NULL, ("[ucp,%d] md is NULL", __LINE__)); 1162206089Sfabient 1163283884Sjhb PMCDBG0(MDP,INI,1, "ucp-initialize"); 1164206089Sfabient 1165206089Sfabient pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP]; 1166206089Sfabient 1167206089Sfabient pcd->pcd_caps = UCP_PMC_CAPS; 1168206089Sfabient pcd->pcd_class = PMC_CLASS_UCP; 1169206089Sfabient pcd->pcd_num = npmc; 1170206089Sfabient pcd->pcd_ri = md->pmd_npmc; 1171206089Sfabient pcd->pcd_width = pmcwidth; 1172206089Sfabient 1173206089Sfabient pcd->pcd_allocate_pmc = ucp_allocate_pmc; 1174206089Sfabient pcd->pcd_config_pmc = ucp_config_pmc; 1175206089Sfabient pcd->pcd_describe = ucp_describe; 1176206089Sfabient pcd->pcd_get_config = ucp_get_config; 1177206089Sfabient pcd->pcd_get_msr = NULL; 1178206089Sfabient pcd->pcd_pcpu_fini = uncore_pcpu_fini; 1179206089Sfabient pcd->pcd_pcpu_init = uncore_pcpu_init; 1180206089Sfabient pcd->pcd_read_pmc = ucp_read_pmc; 1181206089Sfabient pcd->pcd_release_pmc = ucp_release_pmc; 1182206089Sfabient pcd->pcd_start_pmc = ucp_start_pmc; 1183206089Sfabient pcd->pcd_stop_pmc = ucp_stop_pmc; 1184206089Sfabient pcd->pcd_write_pmc = ucp_write_pmc; 1185206089Sfabient 1186206089Sfabient md->pmd_npmc += npmc; 1187206089Sfabient} 1188206089Sfabient 1189206089Sfabientint 1190206089Sfabientpmc_uncore_initialize(struct pmc_mdep *md, int maxcpu) 1191206089Sfabient{ 1192206089Sfabient uncore_cputype = md->pmd_cputype; 1193206089Sfabient uncore_pmcmask = 0; 1194206089Sfabient 1195206089Sfabient /* 1196206089Sfabient * Initialize programmable counters. 1197206089Sfabient */ 1198206089Sfabient 1199206089Sfabient uncore_ucp_npmc = 8; 1200206089Sfabient uncore_ucp_width = 48; 1201206089Sfabient 1202206089Sfabient uncore_pmcmask |= ((1ULL << uncore_ucp_npmc) - 1); 1203206089Sfabient 1204206089Sfabient ucp_initialize(md, maxcpu, uncore_ucp_npmc, uncore_ucp_width); 1205206089Sfabient 1206206089Sfabient /* 1207206089Sfabient * Initialize fixed function counters, if present. 1208206089Sfabient */ 1209206089Sfabient uncore_ucf_ri = uncore_ucp_npmc; 1210206089Sfabient uncore_ucf_npmc = 1; 1211206089Sfabient uncore_ucf_width = 48; 1212206089Sfabient 1213206089Sfabient ucf_initialize(md, maxcpu, uncore_ucf_npmc, uncore_ucf_width); 1214232366Sdavide uncore_pmcmask |= ((1ULL << uncore_ucf_npmc) - 1) << SELECTOFF(uncore_cputype); 1215206089Sfabient 1216283884Sjhb PMCDBG2(MDP,INI,1,"uncore-init pmcmask=0x%jx ucfri=%d", uncore_pmcmask, 1217206089Sfabient uncore_ucf_ri); 1218206089Sfabient 1219206089Sfabient uncore_pcpu = malloc(sizeof(struct uncore_cpu **) * maxcpu, M_PMC, 1220206089Sfabient M_ZERO | M_WAITOK); 1221206089Sfabient 1222206089Sfabient return (0); 1223206089Sfabient} 1224206089Sfabient 1225206089Sfabientvoid 1226206089Sfabientpmc_uncore_finalize(struct pmc_mdep *md) 1227206089Sfabient{ 1228283884Sjhb PMCDBG0(MDP,INI,1, "uncore-finalize"); 1229206089Sfabient 1230206089Sfabient free(uncore_pcpu, M_PMC); 1231206089Sfabient uncore_pcpu = NULL; 1232206089Sfabient} 1233