1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2010 Fabien Thomas 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * Intel Uncore PMCs. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <sys/param.h> 37 #include <sys/bus.h> 38 #include <sys/pmc.h> 39 #include <sys/pmckern.h> 40 #include <sys/systm.h> 41 42 #include <machine/intr_machdep.h> 43 #if (__FreeBSD_version >= 1100000) 44 #include <x86/apicvar.h> 45 #else 46 #include <machine/apicvar.h> 47 #endif 48 #include <machine/cpu.h> 49 #include <machine/cpufunc.h> 50 #include <machine/specialreg.h> 51 52 #define UCF_PMC_CAPS \ 53 (PMC_CAP_READ | PMC_CAP_WRITE) 54 55 #define UCP_PMC_CAPS \ 56 (PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE | \ 57 PMC_CAP_INVERT | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE) 58 59 #define SELECTSEL(x) \ 60 (((x) == PMC_CPU_INTEL_SANDYBRIDGE || (x) == PMC_CPU_INTEL_HASWELL) ? \ 61 UCP_CB0_EVSEL0 : UCP_EVSEL0) 62 63 #define SELECTOFF(x) \ 64 (((x) == PMC_CPU_INTEL_SANDYBRIDGE || (x) == PMC_CPU_INTEL_HASWELL) ? \ 65 UCF_OFFSET_SB : UCF_OFFSET) 66 67 static enum pmc_cputype uncore_cputype; 68 69 struct uncore_cpu { 70 volatile uint32_t pc_resync; 71 volatile uint32_t pc_ucfctrl; /* Fixed function control. */ 72 volatile uint64_t pc_globalctrl; /* Global control register. */ 73 struct pmc_hw pc_uncorepmcs[]; 74 }; 75 76 static struct uncore_cpu **uncore_pcpu; 77 78 static uint64_t uncore_pmcmask; 79 80 static int uncore_ucf_ri; /* relative index of fixed counters */ 81 static int uncore_ucf_width; 82 static int uncore_ucf_npmc; 83 84 static int uncore_ucp_width; 85 static int uncore_ucp_npmc; 86 87 static int 88 uncore_pcpu_noop(struct pmc_mdep *md, int cpu) 89 { 90 (void) md; 91 (void) cpu; 92 return (0); 93 } 94 95 static int 96 uncore_pcpu_init(struct pmc_mdep *md, int cpu) 97 { 98 struct pmc_cpu *pc; 99 struct uncore_cpu *cc; 100 struct pmc_hw *phw; 101 int uncore_ri, n, npmc; 102 103 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 104 ("[ucf,%d] insane cpu number %d", __LINE__, cpu)); 105 106 PMCDBG1(MDP,INI,1,"uncore-init cpu=%d", cpu); 107 108 uncore_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_ri; 109 npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_num; 110 npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCF].pcd_num; 111 112 cc = malloc(sizeof(struct uncore_cpu) + npmc * sizeof(struct pmc_hw), 113 M_PMC, M_WAITOK | M_ZERO); 114 115 uncore_pcpu[cpu] = cc; 116 pc = pmc_pcpu[cpu]; 117 118 KASSERT(pc != NULL && cc != NULL, 119 ("[uncore,%d] NULL per-cpu structures cpu=%d", __LINE__, cpu)); 120 121 for (n = 0, phw = cc->pc_uncorepmcs; n < npmc; n++, phw++) { 122 phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | 123 PMC_PHW_CPU_TO_STATE(cpu) | 124 PMC_PHW_INDEX_TO_STATE(n + uncore_ri); 125 phw->phw_pmc = NULL; 126 pc->pc_hwpmcs[n + uncore_ri] = phw; 127 } 128 129 return (0); 130 } 131 132 static int 133 uncore_pcpu_fini(struct pmc_mdep *md, int cpu) 134 { 135 int uncore_ri, n, npmc; 136 struct pmc_cpu *pc; 137 struct uncore_cpu *cc; 138 139 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 140 ("[uncore,%d] insane cpu number (%d)", __LINE__, cpu)); 141 142 PMCDBG1(MDP,INI,1,"uncore-pcpu-fini cpu=%d", cpu); 143 144 if ((cc = uncore_pcpu[cpu]) == NULL) 145 return (0); 146 147 uncore_pcpu[cpu] = NULL; 148 149 pc = pmc_pcpu[cpu]; 150 151 KASSERT(pc != NULL, ("[uncore,%d] NULL per-cpu %d state", __LINE__, 152 cpu)); 153 154 npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_num; 155 uncore_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP].pcd_ri; 156 157 for (n = 0; n < npmc; n++) 158 wrmsr(SELECTSEL(uncore_cputype) + n, 0); 159 160 wrmsr(UCF_CTRL, 0); 161 npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCF].pcd_num; 162 163 for (n = 0; n < npmc; n++) 164 pc->pc_hwpmcs[n + uncore_ri] = NULL; 165 166 free(cc, M_PMC); 167 168 return (0); 169 } 170 171 /* 172 * Fixed function counters. 173 */ 174 175 static pmc_value_t 176 ucf_perfctr_value_to_reload_count(pmc_value_t v) 177 { 178 v &= (1ULL << uncore_ucf_width) - 1; 179 return (1ULL << uncore_ucf_width) - v; 180 } 181 182 static pmc_value_t 183 ucf_reload_count_to_perfctr_value(pmc_value_t rlc) 184 { 185 return (1ULL << uncore_ucf_width) - rlc; 186 } 187 188 static int 189 ucf_allocate_pmc(int cpu, int ri, struct pmc *pm, 190 const struct pmc_op_pmcallocate *a) 191 { 192 enum pmc_event ev; 193 uint32_t caps, flags; 194 195 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 196 ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 197 198 PMCDBG2(MDP,ALL,1, "ucf-allocate ri=%d reqcaps=0x%x", ri, pm->pm_caps); 199 200 if (ri < 0 || ri > uncore_ucf_npmc) 201 return (EINVAL); 202 203 caps = a->pm_caps; 204 205 if (a->pm_class != PMC_CLASS_UCF || 206 (caps & UCF_PMC_CAPS) != caps) 207 return (EINVAL); 208 209 ev = pm->pm_event; 210 if (ev < PMC_EV_UCF_FIRST || ev > PMC_EV_UCF_LAST) 211 return (EINVAL); 212 213 flags = UCF_EN; 214 215 pm->pm_md.pm_ucf.pm_ucf_ctrl = (flags << (ri * 4)); 216 217 PMCDBG1(MDP,ALL,2, "ucf-allocate config=0x%jx", 218 (uintmax_t) pm->pm_md.pm_ucf.pm_ucf_ctrl); 219 220 return (0); 221 } 222 223 static int 224 ucf_config_pmc(int cpu, int ri, struct pmc *pm) 225 { 226 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 227 ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 228 229 KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 230 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 231 232 PMCDBG3(MDP,CFG,1, "ucf-config cpu=%d ri=%d pm=%p", cpu, ri, pm); 233 234 KASSERT(uncore_pcpu[cpu] != NULL, ("[uncore,%d] null per-cpu %d", __LINE__, 235 cpu)); 236 237 uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc = pm; 238 239 return (0); 240 } 241 242 static int 243 ucf_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 244 { 245 int error; 246 struct pmc_hw *phw; 247 char ucf_name[PMC_NAME_MAX]; 248 249 phw = &uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri]; 250 251 (void) snprintf(ucf_name, sizeof(ucf_name), "UCF-%d", ri); 252 if ((error = copystr(ucf_name, pi->pm_name, PMC_NAME_MAX, 253 NULL)) != 0) 254 return (error); 255 256 pi->pm_class = PMC_CLASS_UCF; 257 258 if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 259 pi->pm_enabled = TRUE; 260 *ppmc = phw->phw_pmc; 261 } else { 262 pi->pm_enabled = FALSE; 263 *ppmc = NULL; 264 } 265 266 return (0); 267 } 268 269 static int 270 ucf_get_config(int cpu, int ri, struct pmc **ppm) 271 { 272 *ppm = uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 273 274 return (0); 275 } 276 277 static int 278 ucf_read_pmc(int cpu, int ri, pmc_value_t *v) 279 { 280 struct pmc *pm; 281 pmc_value_t tmp; 282 283 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 284 ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 285 KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 286 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 287 288 pm = uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 289 290 KASSERT(pm, 291 ("[uncore,%d] cpu %d ri %d(%d) pmc not configured", __LINE__, cpu, 292 ri, ri + uncore_ucf_ri)); 293 294 tmp = rdmsr(UCF_CTR0 + ri); 295 296 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 297 *v = ucf_perfctr_value_to_reload_count(tmp); 298 else 299 *v = tmp; 300 301 PMCDBG3(MDP,REA,1, "ucf-read cpu=%d ri=%d -> v=%jx", cpu, ri, *v); 302 303 return (0); 304 } 305 306 static int 307 ucf_release_pmc(int cpu, int ri, struct pmc *pmc) 308 { 309 PMCDBG3(MDP,REL,1, "ucf-release cpu=%d ri=%d pm=%p", cpu, ri, pmc); 310 311 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 312 ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 313 KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 314 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 315 316 KASSERT(uncore_pcpu[cpu]->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc == NULL, 317 ("[uncore,%d] PHW pmc non-NULL", __LINE__)); 318 319 return (0); 320 } 321 322 static int 323 ucf_start_pmc(int cpu, int ri) 324 { 325 struct pmc *pm; 326 struct uncore_cpu *ucfc; 327 328 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 329 ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 330 KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 331 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 332 333 PMCDBG2(MDP,STA,1,"ucf-start cpu=%d ri=%d", cpu, ri); 334 335 ucfc = uncore_pcpu[cpu]; 336 pm = ucfc->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 337 338 ucfc->pc_ucfctrl |= pm->pm_md.pm_ucf.pm_ucf_ctrl; 339 340 wrmsr(UCF_CTRL, ucfc->pc_ucfctrl); 341 342 do { 343 ucfc->pc_resync = 0; 344 ucfc->pc_globalctrl |= (1ULL << (ri + SELECTOFF(uncore_cputype))); 345 wrmsr(UC_GLOBAL_CTRL, ucfc->pc_globalctrl); 346 } while (ucfc->pc_resync != 0); 347 348 PMCDBG4(MDP,STA,1,"ucfctrl=%x(%x) globalctrl=%jx(%jx)", 349 ucfc->pc_ucfctrl, (uint32_t) rdmsr(UCF_CTRL), 350 ucfc->pc_globalctrl, rdmsr(UC_GLOBAL_CTRL)); 351 352 return (0); 353 } 354 355 static int 356 ucf_stop_pmc(int cpu, int ri) 357 { 358 uint32_t fc; 359 struct uncore_cpu *ucfc; 360 361 PMCDBG2(MDP,STO,1,"ucf-stop cpu=%d ri=%d", cpu, ri); 362 363 ucfc = uncore_pcpu[cpu]; 364 365 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 366 ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 367 KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 368 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 369 370 fc = (UCF_MASK << (ri * 4)); 371 372 ucfc->pc_ucfctrl &= ~fc; 373 374 PMCDBG1(MDP,STO,1,"ucf-stop ucfctrl=%x", ucfc->pc_ucfctrl); 375 wrmsr(UCF_CTRL, ucfc->pc_ucfctrl); 376 377 do { 378 ucfc->pc_resync = 0; 379 ucfc->pc_globalctrl &= ~(1ULL << (ri + SELECTOFF(uncore_cputype))); 380 wrmsr(UC_GLOBAL_CTRL, ucfc->pc_globalctrl); 381 } while (ucfc->pc_resync != 0); 382 383 PMCDBG4(MDP,STO,1,"ucfctrl=%x(%x) globalctrl=%jx(%jx)", 384 ucfc->pc_ucfctrl, (uint32_t) rdmsr(UCF_CTRL), 385 ucfc->pc_globalctrl, rdmsr(UC_GLOBAL_CTRL)); 386 387 return (0); 388 } 389 390 static int 391 ucf_write_pmc(int cpu, int ri, pmc_value_t v) 392 { 393 struct uncore_cpu *cc; 394 struct pmc *pm; 395 396 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 397 ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 398 KASSERT(ri >= 0 && ri < uncore_ucf_npmc, 399 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 400 401 cc = uncore_pcpu[cpu]; 402 pm = cc->pc_uncorepmcs[ri + uncore_ucf_ri].phw_pmc; 403 404 KASSERT(pm, 405 ("[uncore,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, ri)); 406 407 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 408 v = ucf_reload_count_to_perfctr_value(v); 409 410 wrmsr(UCF_CTRL, 0); /* Turn off fixed counters */ 411 wrmsr(UCF_CTR0 + ri, v); 412 wrmsr(UCF_CTRL, cc->pc_ucfctrl); 413 414 PMCDBG4(MDP,WRI,1, "ucf-write cpu=%d ri=%d v=%jx ucfctrl=%jx ", 415 cpu, ri, v, (uintmax_t) rdmsr(UCF_CTRL)); 416 417 return (0); 418 } 419 420 421 static void 422 ucf_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth) 423 { 424 struct pmc_classdep *pcd; 425 426 KASSERT(md != NULL, ("[ucf,%d] md is NULL", __LINE__)); 427 428 PMCDBG0(MDP,INI,1, "ucf-initialize"); 429 430 pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCF]; 431 432 pcd->pcd_caps = UCF_PMC_CAPS; 433 pcd->pcd_class = PMC_CLASS_UCF; 434 pcd->pcd_num = npmc; 435 pcd->pcd_ri = md->pmd_npmc; 436 pcd->pcd_width = pmcwidth; 437 438 pcd->pcd_allocate_pmc = ucf_allocate_pmc; 439 pcd->pcd_config_pmc = ucf_config_pmc; 440 pcd->pcd_describe = ucf_describe; 441 pcd->pcd_get_config = ucf_get_config; 442 pcd->pcd_get_msr = NULL; 443 pcd->pcd_pcpu_fini = uncore_pcpu_noop; 444 pcd->pcd_pcpu_init = uncore_pcpu_noop; 445 pcd->pcd_read_pmc = ucf_read_pmc; 446 pcd->pcd_release_pmc = ucf_release_pmc; 447 pcd->pcd_start_pmc = ucf_start_pmc; 448 pcd->pcd_stop_pmc = ucf_stop_pmc; 449 pcd->pcd_write_pmc = ucf_write_pmc; 450 451 md->pmd_npmc += npmc; 452 } 453 454 /* 455 * Intel programmable PMCs. 456 */ 457 458 /* 459 * Event descriptor tables. 460 * 461 * For each event id, we track: 462 * 463 * 1. The CPUs that the event is valid for. 464 * 465 * 2. If the event uses a fixed UMASK, the value of the umask field. 466 * If the event doesn't use a fixed UMASK, a mask of legal bits 467 * to check against. 468 */ 469 470 struct ucp_event_descr { 471 enum pmc_event ucp_ev; 472 unsigned char ucp_evcode; 473 unsigned char ucp_umask; 474 unsigned char ucp_flags; 475 }; 476 477 #define UCP_F_I7 (1 << 0) /* CPU: Core i7 */ 478 #define UCP_F_WM (1 << 1) /* CPU: Westmere */ 479 #define UCP_F_SB (1 << 2) /* CPU: Sandy Bridge */ 480 #define UCP_F_HW (1 << 3) /* CPU: Haswell */ 481 #define UCP_F_FM (1 << 4) /* Fixed mask */ 482 483 #define UCP_F_ALLCPUS \ 484 (UCP_F_I7 | UCP_F_WM) 485 486 #define UCP_F_CMASK 0xFF000000 487 488 static struct ucp_event_descr ucp_events[] = { 489 #undef UCPDESCR 490 #define UCPDESCR(N,EV,UM,FLAGS) { \ 491 .ucp_ev = PMC_EV_UCP_EVENT_##N, \ 492 .ucp_evcode = (EV), \ 493 .ucp_umask = (UM), \ 494 .ucp_flags = (FLAGS) \ 495 } 496 497 UCPDESCR(00H_01H, 0x00, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 498 UCPDESCR(00H_02H, 0x00, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 499 UCPDESCR(00H_04H, 0x00, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 500 501 UCPDESCR(01H_01H, 0x01, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 502 UCPDESCR(01H_02H, 0x01, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 503 UCPDESCR(01H_04H, 0x01, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 504 505 UCPDESCR(02H_01H, 0x02, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 506 UCPDESCR(03H_01H, 0x03, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 507 UCPDESCR(03H_02H, 0x03, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 508 UCPDESCR(03H_04H, 0x03, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 509 UCPDESCR(03H_08H, 0x03, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 510 UCPDESCR(03H_10H, 0x03, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 511 UCPDESCR(03H_20H, 0x03, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 512 UCPDESCR(03H_40H, 0x03, 0x40, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 513 514 UCPDESCR(04H_01H, 0x04, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 515 UCPDESCR(04H_02H, 0x04, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 516 UCPDESCR(04H_04H, 0x04, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 517 UCPDESCR(04H_08H, 0x04, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 518 UCPDESCR(04H_10H, 0x04, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 519 520 UCPDESCR(05H_01H, 0x05, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 521 UCPDESCR(05H_02H, 0x05, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 522 UCPDESCR(05H_04H, 0x05, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 523 524 UCPDESCR(06H_01H, 0x06, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 525 UCPDESCR(06H_02H, 0x06, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 526 UCPDESCR(06H_04H, 0x06, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 527 UCPDESCR(06H_08H, 0x06, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 528 UCPDESCR(06H_10H, 0x06, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 529 UCPDESCR(06H_20H, 0x06, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 530 531 UCPDESCR(07H_01H, 0x07, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 532 UCPDESCR(07H_02H, 0x07, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 533 UCPDESCR(07H_04H, 0x07, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 534 UCPDESCR(07H_08H, 0x07, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 535 UCPDESCR(07H_10H, 0x07, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 536 UCPDESCR(07H_20H, 0x07, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 537 UCPDESCR(07H_24H, 0x07, 0x24, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 538 539 UCPDESCR(08H_01H, 0x08, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 540 UCPDESCR(08H_02H, 0x08, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 541 UCPDESCR(08H_04H, 0x08, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 542 UCPDESCR(08H_03H, 0x08, 0x03, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 543 544 UCPDESCR(09H_01H, 0x09, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 545 UCPDESCR(09H_02H, 0x09, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 546 UCPDESCR(09H_04H, 0x09, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 547 UCPDESCR(09H_03H, 0x09, 0x03, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 548 549 UCPDESCR(0AH_01H, 0x0A, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 550 UCPDESCR(0AH_02H, 0x0A, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 551 UCPDESCR(0AH_04H, 0x0A, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 552 UCPDESCR(0AH_08H, 0x0A, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 553 UCPDESCR(0AH_0FH, 0x0A, 0x0F, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 554 555 UCPDESCR(0BH_01H, 0x0B, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 556 UCPDESCR(0BH_02H, 0x0B, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 557 UCPDESCR(0BH_04H, 0x0B, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 558 UCPDESCR(0BH_08H, 0x0B, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 559 UCPDESCR(0BH_10H, 0x0B, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 560 UCPDESCR(0BH_1FH, 0x0B, 0x1F, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 561 562 UCPDESCR(0CH_01H, 0x0C, 0x01, UCP_F_FM | UCP_F_WM), 563 UCPDESCR(0CH_02H, 0x0C, 0x02, UCP_F_FM | UCP_F_WM), 564 UCPDESCR(0CH_04H_E, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 565 UCPDESCR(0CH_04H_F, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 566 UCPDESCR(0CH_04H_M, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 567 UCPDESCR(0CH_04H_S, 0x0C, 0x04, UCP_F_FM | UCP_F_WM), 568 UCPDESCR(0CH_08H_E, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 569 UCPDESCR(0CH_08H_F, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 570 UCPDESCR(0CH_08H_M, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 571 UCPDESCR(0CH_08H_S, 0x0C, 0x08, UCP_F_FM | UCP_F_WM), 572 573 UCPDESCR(20H_01H, 0x20, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 574 UCPDESCR(20H_02H, 0x20, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 575 UCPDESCR(20H_04H, 0x20, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 576 UCPDESCR(20H_08H, 0x20, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 577 UCPDESCR(20H_10H, 0x20, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 578 UCPDESCR(20H_20H, 0x20, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 579 580 UCPDESCR(21H_01H, 0x21, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 581 UCPDESCR(21H_02H, 0x21, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 582 UCPDESCR(21H_04H, 0x21, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 583 584 UCPDESCR(22H_01H, 0x22, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM | 585 UCP_F_SB | UCP_F_HW), 586 UCPDESCR(22H_02H, 0x22, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM | 587 UCP_F_SB | UCP_F_HW), 588 UCPDESCR(22H_04H, 0x22, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM | 589 UCP_F_SB | UCP_F_HW), 590 UCPDESCR(22H_08H, 0x22, 0x08, UCP_F_FM | UCP_F_SB | UCP_F_HW), 591 UCPDESCR(22H_10H, 0x22, 0x10, UCP_F_FM | UCP_F_HW), 592 UCPDESCR(22H_20H, 0x22, 0x20, UCP_F_FM | UCP_F_SB | UCP_F_HW), 593 UCPDESCR(22H_40H, 0x22, 0x40, UCP_F_FM | UCP_F_SB | UCP_F_HW), 594 UCPDESCR(22H_80H, 0x22, 0x80, UCP_F_FM | UCP_F_SB | UCP_F_HW), 595 596 UCPDESCR(23H_01H, 0x23, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 597 UCPDESCR(23H_02H, 0x23, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 598 UCPDESCR(23H_04H, 0x23, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 599 600 UCPDESCR(24H_02H, 0x24, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 601 UCPDESCR(24H_04H, 0x24, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 602 603 UCPDESCR(25H_01H, 0x25, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 604 UCPDESCR(25H_02H, 0x25, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 605 UCPDESCR(25H_04H, 0x25, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 606 607 UCPDESCR(26H_01H, 0x26, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 608 609 UCPDESCR(27H_01H, 0x27, 0x01, UCP_F_FM | UCP_F_I7), 610 UCPDESCR(27H_02H, 0x27, 0x02, UCP_F_FM | UCP_F_I7), 611 UCPDESCR(27H_04H, 0x27, 0x04, UCP_F_FM | UCP_F_I7), 612 UCPDESCR(27H_08H, 0x27, 0x08, UCP_F_FM | UCP_F_I7), 613 UCPDESCR(27H_10H, 0x27, 0x10, UCP_F_FM | UCP_F_I7), 614 UCPDESCR(27H_20H, 0x27, 0x20, UCP_F_FM | UCP_F_I7), 615 616 UCPDESCR(28H_01H, 0x28, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 617 UCPDESCR(28H_02H, 0x28, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 618 UCPDESCR(28H_04H, 0x28, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 619 UCPDESCR(28H_08H, 0x28, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 620 UCPDESCR(28H_10H, 0x28, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 621 UCPDESCR(28H_20H, 0x28, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 622 623 UCPDESCR(29H_01H, 0x29, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 624 UCPDESCR(29H_02H, 0x29, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 625 UCPDESCR(29H_04H, 0x29, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 626 UCPDESCR(29H_08H, 0x29, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 627 UCPDESCR(29H_10H, 0x29, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 628 UCPDESCR(29H_20H, 0x29, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 629 630 UCPDESCR(2AH_01H, 0x2A, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 631 UCPDESCR(2AH_02H, 0x2A, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 632 UCPDESCR(2AH_04H, 0x2A, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 633 UCPDESCR(2AH_07H, 0x2A, 0x07, UCP_F_FM | UCP_F_WM), 634 635 UCPDESCR(2BH_01H, 0x2B, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 636 UCPDESCR(2BH_02H, 0x2B, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 637 UCPDESCR(2BH_04H, 0x2B, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 638 UCPDESCR(2BH_07H, 0x2B, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 639 640 UCPDESCR(2CH_01H, 0x2C, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 641 UCPDESCR(2CH_02H, 0x2C, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 642 UCPDESCR(2CH_04H, 0x2C, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 643 UCPDESCR(2CH_07H, 0x2C, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 644 645 UCPDESCR(2DH_01H, 0x2D, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 646 UCPDESCR(2DH_02H, 0x2D, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 647 UCPDESCR(2DH_04H, 0x2D, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 648 UCPDESCR(2DH_07H, 0x2D, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 649 650 UCPDESCR(2EH_01H, 0x2E, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 651 UCPDESCR(2EH_02H, 0x2E, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 652 UCPDESCR(2EH_04H, 0x2E, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 653 UCPDESCR(2EH_07H, 0x2E, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 654 655 UCPDESCR(2FH_01H, 0x2F, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 656 UCPDESCR(2FH_02H, 0x2F, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 657 UCPDESCR(2FH_04H, 0x2F, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 658 UCPDESCR(2FH_07H, 0x2F, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 659 UCPDESCR(2FH_08H, 0x2F, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 660 UCPDESCR(2FH_10H, 0x2F, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 661 UCPDESCR(2FH_20H, 0x2F, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 662 UCPDESCR(2FH_38H, 0x2F, 0x38, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 663 664 UCPDESCR(30H_01H, 0x30, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 665 UCPDESCR(30H_02H, 0x30, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 666 UCPDESCR(30H_04H, 0x30, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 667 UCPDESCR(30H_07H, 0x30, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 668 669 UCPDESCR(31H_01H, 0x31, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 670 UCPDESCR(31H_02H, 0x31, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 671 UCPDESCR(31H_04H, 0x31, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 672 UCPDESCR(31H_07H, 0x31, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 673 674 UCPDESCR(32H_01H, 0x32, 0x01, UCP_F_FM | UCP_F_WM), 675 UCPDESCR(32H_02H, 0x32, 0x02, UCP_F_FM | UCP_F_WM), 676 UCPDESCR(32H_04H, 0x32, 0x04, UCP_F_FM | UCP_F_WM), 677 UCPDESCR(32H_07H, 0x32, 0x07, UCP_F_FM | UCP_F_WM), 678 679 UCPDESCR(33H_01H, 0x33, 0x01, UCP_F_FM | UCP_F_WM), 680 UCPDESCR(33H_02H, 0x33, 0x02, UCP_F_FM | UCP_F_WM), 681 UCPDESCR(33H_04H, 0x33, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 682 UCPDESCR(33H_07H, 0x33, 0x07, UCP_F_FM | UCP_F_WM), 683 684 UCPDESCR(34H_01H, 0x34, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 685 UCP_F_HW), 686 UCPDESCR(34H_02H, 0x34, 0x02, UCP_F_FM | UCP_F_WM | UCP_F_SB), 687 UCPDESCR(34H_04H, 0x34, 0x04, UCP_F_FM | UCP_F_WM | UCP_F_SB), 688 UCPDESCR(34H_06H, 0x34, 0x06, UCP_F_FM | UCP_F_HW), 689 UCPDESCR(34H_08H, 0x34, 0x08, UCP_F_FM | UCP_F_WM | UCP_F_SB | 690 UCP_F_HW), 691 UCPDESCR(34H_10H, 0x34, 0x10, UCP_F_FM | UCP_F_WM | UCP_F_SB | 692 UCP_F_HW), 693 UCPDESCR(34H_20H, 0x34, 0x20, UCP_F_FM | UCP_F_WM | UCP_F_SB | 694 UCP_F_HW), 695 UCPDESCR(34H_40H, 0x34, 0x40, UCP_F_FM | UCP_F_SB | UCP_F_HW), 696 UCPDESCR(34H_80H, 0x34, 0x80, UCP_F_FM | UCP_F_SB | UCP_F_HW), 697 698 UCPDESCR(35H_01H, 0x35, 0x01, UCP_F_FM | UCP_F_WM), 699 UCPDESCR(35H_02H, 0x35, 0x02, UCP_F_FM | UCP_F_WM), 700 UCPDESCR(35H_04H, 0x35, 0x04, UCP_F_FM | UCP_F_WM), 701 702 UCPDESCR(40H_01H, 0x40, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 703 UCPDESCR(40H_02H, 0x40, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 704 UCPDESCR(40H_04H, 0x40, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 705 UCPDESCR(40H_08H, 0x40, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 706 UCPDESCR(40H_10H, 0x40, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 707 UCPDESCR(40H_20H, 0x40, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 708 UCPDESCR(40H_07H, 0x40, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 709 UCPDESCR(40H_38H, 0x40, 0x38, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 710 711 UCPDESCR(41H_01H, 0x41, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 712 UCPDESCR(41H_02H, 0x41, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 713 UCPDESCR(41H_04H, 0x41, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 714 UCPDESCR(41H_08H, 0x41, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 715 UCPDESCR(41H_10H, 0x41, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 716 UCPDESCR(41H_20H, 0x41, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 717 UCPDESCR(41H_07H, 0x41, 0x07, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 718 UCPDESCR(41H_38H, 0x41, 0x38, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 719 720 UCPDESCR(42H_01H, 0x42, 0x01, UCP_F_FM | UCP_F_WM), 721 UCPDESCR(42H_02H, 0x42, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 722 UCPDESCR(42H_04H, 0x42, 0x04, UCP_F_FM | UCP_F_WM), 723 UCPDESCR(42H_08H, 0x42, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 724 725 UCPDESCR(43H_01H, 0x43, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 726 UCPDESCR(43H_02H, 0x43, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 727 728 UCPDESCR(60H_01H, 0x60, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 729 UCPDESCR(60H_02H, 0x60, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 730 UCPDESCR(60H_04H, 0x60, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 731 732 UCPDESCR(61H_01H, 0x61, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 733 UCPDESCR(61H_02H, 0x61, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 734 UCPDESCR(61H_04H, 0x61, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 735 736 UCPDESCR(62H_01H, 0x62, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 737 UCPDESCR(62H_02H, 0x62, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 738 UCPDESCR(62H_04H, 0x62, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 739 740 UCPDESCR(63H_01H, 0x63, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 741 UCPDESCR(63H_02H, 0x63, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 742 UCPDESCR(63H_04H, 0x63, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 743 UCPDESCR(63H_08H, 0x63, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 744 UCPDESCR(63H_10H, 0x63, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 745 UCPDESCR(63H_20H, 0x63, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 746 747 UCPDESCR(64H_01H, 0x64, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 748 UCPDESCR(64H_02H, 0x64, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 749 UCPDESCR(64H_04H, 0x64, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 750 UCPDESCR(64H_08H, 0x64, 0x08, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 751 UCPDESCR(64H_10H, 0x64, 0x10, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 752 UCPDESCR(64H_20H, 0x64, 0x20, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 753 754 UCPDESCR(65H_01H, 0x65, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 755 UCPDESCR(65H_02H, 0x65, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 756 UCPDESCR(65H_04H, 0x65, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 757 758 UCPDESCR(66H_01H, 0x66, 0x01, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 759 UCPDESCR(66H_02H, 0x66, 0x02, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 760 UCPDESCR(66H_04H, 0x66, 0x04, UCP_F_FM | UCP_F_I7 | UCP_F_WM), 761 762 UCPDESCR(67H_01H, 0x67, 0x01, UCP_F_FM | UCP_F_WM), 763 764 UCPDESCR(80H_01H, 0x80, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 765 UCP_F_HW), 766 UCPDESCR(80H_02H, 0x80, 0x02, UCP_F_FM | UCP_F_WM), 767 UCPDESCR(80H_04H, 0x80, 0x04, UCP_F_FM | UCP_F_WM), 768 UCPDESCR(80H_08H, 0x80, 0x08, UCP_F_FM | UCP_F_WM), 769 770 UCPDESCR(81H_01H, 0x81, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 771 UCP_F_HW), 772 UCPDESCR(81H_02H, 0x81, 0x02, UCP_F_FM | UCP_F_WM), 773 UCPDESCR(81H_04H, 0x81, 0x04, UCP_F_FM | UCP_F_WM), 774 UCPDESCR(81H_08H, 0x81, 0x08, UCP_F_FM | UCP_F_WM), 775 UCPDESCR(81H_20H, 0x81, 0x20, UCP_F_FM | UCP_F_SB | UCP_F_HW), 776 UCPDESCR(81H_80H, 0x81, 0x80, UCP_F_FM | UCP_F_SB | UCP_F_HW), 777 778 UCPDESCR(82H_01H, 0x82, 0x01, UCP_F_FM | UCP_F_WM), 779 780 UCPDESCR(83H_01H, 0x83, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 781 UCP_F_HW), 782 UCPDESCR(83H_02H, 0x83, 0x02, UCP_F_FM | UCP_F_WM), 783 UCPDESCR(83H_04H, 0x83, 0x04, UCP_F_FM | UCP_F_WM), 784 UCPDESCR(83H_08H, 0x83, 0x08, UCP_F_FM | UCP_F_WM), 785 786 UCPDESCR(84H_01H, 0x84, 0x01, UCP_F_FM | UCP_F_WM | UCP_F_SB | 787 UCP_F_HW), 788 UCPDESCR(84H_02H, 0x84, 0x02, UCP_F_FM | UCP_F_WM), 789 UCPDESCR(84H_04H, 0x84, 0x04, UCP_F_FM | UCP_F_WM), 790 UCPDESCR(84H_08H, 0x84, 0x08, UCP_F_FM | UCP_F_WM), 791 UCPDESCR(85H_02H, 0x85, 0x02, UCP_F_FM | UCP_F_WM), 792 UCPDESCR(86H_01H, 0x86, 0x01, UCP_F_FM | UCP_F_WM) 793 }; 794 795 static pmc_value_t 796 ucp_perfctr_value_to_reload_count(pmc_value_t v) 797 { 798 v &= (1ULL << uncore_ucp_width) - 1; 799 return (1ULL << uncore_ucp_width) - v; 800 } 801 802 static pmc_value_t 803 ucp_reload_count_to_perfctr_value(pmc_value_t rlc) 804 { 805 return (1ULL << uncore_ucp_width) - rlc; 806 } 807 808 /* 809 * Counter specific event information for Sandybridge and Haswell 810 */ 811 static int 812 ucp_event_sb_hw_ok_on_counter(enum pmc_event pe, int ri) 813 { 814 uint32_t mask; 815 816 switch (pe) { 817 /* 818 * Events valid only on counter 0. 819 */ 820 case PMC_EV_UCP_EVENT_80H_01H: 821 case PMC_EV_UCP_EVENT_83H_01H: 822 mask = (1 << 0); 823 break; 824 825 default: 826 mask = ~0; /* Any row index is ok. */ 827 } 828 829 return (mask & (1 << ri)); 830 } 831 832 static int 833 ucp_allocate_pmc(int cpu, int ri, struct pmc *pm, 834 const struct pmc_op_pmcallocate *a) 835 { 836 int n; 837 enum pmc_event ev; 838 struct ucp_event_descr *ie; 839 uint32_t caps, config, cpuflag, evsel; 840 841 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 842 ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 843 KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 844 ("[uncore,%d] illegal row-index value %d", __LINE__, ri)); 845 846 /* check requested capabilities */ 847 caps = a->pm_caps; 848 if ((UCP_PMC_CAPS & caps) != caps) 849 return (EPERM); 850 851 ev = pm->pm_event; 852 853 switch (uncore_cputype) { 854 case PMC_CPU_INTEL_HASWELL: 855 case PMC_CPU_INTEL_SANDYBRIDGE: 856 if (ucp_event_sb_hw_ok_on_counter(ev, ri) == 0) 857 return (EINVAL); 858 break; 859 default: 860 break; 861 } 862 863 864 /* 865 * Look for an event descriptor with matching CPU and event id 866 * fields. 867 */ 868 869 switch (uncore_cputype) { 870 case PMC_CPU_INTEL_COREI7: 871 cpuflag = UCP_F_I7; 872 break; 873 case PMC_CPU_INTEL_HASWELL: 874 cpuflag = UCP_F_HW; 875 break; 876 case PMC_CPU_INTEL_SANDYBRIDGE: 877 cpuflag = UCP_F_SB; 878 break; 879 case PMC_CPU_INTEL_WESTMERE: 880 cpuflag = UCP_F_WM; 881 break; 882 default: 883 return (EINVAL); 884 } 885 886 for (n = 0, ie = ucp_events; n < nitems(ucp_events); n++, ie++) 887 if (ie->ucp_ev == ev && ie->ucp_flags & cpuflag) 888 break; 889 890 if (n == nitems(ucp_events)) 891 return (EINVAL); 892 893 /* 894 * A matching event descriptor has been found, so start 895 * assembling the contents of the event select register. 896 */ 897 evsel = ie->ucp_evcode | UCP_EN; 898 899 config = a->pm_md.pm_ucp.pm_ucp_config & ~UCP_F_CMASK; 900 901 /* 902 * If the event uses a fixed umask value, reject any umask 903 * bits set by the user. 904 */ 905 if (ie->ucp_flags & UCP_F_FM) { 906 907 if (UCP_UMASK(config) != 0) 908 return (EINVAL); 909 910 evsel |= (ie->ucp_umask << 8); 911 912 } else 913 return (EINVAL); 914 915 if (caps & PMC_CAP_THRESHOLD) 916 evsel |= (a->pm_md.pm_ucp.pm_ucp_config & UCP_F_CMASK); 917 if (caps & PMC_CAP_EDGE) 918 evsel |= UCP_EDGE; 919 if (caps & PMC_CAP_INVERT) 920 evsel |= UCP_INV; 921 922 pm->pm_md.pm_ucp.pm_ucp_evsel = evsel; 923 924 return (0); 925 } 926 927 static int 928 ucp_config_pmc(int cpu, int ri, struct pmc *pm) 929 { 930 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 931 ("[uncore,%d] illegal CPU %d", __LINE__, cpu)); 932 933 KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 934 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 935 936 PMCDBG3(MDP,CFG,1, "ucp-config cpu=%d ri=%d pm=%p", cpu, ri, pm); 937 938 KASSERT(uncore_pcpu[cpu] != NULL, ("[uncore,%d] null per-cpu %d", __LINE__, 939 cpu)); 940 941 uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc = pm; 942 943 return (0); 944 } 945 946 static int 947 ucp_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 948 { 949 int error; 950 struct pmc_hw *phw; 951 char ucp_name[PMC_NAME_MAX]; 952 953 phw = &uncore_pcpu[cpu]->pc_uncorepmcs[ri]; 954 955 (void) snprintf(ucp_name, sizeof(ucp_name), "UCP-%d", ri); 956 if ((error = copystr(ucp_name, pi->pm_name, PMC_NAME_MAX, 957 NULL)) != 0) 958 return (error); 959 960 pi->pm_class = PMC_CLASS_UCP; 961 962 if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 963 pi->pm_enabled = TRUE; 964 *ppmc = phw->phw_pmc; 965 } else { 966 pi->pm_enabled = FALSE; 967 *ppmc = NULL; 968 } 969 970 return (0); 971 } 972 973 static int 974 ucp_get_config(int cpu, int ri, struct pmc **ppm) 975 { 976 *ppm = uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc; 977 978 return (0); 979 } 980 981 static int 982 ucp_read_pmc(int cpu, int ri, pmc_value_t *v) 983 { 984 struct pmc *pm; 985 pmc_value_t tmp; 986 987 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 988 ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 989 KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 990 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 991 992 pm = uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc; 993 994 KASSERT(pm, 995 ("[uncore,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, 996 ri)); 997 998 tmp = rdmsr(UCP_PMC0 + ri); 999 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 1000 *v = ucp_perfctr_value_to_reload_count(tmp); 1001 else 1002 *v = tmp; 1003 1004 PMCDBG4(MDP,REA,1, "ucp-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri, 1005 ri, *v); 1006 1007 return (0); 1008 } 1009 1010 static int 1011 ucp_release_pmc(int cpu, int ri, struct pmc *pm) 1012 { 1013 (void) pm; 1014 1015 PMCDBG3(MDP,REL,1, "ucp-release cpu=%d ri=%d pm=%p", cpu, ri, 1016 pm); 1017 1018 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1019 ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 1020 KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1021 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 1022 1023 KASSERT(uncore_pcpu[cpu]->pc_uncorepmcs[ri].phw_pmc 1024 == NULL, ("[uncore,%d] PHW pmc non-NULL", __LINE__)); 1025 1026 return (0); 1027 } 1028 1029 static int 1030 ucp_start_pmc(int cpu, int ri) 1031 { 1032 struct pmc *pm; 1033 uint32_t evsel; 1034 struct uncore_cpu *cc; 1035 1036 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1037 ("[uncore,%d] illegal CPU value %d", __LINE__, cpu)); 1038 KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1039 ("[uncore,%d] illegal row-index %d", __LINE__, ri)); 1040 1041 cc = uncore_pcpu[cpu]; 1042 pm = cc->pc_uncorepmcs[ri].phw_pmc; 1043 1044 KASSERT(pm, 1045 ("[uncore,%d] starting cpu%d,ri%d with no pmc configured", 1046 __LINE__, cpu, ri)); 1047 1048 PMCDBG2(MDP,STA,1, "ucp-start cpu=%d ri=%d", cpu, ri); 1049 1050 evsel = pm->pm_md.pm_ucp.pm_ucp_evsel; 1051 1052 PMCDBG4(MDP,STA,2, 1053 "ucp-start/2 cpu=%d ri=%d evselmsr=0x%x evsel=0x%x", 1054 cpu, ri, SELECTSEL(uncore_cputype) + ri, evsel); 1055 1056 /* Event specific configuration. */ 1057 switch (pm->pm_event) { 1058 case PMC_EV_UCP_EVENT_0CH_04H_E: 1059 case PMC_EV_UCP_EVENT_0CH_08H_E: 1060 wrmsr(MSR_GQ_SNOOP_MESF,0x2); 1061 break; 1062 case PMC_EV_UCP_EVENT_0CH_04H_F: 1063 case PMC_EV_UCP_EVENT_0CH_08H_F: 1064 wrmsr(MSR_GQ_SNOOP_MESF,0x8); 1065 break; 1066 case PMC_EV_UCP_EVENT_0CH_04H_M: 1067 case PMC_EV_UCP_EVENT_0CH_08H_M: 1068 wrmsr(MSR_GQ_SNOOP_MESF,0x1); 1069 break; 1070 case PMC_EV_UCP_EVENT_0CH_04H_S: 1071 case PMC_EV_UCP_EVENT_0CH_08H_S: 1072 wrmsr(MSR_GQ_SNOOP_MESF,0x4); 1073 break; 1074 default: 1075 break; 1076 } 1077 1078 wrmsr(SELECTSEL(uncore_cputype) + ri, evsel); 1079 1080 do { 1081 cc->pc_resync = 0; 1082 cc->pc_globalctrl |= (1ULL << ri); 1083 wrmsr(UC_GLOBAL_CTRL, cc->pc_globalctrl); 1084 } while (cc->pc_resync != 0); 1085 1086 return (0); 1087 } 1088 1089 static int 1090 ucp_stop_pmc(int cpu, int ri) 1091 { 1092 struct pmc *pm; 1093 struct uncore_cpu *cc; 1094 1095 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1096 ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 1097 KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1098 ("[uncore,%d] illegal row index %d", __LINE__, ri)); 1099 1100 cc = uncore_pcpu[cpu]; 1101 pm = cc->pc_uncorepmcs[ri].phw_pmc; 1102 1103 KASSERT(pm, 1104 ("[uncore,%d] cpu%d ri%d no configured PMC to stop", __LINE__, 1105 cpu, ri)); 1106 1107 PMCDBG2(MDP,STO,1, "ucp-stop cpu=%d ri=%d", cpu, ri); 1108 1109 /* stop hw. */ 1110 wrmsr(SELECTSEL(uncore_cputype) + ri, 0); 1111 1112 do { 1113 cc->pc_resync = 0; 1114 cc->pc_globalctrl &= ~(1ULL << ri); 1115 wrmsr(UC_GLOBAL_CTRL, cc->pc_globalctrl); 1116 } while (cc->pc_resync != 0); 1117 1118 return (0); 1119 } 1120 1121 static int 1122 ucp_write_pmc(int cpu, int ri, pmc_value_t v) 1123 { 1124 struct pmc *pm; 1125 struct uncore_cpu *cc; 1126 1127 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 1128 ("[uncore,%d] illegal cpu value %d", __LINE__, cpu)); 1129 KASSERT(ri >= 0 && ri < uncore_ucp_npmc, 1130 ("[uncore,%d] illegal row index %d", __LINE__, ri)); 1131 1132 cc = uncore_pcpu[cpu]; 1133 pm = cc->pc_uncorepmcs[ri].phw_pmc; 1134 1135 KASSERT(pm, 1136 ("[uncore,%d] cpu%d ri%d no configured PMC to stop", __LINE__, 1137 cpu, ri)); 1138 1139 PMCDBG4(MDP,WRI,1, "ucp-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri, 1140 UCP_PMC0 + ri, v); 1141 1142 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 1143 v = ucp_reload_count_to_perfctr_value(v); 1144 1145 /* 1146 * Write the new value to the counter. The counter will be in 1147 * a stopped state when the pcd_write() entry point is called. 1148 */ 1149 1150 wrmsr(UCP_PMC0 + ri, v); 1151 1152 return (0); 1153 } 1154 1155 1156 static void 1157 ucp_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth) 1158 { 1159 struct pmc_classdep *pcd; 1160 1161 KASSERT(md != NULL, ("[ucp,%d] md is NULL", __LINE__)); 1162 1163 PMCDBG0(MDP,INI,1, "ucp-initialize"); 1164 1165 pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_UCP]; 1166 1167 pcd->pcd_caps = UCP_PMC_CAPS; 1168 pcd->pcd_class = PMC_CLASS_UCP; 1169 pcd->pcd_num = npmc; 1170 pcd->pcd_ri = md->pmd_npmc; 1171 pcd->pcd_width = pmcwidth; 1172 1173 pcd->pcd_allocate_pmc = ucp_allocate_pmc; 1174 pcd->pcd_config_pmc = ucp_config_pmc; 1175 pcd->pcd_describe = ucp_describe; 1176 pcd->pcd_get_config = ucp_get_config; 1177 pcd->pcd_get_msr = NULL; 1178 pcd->pcd_pcpu_fini = uncore_pcpu_fini; 1179 pcd->pcd_pcpu_init = uncore_pcpu_init; 1180 pcd->pcd_read_pmc = ucp_read_pmc; 1181 pcd->pcd_release_pmc = ucp_release_pmc; 1182 pcd->pcd_start_pmc = ucp_start_pmc; 1183 pcd->pcd_stop_pmc = ucp_stop_pmc; 1184 pcd->pcd_write_pmc = ucp_write_pmc; 1185 1186 md->pmd_npmc += npmc; 1187 } 1188 1189 int 1190 pmc_uncore_initialize(struct pmc_mdep *md, int maxcpu) 1191 { 1192 uncore_cputype = md->pmd_cputype; 1193 uncore_pmcmask = 0; 1194 1195 /* 1196 * Initialize programmable counters. 1197 */ 1198 1199 uncore_ucp_npmc = 8; 1200 uncore_ucp_width = 48; 1201 1202 uncore_pmcmask |= ((1ULL << uncore_ucp_npmc) - 1); 1203 1204 ucp_initialize(md, maxcpu, uncore_ucp_npmc, uncore_ucp_width); 1205 1206 /* 1207 * Initialize fixed function counters, if present. 1208 */ 1209 uncore_ucf_ri = uncore_ucp_npmc; 1210 uncore_ucf_npmc = 1; 1211 uncore_ucf_width = 48; 1212 1213 ucf_initialize(md, maxcpu, uncore_ucf_npmc, uncore_ucf_width); 1214 uncore_pmcmask |= ((1ULL << uncore_ucf_npmc) - 1) << SELECTOFF(uncore_cputype); 1215 1216 PMCDBG2(MDP,INI,1,"uncore-init pmcmask=0x%jx ucfri=%d", uncore_pmcmask, 1217 uncore_ucf_ri); 1218 1219 uncore_pcpu = malloc(sizeof(*uncore_pcpu) * maxcpu, M_PMC, 1220 M_ZERO | M_WAITOK); 1221 1222 return (0); 1223 } 1224 1225 void 1226 pmc_uncore_finalize(struct pmc_mdep *md) 1227 { 1228 PMCDBG0(MDP,INI,1, "uncore-finalize"); 1229 1230 free(uncore_pcpu, M_PMC); 1231 uncore_pcpu = NULL; 1232 } 1233