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