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