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