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
call_func_ntv(int cpuid,xc_func_t func,xc_arg_t arg1,xc_arg_t arg2)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
cmi_hdl_inj_begin(cmi_hdl_t ophdl)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
cmi_hdl_inj_end(cmi_hdl_t ophdl)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
cmi_inj_tainted(void)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
msri_addent(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)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
msri_lookup(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t * valp)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
msri_rment(cmi_hdl_impl_t * hdl,uint_t msr)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
pcii_addent(int bus,int dev,int func,int reg,uint32_t val,int asz)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
pcii_lookup(int bus,int dev,int func,int reg,int asz,uint32_t * valp)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
pcii_rment(int bus,int dev,int func,int reg,int asz)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
ntv_vendor(cmi_hdl_impl_t * hdl)584 ntv_vendor(cmi_hdl_impl_t *hdl)
585 {
586 return (cpuid_getvendor(HDLPRIV(hdl)));
587 }
588
589 static const char *
ntv_vendorstr(cmi_hdl_impl_t * hdl)590 ntv_vendorstr(cmi_hdl_impl_t *hdl)
591 {
592 return (cpuid_getvendorstr(HDLPRIV(hdl)));
593 }
594
595 static uint_t
ntv_family(cmi_hdl_impl_t * hdl)596 ntv_family(cmi_hdl_impl_t *hdl)
597 {
598 return (cpuid_getfamily(HDLPRIV(hdl)));
599 }
600
601 static uint_t
ntv_model(cmi_hdl_impl_t * hdl)602 ntv_model(cmi_hdl_impl_t *hdl)
603 {
604 return (cpuid_getmodel(HDLPRIV(hdl)));
605 }
606
607 static uint_t
ntv_stepping(cmi_hdl_impl_t * hdl)608 ntv_stepping(cmi_hdl_impl_t *hdl)
609 {
610 return (cpuid_getstep(HDLPRIV(hdl)));
611 }
612
613 static uint_t
ntv_chipid(cmi_hdl_impl_t * hdl)614 ntv_chipid(cmi_hdl_impl_t *hdl)
615 {
616 return (hdl->cmih_chipid);
617
618 }
619
620 static uint_t
ntv_procnodeid(cmi_hdl_impl_t * hdl)621 ntv_procnodeid(cmi_hdl_impl_t *hdl)
622 {
623 return (hdl->cmih_procnodeid);
624 }
625
626 static uint_t
ntv_procnodes_per_pkg(cmi_hdl_impl_t * hdl)627 ntv_procnodes_per_pkg(cmi_hdl_impl_t *hdl)
628 {
629 return (hdl->cmih_procnodes_per_pkg);
630 }
631
632 static uint_t
ntv_coreid(cmi_hdl_impl_t * hdl)633 ntv_coreid(cmi_hdl_impl_t *hdl)
634 {
635 return (hdl->cmih_coreid);
636 }
637
638 static uint_t
ntv_strandid(cmi_hdl_impl_t * hdl)639 ntv_strandid(cmi_hdl_impl_t *hdl)
640 {
641 return (hdl->cmih_strandid);
642 }
643
644 static uint_t
ntv_strand_apicid(cmi_hdl_impl_t * hdl)645 ntv_strand_apicid(cmi_hdl_impl_t *hdl)
646 {
647 return (cpuid_get_apicid(HDLPRIV(hdl)));
648 }
649
650 static uint16_t
ntv_smbiosid(cmi_hdl_impl_t * hdl)651 ntv_smbiosid(cmi_hdl_impl_t *hdl)
652 {
653 return (hdl->cmih_smbiosid);
654 }
655
656 static uint_t
ntv_smb_chipid(cmi_hdl_impl_t * hdl)657 ntv_smb_chipid(cmi_hdl_impl_t *hdl)
658 {
659 return (hdl->cmih_smb_chipid);
660 }
661
662 static nvlist_t *
ntv_smb_bboard(cmi_hdl_impl_t * hdl)663 ntv_smb_bboard(cmi_hdl_impl_t *hdl)
664 {
665 return (hdl->cmih_smb_bboard);
666 }
667
668 static x86_chiprev_t
ntv_chiprev(cmi_hdl_impl_t * hdl)669 ntv_chiprev(cmi_hdl_impl_t *hdl)
670 {
671 return (cpuid_getchiprev(HDLPRIV(hdl)));
672 }
673
674 static const char *
ntv_chiprevstr(cmi_hdl_impl_t * hdl)675 ntv_chiprevstr(cmi_hdl_impl_t *hdl)
676 {
677 return (cpuid_getchiprevstr(HDLPRIV(hdl)));
678 }
679
680 static uint32_t
ntv_getsockettype(cmi_hdl_impl_t * hdl)681 ntv_getsockettype(cmi_hdl_impl_t *hdl)
682 {
683 return (cpuid_getsockettype(HDLPRIV(hdl)));
684 }
685
686 static const char *
ntv_getsocketstr(cmi_hdl_impl_t * hdl)687 ntv_getsocketstr(cmi_hdl_impl_t *hdl)
688 {
689 return (cpuid_getsocketstr(HDLPRIV(hdl)));
690 }
691
692 static uint_t
ntv_chipsig(cmi_hdl_impl_t * hdl)693 ntv_chipsig(cmi_hdl_impl_t *hdl)
694 {
695 return (cpuid_getsig(HDLPRIV(hdl)));
696 }
697
698 static cmi_errno_t
cmi_cpuid_cache_to_cmi(int err)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
ntv_ncache(cmi_hdl_impl_t * hdl,uint32_t * ncache)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
ntv_cache(cmi_hdl_impl_t * hdl,uint32_t cno,x86_cache_t * cachep)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
ntv_logical_id(cmi_hdl_impl_t * hdl)728 ntv_logical_id(cmi_hdl_impl_t *hdl)
729 {
730 return (HDLPRIV(hdl)->cpu_id);
731 }
732
733 /*ARGSUSED*/
734 static int
ntv_getcr4_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)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
ntv_getcr4(cmi_hdl_impl_t * hdl)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
ntv_setcr4_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)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
ntv_setcr4(cmi_hdl_impl_t * hdl,ulong_t val)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
ntv_rdmsr_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)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
ntv_rdmsr(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t * valp)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
ntv_wrmsr_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)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
ntv_wrmsr(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)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
ntv_msrinterpose(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)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
ntv_int_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)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
ntv_int(cmi_hdl_impl_t * hdl,int int_no)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
ntv_online(cmi_hdl_impl_t * hdl,int new_status,int * old_status)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
xpv_vendor(cmi_hdl_impl_t * hdl)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 *
xpv_vendorstr(cmi_hdl_impl_t * hdl)927 xpv_vendorstr(cmi_hdl_impl_t *hdl)
928 {
929 return (xen_physcpu_vendorstr(HDLPRIV(hdl)));
930 }
931
932 static uint_t
xpv_family(cmi_hdl_impl_t * hdl)933 xpv_family(cmi_hdl_impl_t *hdl)
934 {
935 return (xen_physcpu_family(HDLPRIV(hdl)));
936 }
937
938 static uint_t
xpv_model(cmi_hdl_impl_t * hdl)939 xpv_model(cmi_hdl_impl_t *hdl)
940 {
941 return (xen_physcpu_model(HDLPRIV(hdl)));
942 }
943
944 static uint_t
xpv_stepping(cmi_hdl_impl_t * hdl)945 xpv_stepping(cmi_hdl_impl_t *hdl)
946 {
947 return (xen_physcpu_stepping(HDLPRIV(hdl)));
948 }
949
950 static uint_t
xpv_chipid(cmi_hdl_impl_t * hdl)951 xpv_chipid(cmi_hdl_impl_t *hdl)
952 {
953 return (hdl->cmih_chipid);
954 }
955
956 static uint_t
xpv_procnodeid(cmi_hdl_impl_t * hdl)957 xpv_procnodeid(cmi_hdl_impl_t *hdl)
958 {
959 return (hdl->cmih_procnodeid);
960 }
961
962 static uint_t
xpv_procnodes_per_pkg(cmi_hdl_impl_t * hdl)963 xpv_procnodes_per_pkg(cmi_hdl_impl_t *hdl)
964 {
965 return (hdl->cmih_procnodes_per_pkg);
966 }
967
968 static uint_t
xpv_coreid(cmi_hdl_impl_t * hdl)969 xpv_coreid(cmi_hdl_impl_t *hdl)
970 {
971 return (hdl->cmih_coreid);
972 }
973
974 static uint_t
xpv_strandid(cmi_hdl_impl_t * hdl)975 xpv_strandid(cmi_hdl_impl_t *hdl)
976 {
977 return (hdl->cmih_strandid);
978 }
979
980 static uint_t
xpv_strand_apicid(cmi_hdl_impl_t * hdl)981 xpv_strand_apicid(cmi_hdl_impl_t *hdl)
982 {
983 return (xen_physcpu_initial_apicid(HDLPRIV(hdl)));
984 }
985
986 static uint16_t
xpv_smbiosid(cmi_hdl_impl_t * hdl)987 xpv_smbiosid(cmi_hdl_impl_t *hdl)
988 {
989 return (hdl->cmih_smbiosid);
990 }
991
992 static uint_t
xpv_smb_chipid(cmi_hdl_impl_t * hdl)993 xpv_smb_chipid(cmi_hdl_impl_t *hdl)
994 {
995 return (hdl->cmih_smb_chipid);
996 }
997
998 static nvlist_t *
xpv_smb_bboard(cmi_hdl_impl_t * hdl)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
xpv_chiprev(cmi_hdl_impl_t * hdl)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 *
xpv_chiprevstr(cmi_hdl_impl_t * hdl)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
xpv_getsockettype(cmi_hdl_impl_t * hdl)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 *
xpv_getsocketstr(cmi_hdl_impl_t * hdl)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
xpv_chipsig(cmi_hdl_impl_t * hdl)1042 xpv_chipsig(cmi_hdl_impl_t *hdl)
1043 {
1044 return (0);
1045 }
1046
1047 static cmi_errno_t
xpv_ncache(cmi_hdl_impl_t * hdl,uint32_t * ncache)1048 xpv_ncache(cmi_hdl_impl_t *hdl, uint32_t *ncache)
1049 {
1050 return (CMIERR_NOTSUP);
1051 }
1052
1053 static cmi_errno_t
xpv_cache(cmi_hdl_impl_t * hdl,uint32_t cno,x86_cache_t * cachep)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
xpv_logical_id(cmi_hdl_impl_t * hdl)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
xpv_rdmsr(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t * valp)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
xpv_wrmsr_cmn(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val,boolean_t intpose)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
xpv_wrmsr(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)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
xpv_msrinterpose(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)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
xpv_int(cmi_hdl_impl_t * hdl,int int_no)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
xpv_online(cmi_hdl_impl_t * hdl,int new_status,int * old_status)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 *
cpu_search(enum cmi_hdl_class class,uint_t chipid,uint_t coreid,uint_t strandid)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
cpu_is_cmt(void * priv)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 *
cmi_hdl_ent_lookup(uint_t chipid,uint_t coreid,uint_t strandid)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
cmi_hdl_create(enum cmi_hdl_class class,uint_t chipid,uint_t coreid,uint_t strandid)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
cmi_read_smbios(cmi_hdl_t ophdl)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
cmi_hdl_hold(cmi_hdl_t ophdl)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
cmi_hdl_canref(cmi_hdl_ent_t * ent)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
cmi_hdl_rele(cmi_hdl_t ophdl)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
cmi_hdl_destroy(cmi_hdl_t ophdl)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
cmi_hdl_setspecific(cmi_hdl_t ophdl,void * arg)1521 cmi_hdl_setspecific(cmi_hdl_t ophdl, void *arg)
1522 {
1523 IMPLHDL(ophdl)->cmih_spec = arg;
1524 }
1525
1526 void *
cmi_hdl_getspecific(cmi_hdl_t ophdl)1527 cmi_hdl_getspecific(cmi_hdl_t ophdl)
1528 {
1529 return (IMPLHDL(ophdl)->cmih_spec);
1530 }
1531
1532 void
cmi_hdl_setmc(cmi_hdl_t ophdl,const struct cmi_mc_ops * mcops,void * mcdata)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 *
cmi_hdl_getmcops(cmi_hdl_t ophdl)1543 cmi_hdl_getmcops(cmi_hdl_t ophdl)
1544 {
1545 return (IMPLHDL(ophdl)->cmih_mcops);
1546 }
1547
1548 void *
cmi_hdl_getmcdata(cmi_hdl_t ophdl)1549 cmi_hdl_getmcdata(cmi_hdl_t ophdl)
1550 {
1551 return (IMPLHDL(ophdl)->cmih_mcdata);
1552 }
1553
1554 cmi_hdl_t
cmi_hdl_lookup(enum cmi_hdl_class class,uint_t chipid,uint_t coreid,uint_t strandid)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
cmi_hdl_any(void)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
cmi_hdl_walk(int (* cbfunc)(cmi_hdl_t,void *,void *,void *),void * arg1,void * arg2,void * arg3)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
cmi_hdl_setcmi(cmi_hdl_t ophdl,void * cmi,void * cmidata)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 *
cmi_hdl_getcmi(cmi_hdl_t ophdl)1641 cmi_hdl_getcmi(cmi_hdl_t ophdl)
1642 {
1643 return (IMPLHDL(ophdl)->cmih_cmi);
1644 }
1645
1646 void *
cmi_hdl_getcmidata(cmi_hdl_t ophdl)1647 cmi_hdl_getcmidata(cmi_hdl_t ophdl)
1648 {
1649 return (IMPLHDL(ophdl)->cmih_cmidata);
1650 }
1651
1652 enum cmi_hdl_class
cmi_hdl_class(cmi_hdl_t ophdl)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 */
CMI_HDL_OPFUNC(vendor,uint_t)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
cmi_hdl_int(cmi_hdl_t ophdl,int num)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
cmi_hdl_online(cmi_hdl_t ophdl,int new_status,int * old_status)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
cmi_ntv_hwchipid(cpu_t * cp)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
cmi_ntv_hwprocnodeid(cpu_t * cp)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
cmi_ntv_hwcoreid(cpu_t * cp)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
cmi_ntv_hwstrandid(cpu_t * cp)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
cmi_ntv_hwdisable_mce_xc(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
cmi_ntv_hwdisable_mce(cmi_hdl_t hdl)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
cmi_hdlconf_rdmsr_nohw(cmi_hdl_t ophdl)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
cmi_hdlconf_wrmsr_nohw(cmi_hdl_t ophdl)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
cmi_hdl_rdmsr(cmi_hdl_t ophdl,uint_t msr,uint64_t * valp)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
cmi_hdl_wrmsr(cmi_hdl_t ophdl,uint_t msr,uint64_t val)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
cmi_hdl_enable_mce(cmi_hdl_t ophdl)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
cmi_hdl_msrinterpose(cmi_hdl_t ophdl,cmi_mca_regs_t * regs,uint_t nregs)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
cmi_hdl_msrforward(cmi_hdl_t ophdl,cmi_mca_regs_t * regs,uint_t nregs)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
cmi_pcird_nohw(void)1883 cmi_pcird_nohw(void)
1884 {
1885 cmi_pcicfg_flags &= ~CMI_PCICFG_FLAG_RD_HWOK;
1886 }
1887
1888 void
cmi_pciwr_nohw(void)1889 cmi_pciwr_nohw(void)
1890 {
1891 cmi_pcicfg_flags &= ~CMI_PCICFG_FLAG_WR_HWOK;
1892 }
1893
1894 static uint32_t
cmi_pci_get_cmn(int bus,int dev,int func,int reg,int asz,int * interpose,ddi_acc_handle_t hdl)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
cmi_pci_getb(int bus,int dev,int func,int reg,int * interpose,ddi_acc_handle_t hdl)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
cmi_pci_getw(int bus,int dev,int func,int reg,int * interpose,ddi_acc_handle_t hdl)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
cmi_pci_getl(int bus,int dev,int func,int reg,int * interpose,ddi_acc_handle_t hdl)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
cmi_pci_interposeb(int bus,int dev,int func,int reg,uint8_t val)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
cmi_pci_interposew(int bus,int dev,int func,int reg,uint16_t val)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
cmi_pci_interposel(int bus,int dev,int func,int reg,uint32_t val)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
cmi_pci_put_cmn(int bus,int dev,int func,int reg,int asz,ddi_acc_handle_t hdl,uint32_t val)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
cmi_pci_putb(int bus,int dev,int func,int reg,ddi_acc_handle_t hdl,uint8_t val)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
cmi_pci_putw(int bus,int dev,int func,int reg,ddi_acc_handle_t hdl,uint16_t val)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
cmi_pci_putl(int bus,int dev,int func,int reg,ddi_acc_handle_t hdl,uint32_t val)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
cmi_cache_ncaches(cmi_hdl_t hdl,uint32_t * ncache)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
cmi_cache_info(cmi_hdl_t hdl,uint32_t cno,x86_cache_t * cachep)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