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