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