1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * CPU Module Interface - hardware abstraction. 29 */ 30 31 #ifdef __xpv 32 #include <sys/xpv_user.h> 33 #endif 34 35 #include <sys/types.h> 36 #include <sys/cpu_module.h> 37 #include <sys/kmem.h> 38 #include <sys/x86_archext.h> 39 #include <sys/cpuvar.h> 40 #include <sys/ksynch.h> 41 #include <sys/x_call.h> 42 #include <sys/pghw.h> 43 #include <sys/pci_cfgspace.h> 44 #include <sys/archsystm.h> 45 #include <sys/ontrap.h> 46 #include <sys/controlregs.h> 47 #include <sys/sunddi.h> 48 #include <sys/trap.h> 49 #include <sys/mca_x86.h> 50 #include <sys/processor.h> 51 52 /* 53 * Outside of this file consumers use the opaque cmi_hdl_t. This 54 * definition is duplicated in the generic_cpu mdb module, so keep 55 * them in-sync when making changes. 56 */ 57 typedef struct cmi_hdl_impl { 58 enum cmi_hdl_class cmih_class; /* Handle nature */ 59 const struct cmi_hdl_ops *cmih_ops; /* Operations vector */ 60 uint_t cmih_chipid; /* Chipid of cpu resource */ 61 uint_t cmih_coreid; /* Core within die */ 62 uint_t cmih_strandid; /* Thread within core */ 63 boolean_t cmih_mstrand; /* cores are multithreaded */ 64 volatile uint32_t *cmih_refcntp; /* Reference count pointer */ 65 uint64_t cmih_msrsrc; /* MSR data source flags */ 66 void *cmih_hdlpriv; /* cmi_hw.c private data */ 67 void *cmih_spec; /* cmi_hdl_{set,get}_specific */ 68 void *cmih_cmi; /* cpu mod control structure */ 69 void *cmih_cmidata; /* cpu mod private data */ 70 const struct cmi_mc_ops *cmih_mcops; /* Memory-controller ops */ 71 void *cmih_mcdata; /* Memory-controller data */ 72 uint64_t cmih_flags; /* See CMIH_F_* below */ 73 } cmi_hdl_impl_t; 74 75 #define IMPLHDL(ophdl) ((cmi_hdl_impl_t *)ophdl) 76 #define HDLOPS(hdl) ((hdl)->cmih_ops) 77 78 #define CMIH_F_INJACTV 0x1ULL 79 80 /* 81 * Ops structure for handle operations. 82 */ 83 struct cmi_hdl_ops { 84 /* 85 * These ops are required in an implementation. 86 */ 87 uint_t (*cmio_vendor)(cmi_hdl_impl_t *); 88 const char *(*cmio_vendorstr)(cmi_hdl_impl_t *); 89 uint_t (*cmio_family)(cmi_hdl_impl_t *); 90 uint_t (*cmio_model)(cmi_hdl_impl_t *); 91 uint_t (*cmio_stepping)(cmi_hdl_impl_t *); 92 uint_t (*cmio_chipid)(cmi_hdl_impl_t *); 93 uint_t (*cmio_coreid)(cmi_hdl_impl_t *); 94 uint_t (*cmio_strandid)(cmi_hdl_impl_t *); 95 uint32_t (*cmio_chiprev)(cmi_hdl_impl_t *); 96 const char *(*cmio_chiprevstr)(cmi_hdl_impl_t *); 97 uint32_t (*cmio_getsockettype)(cmi_hdl_impl_t *); 98 const char *(*cmio_getsocketstr)(cmi_hdl_impl_t *); 99 100 id_t (*cmio_logical_id)(cmi_hdl_impl_t *); 101 /* 102 * These ops are optional in an implementation. 103 */ 104 ulong_t (*cmio_getcr4)(cmi_hdl_impl_t *); 105 void (*cmio_setcr4)(cmi_hdl_impl_t *, ulong_t); 106 cmi_errno_t (*cmio_rdmsr)(cmi_hdl_impl_t *, uint_t, uint64_t *); 107 cmi_errno_t (*cmio_wrmsr)(cmi_hdl_impl_t *, uint_t, uint64_t); 108 cmi_errno_t (*cmio_msrinterpose)(cmi_hdl_impl_t *, uint_t, uint64_t); 109 void (*cmio_int)(cmi_hdl_impl_t *, int); 110 int (*cmio_online)(cmi_hdl_impl_t *, int, int *); 111 }; 112 113 static const struct cmi_hdl_ops cmi_hdl_ops; 114 115 /* 116 * Handles are looked up from contexts such as polling, injection etc 117 * where the context is reasonably well defined (although a poller could 118 * interrupt any old thread holding any old lock). They are also looked 119 * up by machine check handlers, which may strike at inconvenient times 120 * such as during handle initialization or destruction or during handle 121 * lookup (which the #MC handler itself will also have to perform). 122 * 123 * So keeping handles in a linked list makes locking difficult when we 124 * consider #MC handlers. Our solution is to have a look-up table indexed 125 * by that which uniquely identifies a handle - chip/core/strand id - 126 * with each entry a structure including a pointer to a handle 127 * structure for the resource, and a reference count for the handle. 128 * Reference counts are modified atomically. The public cmi_hdl_hold 129 * always succeeds because this can only be used after handle creation 130 * and before the call to destruct, so the hold count is already at least one. 131 * In other functions that lookup a handle (cmi_hdl_lookup, cmi_hdl_any) 132 * we must be certain that the count has not already decrmented to zero 133 * before applying our hold. 134 * 135 * The table is an array of maximum number of chips defined in 136 * CMI_CHIPID_ARR_SZ indexed by the chip id. If the chip is not present, the 137 * entry is NULL. Each entry is a pointer to another array which contains a 138 * list of all strands of the chip. This first level table is allocated when 139 * first we want to populate an entry. The size of the latter (per chip) table 140 * is CMI_MAX_STRANDS_PER_CHIP and it is populated when one of its cpus starts. 141 * 142 * Ideally we should only allocate to the actual number of chips, cores per 143 * chip and strand per core. The number of chips is not available until all 144 * of them are passed. The number of cores and strands are partially available. 145 * For now we stick with the above approach. 146 */ 147 #define CMI_MAX_CHIPID_NBITS 6 /* max chipid of 63 */ 148 #define CMI_MAX_CORES_PER_CHIP_NBITS 4 /* 16 cores per chip max */ 149 #define CMI_MAX_STRANDS_PER_CORE_NBITS 3 /* 8 strands per core max */ 150 151 #define CMI_MAX_CHIPID ((1 << (CMI_MAX_CHIPID_NBITS)) - 1) 152 #define CMI_MAX_CORES_PER_CHIP (1 << CMI_MAX_CORES_PER_CHIP_NBITS) 153 #define CMI_MAX_STRANDS_PER_CORE (1 << CMI_MAX_STRANDS_PER_CORE_NBITS) 154 #define CMI_MAX_STRANDS_PER_CHIP (CMI_MAX_CORES_PER_CHIP * \ 155 CMI_MAX_STRANDS_PER_CORE) 156 157 /* 158 * Handle array indexing within a per-chip table 159 * [6:3] = Core in package, 160 * [2:0] = Strand in core, 161 */ 162 #define CMI_HDL_ARR_IDX_CORE(coreid) \ 163 (((coreid) & (CMI_MAX_CORES_PER_CHIP - 1)) << \ 164 CMI_MAX_STRANDS_PER_CORE_NBITS) 165 166 #define CMI_HDL_ARR_IDX_STRAND(strandid) \ 167 (((strandid) & (CMI_MAX_STRANDS_PER_CORE - 1))) 168 169 #define CMI_HDL_ARR_IDX(coreid, strandid) \ 170 (CMI_HDL_ARR_IDX_CORE(coreid) | CMI_HDL_ARR_IDX_STRAND(strandid)) 171 172 #define CMI_CHIPID_ARR_SZ (1 << CMI_MAX_CHIPID_NBITS) 173 174 typedef struct cmi_hdl_ent { 175 volatile uint32_t cmae_refcnt; 176 cmi_hdl_impl_t *cmae_hdlp; 177 } cmi_hdl_ent_t; 178 179 static cmi_hdl_ent_t *cmi_chip_tab[CMI_CHIPID_ARR_SZ]; 180 181 /* 182 * Controls where we will source PCI config space data. 183 */ 184 #define CMI_PCICFG_FLAG_RD_HWOK 0x0001 185 #define CMI_PCICFG_FLAG_RD_INTERPOSEOK 0X0002 186 #define CMI_PCICFG_FLAG_WR_HWOK 0x0004 187 #define CMI_PCICFG_FLAG_WR_INTERPOSEOK 0X0008 188 189 static uint64_t cmi_pcicfg_flags = 190 CMI_PCICFG_FLAG_RD_HWOK | CMI_PCICFG_FLAG_RD_INTERPOSEOK | 191 CMI_PCICFG_FLAG_WR_HWOK | CMI_PCICFG_FLAG_WR_INTERPOSEOK; 192 193 /* 194 * The flags for individual cpus are kept in their per-cpu handle cmih_msrsrc 195 */ 196 #define CMI_MSR_FLAG_RD_HWOK 0x0001 197 #define CMI_MSR_FLAG_RD_INTERPOSEOK 0x0002 198 #define CMI_MSR_FLAG_WR_HWOK 0x0004 199 #define CMI_MSR_FLAG_WR_INTERPOSEOK 0x0008 200 201 int cmi_call_func_ntv_tries = 3; 202 203 static cmi_errno_t 204 call_func_ntv(int cpuid, xc_func_t func, xc_arg_t arg1, xc_arg_t arg2) 205 { 206 cmi_errno_t rc = -1; 207 int i; 208 209 kpreempt_disable(); 210 211 if (CPU->cpu_id == cpuid) { 212 (*func)(arg1, arg2, (xc_arg_t)&rc); 213 } else { 214 /* 215 * This should not happen for a #MC trap or a poll, so 216 * this is likely an error injection or similar. 217 * We will try to cross call with xc_trycall - we 218 * can't guarantee success with xc_call because 219 * the interrupt code in the case of a #MC may 220 * already hold the xc mutex. 221 */ 222 for (i = 0; i < cmi_call_func_ntv_tries; i++) { 223 cpuset_t cpus; 224 225 CPUSET_ONLY(cpus, cpuid); 226 xc_priority(arg1, arg2, (xc_arg_t)&rc, 227 CPUSET2BV(cpus), func); 228 if (rc != -1) 229 break; 230 231 DELAY(1); 232 } 233 } 234 235 kpreempt_enable(); 236 237 return (rc != -1 ? rc : CMIERR_DEADLOCK); 238 } 239 240 static uint64_t injcnt; 241 242 void 243 cmi_hdl_inj_begin(cmi_hdl_t ophdl) 244 { 245 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 246 247 if (hdl != NULL) 248 hdl->cmih_flags |= CMIH_F_INJACTV; 249 if (injcnt++ == 0) { 250 cmn_err(CE_NOTE, "Hardware error injection/simulation " 251 "activity noted"); 252 } 253 } 254 255 void 256 cmi_hdl_inj_end(cmi_hdl_t ophdl) 257 { 258 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 259 260 ASSERT(hdl == NULL || hdl->cmih_flags & CMIH_F_INJACTV); 261 if (hdl != NULL) 262 hdl->cmih_flags &= ~CMIH_F_INJACTV; 263 } 264 265 boolean_t 266 cmi_inj_tainted(void) 267 { 268 return (injcnt != 0 ? B_TRUE : B_FALSE); 269 } 270 271 /* 272 * ======================================================= 273 * | MSR Interposition | 274 * | ----------------- | 275 * | | 276 * ------------------------------------------------------- 277 */ 278 279 #define CMI_MSRI_HASHSZ 16 280 #define CMI_MSRI_HASHIDX(hdl, msr) \ 281 (((uintptr_t)(hdl) >> 3 + (msr)) % (CMI_MSRI_HASHSZ - 1)) 282 283 struct cmi_msri_bkt { 284 kmutex_t msrib_lock; 285 struct cmi_msri_hashent *msrib_head; 286 }; 287 288 struct cmi_msri_hashent { 289 struct cmi_msri_hashent *msrie_next; 290 struct cmi_msri_hashent *msrie_prev; 291 cmi_hdl_impl_t *msrie_hdl; 292 uint_t msrie_msrnum; 293 uint64_t msrie_msrval; 294 }; 295 296 #define CMI_MSRI_MATCH(ent, hdl, req_msr) \ 297 ((ent)->msrie_hdl == (hdl) && (ent)->msrie_msrnum == (req_msr)) 298 299 static struct cmi_msri_bkt msrihash[CMI_MSRI_HASHSZ]; 300 301 static void 302 msri_addent(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val) 303 { 304 int idx = CMI_MSRI_HASHIDX(hdl, msr); 305 struct cmi_msri_bkt *hbp = &msrihash[idx]; 306 struct cmi_msri_hashent *hep; 307 308 mutex_enter(&hbp->msrib_lock); 309 310 for (hep = hbp->msrib_head; hep != NULL; hep = hep->msrie_next) { 311 if (CMI_MSRI_MATCH(hep, hdl, msr)) 312 break; 313 } 314 315 if (hep != NULL) { 316 hep->msrie_msrval = val; 317 } else { 318 hep = kmem_alloc(sizeof (*hep), KM_SLEEP); 319 hep->msrie_hdl = hdl; 320 hep->msrie_msrnum = msr; 321 hep->msrie_msrval = val; 322 323 if (hbp->msrib_head != NULL) 324 hbp->msrib_head->msrie_prev = hep; 325 hep->msrie_next = hbp->msrib_head; 326 hep->msrie_prev = NULL; 327 hbp->msrib_head = hep; 328 } 329 330 mutex_exit(&hbp->msrib_lock); 331 } 332 333 /* 334 * Look for a match for the given hanlde and msr. Return 1 with valp 335 * filled if a match is found, otherwise return 0 with valp untouched. 336 */ 337 static int 338 msri_lookup(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t *valp) 339 { 340 int idx = CMI_MSRI_HASHIDX(hdl, msr); 341 struct cmi_msri_bkt *hbp = &msrihash[idx]; 342 struct cmi_msri_hashent *hep; 343 344 /* 345 * This function is called during #MC trap handling, so we should 346 * consider the possibility that the hash mutex is held by the 347 * interrupted thread. This should not happen because interposition 348 * is an artificial injection mechanism and the #MC is requested 349 * after adding entries, but just in case of a real #MC at an 350 * unlucky moment we'll use mutex_tryenter here. 351 */ 352 if (!mutex_tryenter(&hbp->msrib_lock)) 353 return (0); 354 355 for (hep = hbp->msrib_head; hep != NULL; hep = hep->msrie_next) { 356 if (CMI_MSRI_MATCH(hep, hdl, msr)) { 357 *valp = hep->msrie_msrval; 358 break; 359 } 360 } 361 362 mutex_exit(&hbp->msrib_lock); 363 364 return (hep != NULL); 365 } 366 367 /* 368 * Remove any interposed value that matches. 369 */ 370 static void 371 msri_rment(cmi_hdl_impl_t *hdl, uint_t msr) 372 { 373 374 int idx = CMI_MSRI_HASHIDX(hdl, msr); 375 struct cmi_msri_bkt *hbp = &msrihash[idx]; 376 struct cmi_msri_hashent *hep; 377 378 if (!mutex_tryenter(&hbp->msrib_lock)) 379 return; 380 381 for (hep = hbp->msrib_head; hep != NULL; hep = hep->msrie_next) { 382 if (CMI_MSRI_MATCH(hep, hdl, msr)) { 383 if (hep->msrie_prev != NULL) 384 hep->msrie_prev->msrie_next = hep->msrie_next; 385 386 if (hep->msrie_next != NULL) 387 hep->msrie_next->msrie_prev = hep->msrie_prev; 388 389 if (hbp->msrib_head == hep) 390 hbp->msrib_head = hep->msrie_next; 391 392 kmem_free(hep, sizeof (*hep)); 393 break; 394 } 395 } 396 397 mutex_exit(&hbp->msrib_lock); 398 } 399 400 /* 401 * ======================================================= 402 * | PCI Config Space Interposition | 403 * | ------------------------------ | 404 * | | 405 * ------------------------------------------------------- 406 */ 407 408 /* 409 * Hash for interposed PCI config space values. We lookup on bus/dev/fun/offset 410 * and then record whether the value stashed was made with a byte, word or 411 * doubleword access; we will only return a hit for an access of the 412 * same size. If you access say a 32-bit register using byte accesses 413 * and then attempt to read the full 32-bit value back you will not obtain 414 * any sort of merged result - you get a lookup miss. 415 */ 416 417 #define CMI_PCII_HASHSZ 16 418 #define CMI_PCII_HASHIDX(b, d, f, o) \ 419 (((b) + (d) + (f) + (o)) % (CMI_PCII_HASHSZ - 1)) 420 421 struct cmi_pcii_bkt { 422 kmutex_t pciib_lock; 423 struct cmi_pcii_hashent *pciib_head; 424 }; 425 426 struct cmi_pcii_hashent { 427 struct cmi_pcii_hashent *pcii_next; 428 struct cmi_pcii_hashent *pcii_prev; 429 int pcii_bus; 430 int pcii_dev; 431 int pcii_func; 432 int pcii_reg; 433 int pcii_asize; 434 uint32_t pcii_val; 435 }; 436 437 #define CMI_PCII_MATCH(ent, b, d, f, r, asz) \ 438 ((ent)->pcii_bus == (b) && (ent)->pcii_dev == (d) && \ 439 (ent)->pcii_func == (f) && (ent)->pcii_reg == (r) && \ 440 (ent)->pcii_asize == (asz)) 441 442 static struct cmi_pcii_bkt pciihash[CMI_PCII_HASHSZ]; 443 444 445 /* 446 * Add a new entry to the PCI interpose hash, overwriting any existing 447 * entry that is found. 448 */ 449 static void 450 pcii_addent(int bus, int dev, int func, int reg, uint32_t val, int asz) 451 { 452 int idx = CMI_PCII_HASHIDX(bus, dev, func, reg); 453 struct cmi_pcii_bkt *hbp = &pciihash[idx]; 454 struct cmi_pcii_hashent *hep; 455 456 cmi_hdl_inj_begin(NULL); 457 458 mutex_enter(&hbp->pciib_lock); 459 460 for (hep = hbp->pciib_head; hep != NULL; hep = hep->pcii_next) { 461 if (CMI_PCII_MATCH(hep, bus, dev, func, reg, asz)) 462 break; 463 } 464 465 if (hep != NULL) { 466 hep->pcii_val = val; 467 } else { 468 hep = kmem_alloc(sizeof (*hep), KM_SLEEP); 469 hep->pcii_bus = bus; 470 hep->pcii_dev = dev; 471 hep->pcii_func = func; 472 hep->pcii_reg = reg; 473 hep->pcii_asize = asz; 474 hep->pcii_val = val; 475 476 if (hbp->pciib_head != NULL) 477 hbp->pciib_head->pcii_prev = hep; 478 hep->pcii_next = hbp->pciib_head; 479 hep->pcii_prev = NULL; 480 hbp->pciib_head = hep; 481 } 482 483 mutex_exit(&hbp->pciib_lock); 484 485 cmi_hdl_inj_end(NULL); 486 } 487 488 /* 489 * Look for a match for the given bus/dev/func/reg; return 1 with valp 490 * filled if a match is found, otherwise return 0 with valp untouched. 491 */ 492 static int 493 pcii_lookup(int bus, int dev, int func, int reg, int asz, uint32_t *valp) 494 { 495 int idx = CMI_PCII_HASHIDX(bus, dev, func, reg); 496 struct cmi_pcii_bkt *hbp = &pciihash[idx]; 497 struct cmi_pcii_hashent *hep; 498 499 if (!mutex_tryenter(&hbp->pciib_lock)) 500 return (0); 501 502 for (hep = hbp->pciib_head; hep != NULL; hep = hep->pcii_next) { 503 if (CMI_PCII_MATCH(hep, bus, dev, func, reg, asz)) { 504 *valp = hep->pcii_val; 505 break; 506 } 507 } 508 509 mutex_exit(&hbp->pciib_lock); 510 511 return (hep != NULL); 512 } 513 514 static void 515 pcii_rment(int bus, int dev, int func, int reg, int asz) 516 { 517 int idx = CMI_PCII_HASHIDX(bus, dev, func, reg); 518 struct cmi_pcii_bkt *hbp = &pciihash[idx]; 519 struct cmi_pcii_hashent *hep; 520 521 mutex_enter(&hbp->pciib_lock); 522 523 for (hep = hbp->pciib_head; hep != NULL; hep = hep->pcii_next) { 524 if (CMI_PCII_MATCH(hep, bus, dev, func, reg, asz)) { 525 if (hep->pcii_prev != NULL) 526 hep->pcii_prev->pcii_next = hep->pcii_next; 527 528 if (hep->pcii_next != NULL) 529 hep->pcii_next->pcii_prev = hep->pcii_prev; 530 531 if (hbp->pciib_head == hep) 532 hbp->pciib_head = hep->pcii_next; 533 534 kmem_free(hep, sizeof (*hep)); 535 break; 536 } 537 } 538 539 mutex_exit(&hbp->pciib_lock); 540 } 541 542 #ifndef __xpv 543 544 /* 545 * ======================================================= 546 * | Native methods | 547 * | -------------- | 548 * | | 549 * | These are used when we are running native on bare- | 550 * | metal, or simply don't know any better. | 551 * --------------------------------------------------------- 552 */ 553 554 #define HDLPRIV(hdl) ((cpu_t *)(hdl)->cmih_hdlpriv) 555 556 static uint_t 557 ntv_vendor(cmi_hdl_impl_t *hdl) 558 { 559 return (cpuid_getvendor(HDLPRIV(hdl))); 560 } 561 562 static const char * 563 ntv_vendorstr(cmi_hdl_impl_t *hdl) 564 { 565 return (cpuid_getvendorstr(HDLPRIV(hdl))); 566 } 567 568 static uint_t 569 ntv_family(cmi_hdl_impl_t *hdl) 570 { 571 return (cpuid_getfamily(HDLPRIV(hdl))); 572 } 573 574 static uint_t 575 ntv_model(cmi_hdl_impl_t *hdl) 576 { 577 return (cpuid_getmodel(HDLPRIV(hdl))); 578 } 579 580 static uint_t 581 ntv_stepping(cmi_hdl_impl_t *hdl) 582 { 583 return (cpuid_getstep(HDLPRIV(hdl))); 584 } 585 586 static uint_t 587 ntv_chipid(cmi_hdl_impl_t *hdl) 588 { 589 return (hdl->cmih_chipid); 590 591 } 592 593 static uint_t 594 ntv_coreid(cmi_hdl_impl_t *hdl) 595 { 596 return (hdl->cmih_coreid); 597 } 598 599 static uint_t 600 ntv_strandid(cmi_hdl_impl_t *hdl) 601 { 602 return (hdl->cmih_strandid); 603 } 604 605 static uint32_t 606 ntv_chiprev(cmi_hdl_impl_t *hdl) 607 { 608 return (cpuid_getchiprev(HDLPRIV(hdl))); 609 } 610 611 static const char * 612 ntv_chiprevstr(cmi_hdl_impl_t *hdl) 613 { 614 return (cpuid_getchiprevstr(HDLPRIV(hdl))); 615 } 616 617 static uint32_t 618 ntv_getsockettype(cmi_hdl_impl_t *hdl) 619 { 620 return (cpuid_getsockettype(HDLPRIV(hdl))); 621 } 622 623 static const char * 624 ntv_getsocketstr(cmi_hdl_impl_t *hdl) 625 { 626 return (cpuid_getsocketstr(HDLPRIV(hdl))); 627 } 628 629 static id_t 630 ntv_logical_id(cmi_hdl_impl_t *hdl) 631 { 632 return (HDLPRIV(hdl)->cpu_id); 633 } 634 635 /*ARGSUSED*/ 636 static int 637 ntv_getcr4_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3) 638 { 639 ulong_t *dest = (ulong_t *)arg1; 640 cmi_errno_t *rcp = (cmi_errno_t *)arg3; 641 642 *dest = getcr4(); 643 *rcp = CMI_SUCCESS; 644 645 return (0); 646 } 647 648 static ulong_t 649 ntv_getcr4(cmi_hdl_impl_t *hdl) 650 { 651 cpu_t *cp = HDLPRIV(hdl); 652 ulong_t val; 653 654 (void) call_func_ntv(cp->cpu_id, ntv_getcr4_xc, (xc_arg_t)&val, NULL); 655 656 return (val); 657 } 658 659 /*ARGSUSED*/ 660 static int 661 ntv_setcr4_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3) 662 { 663 ulong_t val = (ulong_t)arg1; 664 cmi_errno_t *rcp = (cmi_errno_t *)arg3; 665 666 setcr4(val); 667 *rcp = CMI_SUCCESS; 668 669 return (0); 670 } 671 672 static void 673 ntv_setcr4(cmi_hdl_impl_t *hdl, ulong_t val) 674 { 675 cpu_t *cp = HDLPRIV(hdl); 676 677 (void) call_func_ntv(cp->cpu_id, ntv_setcr4_xc, (xc_arg_t)val, NULL); 678 } 679 680 volatile uint32_t cmi_trapped_rdmsr; 681 682 /*ARGSUSED*/ 683 static int 684 ntv_rdmsr_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3) 685 { 686 uint_t msr = (uint_t)arg1; 687 uint64_t *valp = (uint64_t *)arg2; 688 cmi_errno_t *rcp = (cmi_errno_t *)arg3; 689 690 on_trap_data_t otd; 691 692 if (on_trap(&otd, OT_DATA_ACCESS) == 0) { 693 if (checked_rdmsr(msr, valp) == 0) 694 *rcp = CMI_SUCCESS; 695 else 696 *rcp = CMIERR_NOTSUP; 697 } else { 698 *rcp = CMIERR_MSRGPF; 699 atomic_inc_32(&cmi_trapped_rdmsr); 700 } 701 no_trap(); 702 703 return (0); 704 } 705 706 static cmi_errno_t 707 ntv_rdmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t *valp) 708 { 709 cpu_t *cp = HDLPRIV(hdl); 710 711 if (!(hdl->cmih_msrsrc & CMI_MSR_FLAG_RD_HWOK)) 712 return (CMIERR_INTERPOSE); 713 714 return (call_func_ntv(cp->cpu_id, ntv_rdmsr_xc, 715 (xc_arg_t)msr, (xc_arg_t)valp)); 716 } 717 718 volatile uint32_t cmi_trapped_wrmsr; 719 720 /*ARGSUSED*/ 721 static int 722 ntv_wrmsr_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3) 723 { 724 uint_t msr = (uint_t)arg1; 725 uint64_t val = *((uint64_t *)arg2); 726 cmi_errno_t *rcp = (cmi_errno_t *)arg3; 727 on_trap_data_t otd; 728 729 if (on_trap(&otd, OT_DATA_ACCESS) == 0) { 730 if (checked_wrmsr(msr, val) == 0) 731 *rcp = CMI_SUCCESS; 732 else 733 *rcp = CMIERR_NOTSUP; 734 } else { 735 *rcp = CMIERR_MSRGPF; 736 atomic_inc_32(&cmi_trapped_wrmsr); 737 } 738 no_trap(); 739 740 return (0); 741 742 } 743 744 static cmi_errno_t 745 ntv_wrmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val) 746 { 747 cpu_t *cp = HDLPRIV(hdl); 748 749 if (!(hdl->cmih_msrsrc & CMI_MSR_FLAG_WR_HWOK)) 750 return (CMI_SUCCESS); 751 752 return (call_func_ntv(cp->cpu_id, ntv_wrmsr_xc, 753 (xc_arg_t)msr, (xc_arg_t)&val)); 754 } 755 756 static cmi_errno_t 757 ntv_msrinterpose(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val) 758 { 759 msri_addent(hdl, msr, val); 760 return (CMI_SUCCESS); 761 } 762 763 /*ARGSUSED*/ 764 static int 765 ntv_int_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3) 766 { 767 cmi_errno_t *rcp = (cmi_errno_t *)arg3; 768 int int_no = (int)arg1; 769 770 if (int_no == T_MCE) 771 int18(); 772 else 773 int_cmci(); 774 *rcp = CMI_SUCCESS; 775 776 return (0); 777 } 778 779 static void 780 ntv_int(cmi_hdl_impl_t *hdl, int int_no) 781 { 782 cpu_t *cp = HDLPRIV(hdl); 783 784 (void) call_func_ntv(cp->cpu_id, ntv_int_xc, (xc_arg_t)int_no, NULL); 785 } 786 787 static int 788 ntv_online(cmi_hdl_impl_t *hdl, int new_status, int *old_status) 789 { 790 processorid_t cpuid = HDLPRIV(hdl)->cpu_id; 791 792 return (p_online_internal(cpuid, new_status, old_status)); 793 } 794 795 #else /* __xpv */ 796 797 /* 798 * ======================================================= 799 * | xVM dom0 methods | 800 * | ---------------- | 801 * | | 802 * | These are used when we are running as dom0 in | 803 * | a Solaris xVM context. | 804 * --------------------------------------------------------- 805 */ 806 807 #define HDLPRIV(hdl) ((xen_mc_lcpu_cookie_t)(hdl)->cmih_hdlpriv) 808 809 extern uint_t _cpuid_vendorstr_to_vendorcode(char *); 810 811 812 static uint_t 813 xpv_vendor(cmi_hdl_impl_t *hdl) 814 { 815 return (_cpuid_vendorstr_to_vendorcode((char *)xen_physcpu_vendorstr( 816 HDLPRIV(hdl)))); 817 } 818 819 static const char * 820 xpv_vendorstr(cmi_hdl_impl_t *hdl) 821 { 822 return (xen_physcpu_vendorstr(HDLPRIV(hdl))); 823 } 824 825 static uint_t 826 xpv_family(cmi_hdl_impl_t *hdl) 827 { 828 return (xen_physcpu_family(HDLPRIV(hdl))); 829 } 830 831 static uint_t 832 xpv_model(cmi_hdl_impl_t *hdl) 833 { 834 return (xen_physcpu_model(HDLPRIV(hdl))); 835 } 836 837 static uint_t 838 xpv_stepping(cmi_hdl_impl_t *hdl) 839 { 840 return (xen_physcpu_stepping(HDLPRIV(hdl))); 841 } 842 843 static uint_t 844 xpv_chipid(cmi_hdl_impl_t *hdl) 845 { 846 return (hdl->cmih_chipid); 847 } 848 849 static uint_t 850 xpv_coreid(cmi_hdl_impl_t *hdl) 851 { 852 return (hdl->cmih_coreid); 853 } 854 855 static uint_t 856 xpv_strandid(cmi_hdl_impl_t *hdl) 857 { 858 return (hdl->cmih_strandid); 859 } 860 861 extern uint32_t _cpuid_chiprev(uint_t, uint_t, uint_t, uint_t); 862 863 static uint32_t 864 xpv_chiprev(cmi_hdl_impl_t *hdl) 865 { 866 return (_cpuid_chiprev(xpv_vendor(hdl), xpv_family(hdl), 867 xpv_model(hdl), xpv_stepping(hdl))); 868 } 869 870 extern const char *_cpuid_chiprevstr(uint_t, uint_t, uint_t, uint_t); 871 872 static const char * 873 xpv_chiprevstr(cmi_hdl_impl_t *hdl) 874 { 875 return (_cpuid_chiprevstr(xpv_vendor(hdl), xpv_family(hdl), 876 xpv_model(hdl), xpv_stepping(hdl))); 877 } 878 879 extern uint32_t _cpuid_skt(uint_t, uint_t, uint_t, uint_t); 880 881 static uint32_t 882 xpv_getsockettype(cmi_hdl_impl_t *hdl) 883 { 884 return (_cpuid_skt(xpv_vendor(hdl), xpv_family(hdl), 885 xpv_model(hdl), xpv_stepping(hdl))); 886 } 887 888 extern const char *_cpuid_sktstr(uint_t, uint_t, uint_t, uint_t); 889 890 static const char * 891 xpv_getsocketstr(cmi_hdl_impl_t *hdl) 892 { 893 return (_cpuid_sktstr(xpv_vendor(hdl), xpv_family(hdl), 894 xpv_model(hdl), xpv_stepping(hdl))); 895 } 896 897 static id_t 898 xpv_logical_id(cmi_hdl_impl_t *hdl) 899 { 900 return (xen_physcpu_logical_id(HDLPRIV(hdl))); 901 } 902 903 static cmi_errno_t 904 xpv_rdmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t *valp) 905 { 906 switch (msr) { 907 case IA32_MSR_MCG_CAP: 908 *valp = xen_physcpu_mcg_cap(HDLPRIV(hdl)); 909 break; 910 911 default: 912 return (CMIERR_NOTSUP); 913 } 914 915 return (CMI_SUCCESS); 916 } 917 918 /* 919 * Request the hypervisor to write an MSR for us. The hypervisor 920 * will only accept MCA-related MSRs, as this is for MCA error 921 * simulation purposes alone. We will pre-screen MSRs for injection 922 * so we don't bother the HV with bogus requests. We will permit 923 * injection to any MCA bank register, and to MCG_STATUS. 924 */ 925 926 #define IS_MCA_INJ_MSR(msr) \ 927 (((msr) >= IA32_MSR_MC(0, CTL) && (msr) <= IA32_MSR_MC(10, MISC)) || \ 928 (msr) == IA32_MSR_MCG_STATUS) 929 930 static cmi_errno_t 931 xpv_wrmsr_cmn(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val, boolean_t intpose) 932 { 933 struct xen_mc_msrinject mci; 934 935 if (!(hdl->cmih_flags & CMIH_F_INJACTV)) 936 return (CMIERR_NOTSUP); /* for injection use only! */ 937 938 if (!IS_MCA_INJ_MSR(msr)) 939 return (CMIERR_API); 940 941 if (panicstr) 942 return (CMIERR_DEADLOCK); 943 944 mci.mcinj_cpunr = xen_physcpu_logical_id(HDLPRIV(hdl)); 945 mci.mcinj_flags = intpose ? MC_MSRINJ_F_INTERPOSE : 0; 946 mci.mcinj_count = 1; /* learn to batch sometime */ 947 mci.mcinj_msr[0].reg = msr; 948 mci.mcinj_msr[0].value = val; 949 950 return (HYPERVISOR_mca(XEN_MC_msrinject, (xen_mc_arg_t *)&mci) == 951 0 ? CMI_SUCCESS : CMIERR_NOTSUP); 952 } 953 954 static cmi_errno_t 955 xpv_wrmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val) 956 { 957 return (xpv_wrmsr_cmn(hdl, msr, val, B_FALSE)); 958 } 959 960 961 static cmi_errno_t 962 xpv_msrinterpose(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val) 963 { 964 return (xpv_wrmsr_cmn(hdl, msr, val, B_TRUE)); 965 } 966 967 static void 968 xpv_int(cmi_hdl_impl_t *hdl, int int_no) 969 { 970 struct xen_mc_mceinject mce; 971 972 if (!(hdl->cmih_flags & CMIH_F_INJACTV)) 973 return; 974 975 if (int_no != T_MCE) { 976 cmn_err(CE_WARN, "xpv_int: int_no %d unimplemented\n", 977 int_no); 978 } 979 980 mce.mceinj_cpunr = xen_physcpu_logical_id(HDLPRIV(hdl)); 981 982 (void) HYPERVISOR_mca(XEN_MC_mceinject, (xen_mc_arg_t *)&mce); 983 } 984 985 static int 986 xpv_online(cmi_hdl_impl_t *hdl, int new_status, int *old_status) 987 { 988 xen_sysctl_t xs; 989 int op, rc, status; 990 991 new_status &= ~P_FORCED; 992 993 switch (new_status) { 994 case P_STATUS: 995 op = XEN_SYSCTL_CPU_HOTPLUG_STATUS; 996 break; 997 case P_FAULTED: 998 case P_OFFLINE: 999 op = XEN_SYSCTL_CPU_HOTPLUG_OFFLINE; 1000 break; 1001 case P_ONLINE: 1002 op = XEN_SYSCTL_CPU_HOTPLUG_ONLINE; 1003 break; 1004 default: 1005 return (-1); 1006 } 1007 1008 xs.cmd = XEN_SYSCTL_cpu_hotplug; 1009 xs.interface_version = XEN_SYSCTL_INTERFACE_VERSION; 1010 xs.u.cpu_hotplug.cpu = xen_physcpu_logical_id(HDLPRIV(hdl)); 1011 xs.u.cpu_hotplug.op = op; 1012 1013 if ((rc = HYPERVISOR_sysctl(&xs)) >= 0) { 1014 status = rc; 1015 rc = 0; 1016 switch (status) { 1017 case XEN_CPU_HOTPLUG_STATUS_NEW: 1018 *old_status = P_OFFLINE; 1019 break; 1020 case XEN_CPU_HOTPLUG_STATUS_OFFLINE: 1021 *old_status = P_FAULTED; 1022 break; 1023 case XEN_CPU_HOTPLUG_STATUS_ONLINE: 1024 *old_status = P_ONLINE; 1025 break; 1026 default: 1027 return (-1); 1028 } 1029 } 1030 1031 return (-rc); 1032 } 1033 1034 #endif 1035 1036 /*ARGSUSED*/ 1037 static void * 1038 cpu_search(enum cmi_hdl_class class, uint_t chipid, uint_t coreid, 1039 uint_t strandid) 1040 { 1041 #ifdef __xpv 1042 xen_mc_lcpu_cookie_t cpi; 1043 1044 for (cpi = xen_physcpu_next(NULL); cpi != NULL; 1045 cpi = xen_physcpu_next(cpi)) { 1046 if (xen_physcpu_chipid(cpi) == chipid && 1047 xen_physcpu_coreid(cpi) == coreid && 1048 xen_physcpu_strandid(cpi) == strandid) 1049 return ((void *)cpi); 1050 } 1051 return (NULL); 1052 1053 #else /* __xpv */ 1054 1055 cpu_t *cp, *startcp; 1056 1057 kpreempt_disable(); 1058 cp = startcp = CPU; 1059 do { 1060 if (cmi_ntv_hwchipid(cp) == chipid && 1061 cmi_ntv_hwcoreid(cp) == coreid && 1062 cmi_ntv_hwstrandid(cp) == strandid) { 1063 kpreempt_enable(); 1064 return ((void *)cp); 1065 } 1066 1067 cp = cp->cpu_next; 1068 } while (cp != startcp); 1069 kpreempt_enable(); 1070 return (NULL); 1071 #endif /* __ xpv */ 1072 } 1073 1074 static boolean_t 1075 cpu_is_cmt(void *priv) 1076 { 1077 #ifdef __xpv 1078 return (xen_physcpu_is_cmt((xen_mc_lcpu_cookie_t)priv)); 1079 #else /* __xpv */ 1080 cpu_t *cp = (cpu_t *)priv; 1081 1082 int strands_per_core = cpuid_get_ncpu_per_chip(cp) / 1083 cpuid_get_ncore_per_chip(cp); 1084 1085 return (strands_per_core > 1); 1086 #endif /* __xpv */ 1087 } 1088 1089 /* 1090 * Find the handle entry of a given cpu identified by a <chip,core,strand> 1091 * tuple. 1092 */ 1093 static cmi_hdl_ent_t * 1094 cmi_hdl_ent_lookup(uint_t chipid, uint_t coreid, uint_t strandid) 1095 { 1096 /* 1097 * Allocate per-chip table which contains a list of handle of 1098 * all strands of the chip. 1099 */ 1100 if (cmi_chip_tab[chipid] == NULL) { 1101 size_t sz; 1102 cmi_hdl_ent_t *pg; 1103 1104 sz = CMI_MAX_STRANDS_PER_CHIP * sizeof (cmi_hdl_ent_t); 1105 pg = kmem_zalloc(sz, KM_SLEEP); 1106 1107 /* test and set the per-chip table if it is not allocated */ 1108 if (atomic_cas_ptr(&cmi_chip_tab[chipid], NULL, pg) != NULL) 1109 kmem_free(pg, sz); /* someone beat us */ 1110 } 1111 1112 return (cmi_chip_tab[chipid] + CMI_HDL_ARR_IDX(coreid, strandid)); 1113 } 1114 1115 cmi_hdl_t 1116 cmi_hdl_create(enum cmi_hdl_class class, uint_t chipid, uint_t coreid, 1117 uint_t strandid) 1118 { 1119 cmi_hdl_impl_t *hdl; 1120 void *priv; 1121 cmi_hdl_ent_t *ent; 1122 1123 #ifdef __xpv 1124 ASSERT(class == CMI_HDL_SOLARIS_xVM_MCA); 1125 #else 1126 ASSERT(class == CMI_HDL_NATIVE); 1127 #endif 1128 1129 if (chipid > CMI_MAX_CHIPID || 1130 coreid > CMI_MAX_CORES_PER_CHIP - 1 || 1131 strandid > CMI_MAX_STRANDS_PER_CORE - 1) 1132 return (NULL); 1133 1134 if ((priv = cpu_search(class, chipid, coreid, strandid)) == NULL) 1135 return (NULL); 1136 1137 hdl = kmem_zalloc(sizeof (*hdl), KM_SLEEP); 1138 1139 hdl->cmih_class = class; 1140 HDLOPS(hdl) = &cmi_hdl_ops; 1141 hdl->cmih_chipid = chipid; 1142 hdl->cmih_coreid = coreid; 1143 hdl->cmih_strandid = strandid; 1144 hdl->cmih_mstrand = cpu_is_cmt(priv); 1145 hdl->cmih_hdlpriv = priv; 1146 #ifdef __xpv 1147 hdl->cmih_msrsrc = CMI_MSR_FLAG_RD_INTERPOSEOK | 1148 CMI_MSR_FLAG_WR_INTERPOSEOK; 1149 #else /* __xpv */ 1150 hdl->cmih_msrsrc = CMI_MSR_FLAG_RD_HWOK | CMI_MSR_FLAG_RD_INTERPOSEOK | 1151 CMI_MSR_FLAG_WR_HWOK | CMI_MSR_FLAG_WR_INTERPOSEOK; 1152 #endif 1153 1154 ent = cmi_hdl_ent_lookup(chipid, coreid, strandid); 1155 if (ent->cmae_refcnt != 0 || ent->cmae_hdlp != NULL) { 1156 /* 1157 * Somehow this (chipid, coreid, strandid) id tuple has 1158 * already been assigned! This indicates that the 1159 * callers logic in determining these values is busted, 1160 * or perhaps undermined by bad BIOS setup. Complain, 1161 * and refuse to initialize this tuple again as bad things 1162 * will happen. 1163 */ 1164 cmn_err(CE_NOTE, "cmi_hdl_create: chipid %d coreid %d " 1165 "strandid %d handle already allocated!", 1166 chipid, coreid, strandid); 1167 kmem_free(hdl, sizeof (*hdl)); 1168 return (NULL); 1169 } 1170 1171 /* 1172 * Once we store a nonzero reference count others can find this 1173 * handle via cmi_hdl_lookup etc. This initial hold on the handle 1174 * is to be dropped only if some other part of cmi initialization 1175 * fails or, if it succeeds, at later cpu deconfigure. Note the 1176 * the module private data we hold in cmih_cmi and cmih_cmidata 1177 * is still NULL at this point (the caller will fill it with 1178 * cmi_hdl_setcmi if it initializes) so consumers of handles 1179 * should always be ready for that possibility. 1180 */ 1181 ent->cmae_hdlp = hdl; 1182 hdl->cmih_refcntp = &ent->cmae_refcnt; 1183 ent->cmae_refcnt = 1; 1184 1185 return ((cmi_hdl_t)hdl); 1186 } 1187 1188 void 1189 cmi_hdl_hold(cmi_hdl_t ophdl) 1190 { 1191 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1192 1193 ASSERT(*hdl->cmih_refcntp != 0); /* must not be the initial hold */ 1194 1195 atomic_inc_32(hdl->cmih_refcntp); 1196 } 1197 1198 static int 1199 cmi_hdl_canref(cmi_hdl_ent_t *ent) 1200 { 1201 volatile uint32_t *refcntp; 1202 uint32_t refcnt; 1203 1204 refcntp = &ent->cmae_refcnt; 1205 refcnt = *refcntp; 1206 1207 if (refcnt == 0) { 1208 /* 1209 * Associated object never existed, is being destroyed, 1210 * or has been destroyed. 1211 */ 1212 return (0); 1213 } 1214 1215 /* 1216 * We cannot use atomic increment here because once the reference 1217 * count reaches zero it must never be bumped up again. 1218 */ 1219 while (refcnt != 0) { 1220 if (atomic_cas_32(refcntp, refcnt, refcnt + 1) == refcnt) 1221 return (1); 1222 refcnt = *refcntp; 1223 } 1224 1225 /* 1226 * Somebody dropped the reference count to 0 after our initial 1227 * check. 1228 */ 1229 return (0); 1230 } 1231 1232 1233 void 1234 cmi_hdl_rele(cmi_hdl_t ophdl) 1235 { 1236 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1237 cmi_hdl_ent_t *ent; 1238 1239 ASSERT(*hdl->cmih_refcntp > 0); 1240 1241 if (atomic_dec_32_nv(hdl->cmih_refcntp) > 0) 1242 return; 1243 1244 ent = cmi_hdl_ent_lookup(hdl->cmih_chipid, hdl->cmih_coreid, 1245 hdl->cmih_strandid); 1246 ent->cmae_hdlp = NULL; 1247 1248 kmem_free(hdl, sizeof (*hdl)); 1249 } 1250 1251 void 1252 cmi_hdl_setspecific(cmi_hdl_t ophdl, void *arg) 1253 { 1254 IMPLHDL(ophdl)->cmih_spec = arg; 1255 } 1256 1257 void * 1258 cmi_hdl_getspecific(cmi_hdl_t ophdl) 1259 { 1260 return (IMPLHDL(ophdl)->cmih_spec); 1261 } 1262 1263 void 1264 cmi_hdl_setmc(cmi_hdl_t ophdl, const struct cmi_mc_ops *mcops, void *mcdata) 1265 { 1266 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1267 1268 ASSERT(hdl->cmih_mcops == NULL && hdl->cmih_mcdata == NULL); 1269 hdl->cmih_mcops = mcops; 1270 hdl->cmih_mcdata = mcdata; 1271 } 1272 1273 const struct cmi_mc_ops * 1274 cmi_hdl_getmcops(cmi_hdl_t ophdl) 1275 { 1276 return (IMPLHDL(ophdl)->cmih_mcops); 1277 } 1278 1279 void * 1280 cmi_hdl_getmcdata(cmi_hdl_t ophdl) 1281 { 1282 return (IMPLHDL(ophdl)->cmih_mcdata); 1283 } 1284 1285 cmi_hdl_t 1286 cmi_hdl_lookup(enum cmi_hdl_class class, uint_t chipid, uint_t coreid, 1287 uint_t strandid) 1288 { 1289 cmi_hdl_ent_t *ent; 1290 1291 if (chipid > CMI_MAX_CHIPID || 1292 coreid > CMI_MAX_CORES_PER_CHIP - 1 || 1293 strandid > CMI_MAX_STRANDS_PER_CORE - 1) 1294 return (NULL); 1295 1296 ent = cmi_hdl_ent_lookup(chipid, coreid, strandid); 1297 1298 if (class == CMI_HDL_NEUTRAL) 1299 #ifdef __xpv 1300 class = CMI_HDL_SOLARIS_xVM_MCA; 1301 #else 1302 class = CMI_HDL_NATIVE; 1303 #endif 1304 1305 if (!cmi_hdl_canref(ent)) 1306 return (NULL); 1307 1308 if (ent->cmae_hdlp->cmih_class != class) { 1309 cmi_hdl_rele((cmi_hdl_t)ent->cmae_hdlp); 1310 return (NULL); 1311 } 1312 1313 return ((cmi_hdl_t)ent->cmae_hdlp); 1314 } 1315 1316 cmi_hdl_t 1317 cmi_hdl_any(void) 1318 { 1319 int i, j; 1320 cmi_hdl_ent_t *ent; 1321 1322 for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) { 1323 if (cmi_chip_tab[i] == NULL) 1324 continue; 1325 for (j = 0, ent = cmi_chip_tab[i]; j < CMI_MAX_STRANDS_PER_CHIP; 1326 j++, ent++) { 1327 if (cmi_hdl_canref(ent)) 1328 return ((cmi_hdl_t)ent->cmae_hdlp); 1329 } 1330 } 1331 1332 return (NULL); 1333 } 1334 1335 void 1336 cmi_hdl_walk(int (*cbfunc)(cmi_hdl_t, void *, void *, void *), 1337 void *arg1, void *arg2, void *arg3) 1338 { 1339 int i, j; 1340 cmi_hdl_ent_t *ent; 1341 1342 for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) { 1343 if (cmi_chip_tab[i] == NULL) 1344 continue; 1345 for (j = 0, ent = cmi_chip_tab[i]; j < CMI_MAX_STRANDS_PER_CHIP; 1346 j++, ent++) { 1347 if (cmi_hdl_canref(ent)) { 1348 cmi_hdl_impl_t *hdl = ent->cmae_hdlp; 1349 if ((*cbfunc)((cmi_hdl_t)hdl, arg1, arg2, arg3) 1350 == CMI_HDL_WALK_DONE) { 1351 cmi_hdl_rele((cmi_hdl_t)hdl); 1352 return; 1353 } 1354 cmi_hdl_rele((cmi_hdl_t)hdl); 1355 } 1356 } 1357 } 1358 } 1359 1360 void 1361 cmi_hdl_setcmi(cmi_hdl_t ophdl, void *cmi, void *cmidata) 1362 { 1363 IMPLHDL(ophdl)->cmih_cmidata = cmidata; 1364 IMPLHDL(ophdl)->cmih_cmi = cmi; 1365 } 1366 1367 void * 1368 cmi_hdl_getcmi(cmi_hdl_t ophdl) 1369 { 1370 return (IMPLHDL(ophdl)->cmih_cmi); 1371 } 1372 1373 void * 1374 cmi_hdl_getcmidata(cmi_hdl_t ophdl) 1375 { 1376 return (IMPLHDL(ophdl)->cmih_cmidata); 1377 } 1378 1379 enum cmi_hdl_class 1380 cmi_hdl_class(cmi_hdl_t ophdl) 1381 { 1382 return (IMPLHDL(ophdl)->cmih_class); 1383 } 1384 1385 #define CMI_HDL_OPFUNC(what, type) \ 1386 type \ 1387 cmi_hdl_##what(cmi_hdl_t ophdl) \ 1388 { \ 1389 return (HDLOPS(IMPLHDL(ophdl))-> \ 1390 cmio_##what(IMPLHDL(ophdl))); \ 1391 } 1392 1393 CMI_HDL_OPFUNC(vendor, uint_t) 1394 CMI_HDL_OPFUNC(vendorstr, const char *) 1395 CMI_HDL_OPFUNC(family, uint_t) 1396 CMI_HDL_OPFUNC(model, uint_t) 1397 CMI_HDL_OPFUNC(stepping, uint_t) 1398 CMI_HDL_OPFUNC(chipid, uint_t) 1399 CMI_HDL_OPFUNC(coreid, uint_t) 1400 CMI_HDL_OPFUNC(strandid, uint_t) 1401 CMI_HDL_OPFUNC(chiprev, uint32_t) 1402 CMI_HDL_OPFUNC(chiprevstr, const char *) 1403 CMI_HDL_OPFUNC(getsockettype, uint32_t) 1404 CMI_HDL_OPFUNC(getsocketstr, const char *) 1405 CMI_HDL_OPFUNC(logical_id, id_t) 1406 1407 boolean_t 1408 cmi_hdl_is_cmt(cmi_hdl_t ophdl) 1409 { 1410 return (IMPLHDL(ophdl)->cmih_mstrand); 1411 } 1412 1413 void 1414 cmi_hdl_int(cmi_hdl_t ophdl, int num) 1415 { 1416 if (HDLOPS(IMPLHDL(ophdl))->cmio_int == NULL) 1417 return; 1418 1419 cmi_hdl_inj_begin(ophdl); 1420 HDLOPS(IMPLHDL(ophdl))->cmio_int(IMPLHDL(ophdl), num); 1421 cmi_hdl_inj_end(NULL); 1422 } 1423 1424 int 1425 cmi_hdl_online(cmi_hdl_t ophdl, int new_status, int *old_status) 1426 { 1427 return (HDLOPS(IMPLHDL(ophdl))->cmio_online(IMPLHDL(ophdl), 1428 new_status, old_status)); 1429 } 1430 1431 #ifndef __xpv 1432 /* 1433 * Return hardware chip instance; cpuid_get_chipid provides this directly. 1434 */ 1435 uint_t 1436 cmi_ntv_hwchipid(cpu_t *cp) 1437 { 1438 return (cpuid_get_chipid(cp)); 1439 } 1440 1441 /* 1442 * Return core instance within a single chip. 1443 */ 1444 uint_t 1445 cmi_ntv_hwcoreid(cpu_t *cp) 1446 { 1447 return (cpuid_get_pkgcoreid(cp)); 1448 } 1449 1450 /* 1451 * Return strand number within a single core. cpuid_get_clogid numbers 1452 * all execution units (strands, or cores in unstranded models) sequentially 1453 * within a single chip. 1454 */ 1455 uint_t 1456 cmi_ntv_hwstrandid(cpu_t *cp) 1457 { 1458 int strands_per_core = cpuid_get_ncpu_per_chip(cp) / 1459 cpuid_get_ncore_per_chip(cp); 1460 1461 return (cpuid_get_clogid(cp) % strands_per_core); 1462 } 1463 #endif /* __xpv */ 1464 1465 void 1466 cmi_hdlconf_rdmsr_nohw(cmi_hdl_t ophdl) 1467 { 1468 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1469 1470 hdl->cmih_msrsrc &= ~CMI_MSR_FLAG_RD_HWOK; 1471 } 1472 1473 void 1474 cmi_hdlconf_wrmsr_nohw(cmi_hdl_t ophdl) 1475 { 1476 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1477 1478 hdl->cmih_msrsrc &= ~CMI_MSR_FLAG_WR_HWOK; 1479 } 1480 1481 cmi_errno_t 1482 cmi_hdl_rdmsr(cmi_hdl_t ophdl, uint_t msr, uint64_t *valp) 1483 { 1484 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1485 1486 /* 1487 * Regardless of the handle class, we first check for am 1488 * interposed value. In the xVM case you probably want to 1489 * place interposed values within the hypervisor itself, but 1490 * we still allow interposing them in dom0 for test and bringup 1491 * purposes. 1492 */ 1493 if ((hdl->cmih_msrsrc & CMI_MSR_FLAG_RD_INTERPOSEOK) && 1494 msri_lookup(hdl, msr, valp)) 1495 return (CMI_SUCCESS); 1496 1497 if (HDLOPS(hdl)->cmio_rdmsr == NULL) 1498 return (CMIERR_NOTSUP); 1499 1500 return (HDLOPS(hdl)->cmio_rdmsr(hdl, msr, valp)); 1501 } 1502 1503 cmi_errno_t 1504 cmi_hdl_wrmsr(cmi_hdl_t ophdl, uint_t msr, uint64_t val) 1505 { 1506 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1507 1508 /* Invalidate any interposed value */ 1509 msri_rment(hdl, msr); 1510 1511 if (HDLOPS(hdl)->cmio_wrmsr == NULL) 1512 return (CMI_SUCCESS); /* pretend all is ok */ 1513 1514 return (HDLOPS(hdl)->cmio_wrmsr(hdl, msr, val)); 1515 } 1516 1517 void 1518 cmi_hdl_enable_mce(cmi_hdl_t ophdl) 1519 { 1520 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1521 ulong_t cr4; 1522 1523 if (HDLOPS(hdl)->cmio_getcr4 == NULL || 1524 HDLOPS(hdl)->cmio_setcr4 == NULL) 1525 return; 1526 1527 cr4 = HDLOPS(hdl)->cmio_getcr4(hdl); 1528 1529 HDLOPS(hdl)->cmio_setcr4(hdl, cr4 | CR4_MCE); 1530 } 1531 1532 void 1533 cmi_hdl_msrinterpose(cmi_hdl_t ophdl, cmi_mca_regs_t *regs, uint_t nregs) 1534 { 1535 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1536 int i; 1537 1538 if (HDLOPS(hdl)->cmio_msrinterpose == NULL) 1539 return; 1540 1541 cmi_hdl_inj_begin(ophdl); 1542 1543 for (i = 0; i < nregs; i++, regs++) 1544 HDLOPS(hdl)->cmio_msrinterpose(hdl, regs->cmr_msrnum, 1545 regs->cmr_msrval); 1546 1547 cmi_hdl_inj_end(ophdl); 1548 } 1549 1550 /*ARGSUSED*/ 1551 void 1552 cmi_hdl_msrforward(cmi_hdl_t ophdl, cmi_mca_regs_t *regs, uint_t nregs) 1553 { 1554 #ifdef __xpv 1555 cmi_hdl_impl_t *hdl = IMPLHDL(ophdl); 1556 int i; 1557 1558 for (i = 0; i < nregs; i++, regs++) 1559 msri_addent(hdl, regs->cmr_msrnum, regs->cmr_msrval); 1560 #endif 1561 } 1562 1563 1564 void 1565 cmi_pcird_nohw(void) 1566 { 1567 cmi_pcicfg_flags &= ~CMI_PCICFG_FLAG_RD_HWOK; 1568 } 1569 1570 void 1571 cmi_pciwr_nohw(void) 1572 { 1573 cmi_pcicfg_flags &= ~CMI_PCICFG_FLAG_WR_HWOK; 1574 } 1575 1576 static uint32_t 1577 cmi_pci_get_cmn(int bus, int dev, int func, int reg, int asz, 1578 int *interpose, ddi_acc_handle_t hdl) 1579 { 1580 uint32_t val; 1581 1582 if (cmi_pcicfg_flags & CMI_PCICFG_FLAG_RD_INTERPOSEOK && 1583 pcii_lookup(bus, dev, func, reg, asz, &val)) { 1584 if (interpose) 1585 *interpose = 1; 1586 return (val); 1587 } 1588 if (interpose) 1589 *interpose = 0; 1590 1591 if (!(cmi_pcicfg_flags & CMI_PCICFG_FLAG_RD_HWOK)) 1592 return (0); 1593 1594 switch (asz) { 1595 case 1: 1596 if (hdl) 1597 val = pci_config_get8(hdl, (off_t)reg); 1598 else 1599 val = (*pci_getb_func)(bus, dev, func, reg); 1600 break; 1601 case 2: 1602 if (hdl) 1603 val = pci_config_get16(hdl, (off_t)reg); 1604 else 1605 val = (*pci_getw_func)(bus, dev, func, reg); 1606 break; 1607 case 4: 1608 if (hdl) 1609 val = pci_config_get32(hdl, (off_t)reg); 1610 else 1611 val = (*pci_getl_func)(bus, dev, func, reg); 1612 break; 1613 default: 1614 val = 0; 1615 } 1616 return (val); 1617 } 1618 1619 uint8_t 1620 cmi_pci_getb(int bus, int dev, int func, int reg, int *interpose, 1621 ddi_acc_handle_t hdl) 1622 { 1623 return ((uint8_t)cmi_pci_get_cmn(bus, dev, func, reg, 1, interpose, 1624 hdl)); 1625 } 1626 1627 uint16_t 1628 cmi_pci_getw(int bus, int dev, int func, int reg, int *interpose, 1629 ddi_acc_handle_t hdl) 1630 { 1631 return ((uint16_t)cmi_pci_get_cmn(bus, dev, func, reg, 2, interpose, 1632 hdl)); 1633 } 1634 1635 uint32_t 1636 cmi_pci_getl(int bus, int dev, int func, int reg, int *interpose, 1637 ddi_acc_handle_t hdl) 1638 { 1639 return (cmi_pci_get_cmn(bus, dev, func, reg, 4, interpose, hdl)); 1640 } 1641 1642 void 1643 cmi_pci_interposeb(int bus, int dev, int func, int reg, uint8_t val) 1644 { 1645 pcii_addent(bus, dev, func, reg, val, 1); 1646 } 1647 1648 void 1649 cmi_pci_interposew(int bus, int dev, int func, int reg, uint16_t val) 1650 { 1651 pcii_addent(bus, dev, func, reg, val, 2); 1652 } 1653 1654 void 1655 cmi_pci_interposel(int bus, int dev, int func, int reg, uint32_t val) 1656 { 1657 pcii_addent(bus, dev, func, reg, val, 4); 1658 } 1659 1660 static void 1661 cmi_pci_put_cmn(int bus, int dev, int func, int reg, int asz, 1662 ddi_acc_handle_t hdl, uint32_t val) 1663 { 1664 /* 1665 * If there is an interposed value for this register invalidate it. 1666 */ 1667 pcii_rment(bus, dev, func, reg, asz); 1668 1669 if (!(cmi_pcicfg_flags & CMI_PCICFG_FLAG_WR_HWOK)) 1670 return; 1671 1672 switch (asz) { 1673 case 1: 1674 if (hdl) 1675 pci_config_put8(hdl, (off_t)reg, (uint8_t)val); 1676 else 1677 (*pci_putb_func)(bus, dev, func, reg, (uint8_t)val); 1678 break; 1679 1680 case 2: 1681 if (hdl) 1682 pci_config_put16(hdl, (off_t)reg, (uint16_t)val); 1683 else 1684 (*pci_putw_func)(bus, dev, func, reg, (uint16_t)val); 1685 break; 1686 1687 case 4: 1688 if (hdl) 1689 pci_config_put32(hdl, (off_t)reg, val); 1690 else 1691 (*pci_putl_func)(bus, dev, func, reg, val); 1692 break; 1693 1694 default: 1695 break; 1696 } 1697 } 1698 1699 void 1700 cmi_pci_putb(int bus, int dev, int func, int reg, ddi_acc_handle_t hdl, 1701 uint8_t val) 1702 { 1703 cmi_pci_put_cmn(bus, dev, func, reg, 1, hdl, val); 1704 } 1705 1706 void 1707 cmi_pci_putw(int bus, int dev, int func, int reg, ddi_acc_handle_t hdl, 1708 uint16_t val) 1709 { 1710 cmi_pci_put_cmn(bus, dev, func, reg, 2, hdl, val); 1711 } 1712 1713 void 1714 cmi_pci_putl(int bus, int dev, int func, int reg, ddi_acc_handle_t hdl, 1715 uint32_t val) 1716 { 1717 cmi_pci_put_cmn(bus, dev, func, reg, 4, hdl, val); 1718 } 1719 1720 static const struct cmi_hdl_ops cmi_hdl_ops = { 1721 #ifdef __xpv 1722 /* 1723 * CMI_HDL_SOLARIS_xVM_MCA - ops when we are an xVM dom0 1724 */ 1725 xpv_vendor, /* cmio_vendor */ 1726 xpv_vendorstr, /* cmio_vendorstr */ 1727 xpv_family, /* cmio_family */ 1728 xpv_model, /* cmio_model */ 1729 xpv_stepping, /* cmio_stepping */ 1730 xpv_chipid, /* cmio_chipid */ 1731 xpv_coreid, /* cmio_coreid */ 1732 xpv_strandid, /* cmio_strandid */ 1733 xpv_chiprev, /* cmio_chiprev */ 1734 xpv_chiprevstr, /* cmio_chiprevstr */ 1735 xpv_getsockettype, /* cmio_getsockettype */ 1736 xpv_getsocketstr, /* cmio_getsocketstr */ 1737 xpv_logical_id, /* cmio_logical_id */ 1738 NULL, /* cmio_getcr4 */ 1739 NULL, /* cmio_setcr4 */ 1740 xpv_rdmsr, /* cmio_rdmsr */ 1741 xpv_wrmsr, /* cmio_wrmsr */ 1742 xpv_msrinterpose, /* cmio_msrinterpose */ 1743 xpv_int, /* cmio_int */ 1744 xpv_online /* cmio_online */ 1745 1746 #else /* __xpv */ 1747 1748 /* 1749 * CMI_HDL_NATIVE - ops when apparently running on bare-metal 1750 */ 1751 ntv_vendor, /* cmio_vendor */ 1752 ntv_vendorstr, /* cmio_vendorstr */ 1753 ntv_family, /* cmio_family */ 1754 ntv_model, /* cmio_model */ 1755 ntv_stepping, /* cmio_stepping */ 1756 ntv_chipid, /* cmio_chipid */ 1757 ntv_coreid, /* cmio_coreid */ 1758 ntv_strandid, /* cmio_strandid */ 1759 ntv_chiprev, /* cmio_chiprev */ 1760 ntv_chiprevstr, /* cmio_chiprevstr */ 1761 ntv_getsockettype, /* cmio_getsockettype */ 1762 ntv_getsocketstr, /* cmio_getsocketstr */ 1763 ntv_logical_id, /* cmio_logical_id */ 1764 ntv_getcr4, /* cmio_getcr4 */ 1765 ntv_setcr4, /* cmio_setcr4 */ 1766 ntv_rdmsr, /* cmio_rdmsr */ 1767 ntv_wrmsr, /* cmio_wrmsr */ 1768 ntv_msrinterpose, /* cmio_msrinterpose */ 1769 ntv_int, /* cmio_int */ 1770 ntv_online /* cmio_online */ 1771 #endif 1772 }; 1773