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