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