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