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