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