xref: /illumos-gate/usr/src/uts/i86pc/os/cmi_hw.c (revision dd23d762)
120c794b3Sgavinm /*
220c794b3Sgavinm  * CDDL HEADER START
320c794b3Sgavinm  *
420c794b3Sgavinm  * The contents of this file are subject to the terms of the
520c794b3Sgavinm  * Common Development and Distribution License (the "License").
620c794b3Sgavinm  * You may not use this file except in compliance with the License.
720c794b3Sgavinm  *
820c794b3Sgavinm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
920c794b3Sgavinm  * or http://www.opensolaris.org/os/licensing.
1020c794b3Sgavinm  * See the License for the specific language governing permissions
1120c794b3Sgavinm  * and limitations under the License.
1220c794b3Sgavinm  *
1320c794b3Sgavinm  * When distributing Covered Code, include this CDDL HEADER in each
1420c794b3Sgavinm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1520c794b3Sgavinm  * If applicable, add the following below this CDDL HEADER, with the
1620c794b3Sgavinm  * fields enclosed by brackets "[]" replaced with your own identifying
1720c794b3Sgavinm  * information: Portions Copyright [yyyy] [name of copyright owner]
1820c794b3Sgavinm  *
1920c794b3Sgavinm  * CDDL HEADER END
2020c794b3Sgavinm  */
2120c794b3Sgavinm 
2220c794b3Sgavinm /*
232d2efdc6SVuong Nguyen  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
240ce813ffSRobert Mustacchi  * Copyright (c) 2019, Joyent, Inc.
25*dd23d762SRobert Mustacchi  * Copyright 2023 Oxide Computer Company
2620c794b3Sgavinm  */
27a3114836SGerry Liu /*
28a3114836SGerry Liu  * Copyright (c) 2010, Intel Corporation.
29a3114836SGerry Liu  * All rights reserved.
30a3114836SGerry Liu  */
3120c794b3Sgavinm 
3220c794b3Sgavinm /*
3320c794b3Sgavinm  * CPU Module Interface - hardware abstraction.
3420c794b3Sgavinm  */
3520c794b3Sgavinm 
36349b53ddSStuart Maybee #ifdef __xpv
37349b53ddSStuart Maybee #include <sys/xpv_user.h>
38349b53ddSStuart Maybee #endif
39349b53ddSStuart Maybee 
4020c794b3Sgavinm #include <sys/types.h>
4120c794b3Sgavinm #include <sys/cpu_module.h>
4220c794b3Sgavinm #include <sys/kmem.h>
4320c794b3Sgavinm #include <sys/x86_archext.h>
4420c794b3Sgavinm #include <sys/cpuvar.h>
4520c794b3Sgavinm #include <sys/ksynch.h>
4620c794b3Sgavinm #include <sys/x_call.h>
4720c794b3Sgavinm #include <sys/pghw.h>
485667185bSSrihari Venkatesan #include <sys/pci_cfgacc.h>
4920c794b3Sgavinm #include <sys/pci_cfgspace.h>
5020c794b3Sgavinm #include <sys/archsystm.h>
5120c794b3Sgavinm #include <sys/ontrap.h>
5220c794b3Sgavinm #include <sys/controlregs.h>
5320c794b3Sgavinm #include <sys/sunddi.h>
54e3d60c9bSAdrian Frost #include <sys/trap.h>
55e4b86885SCheng Sean Ye #include <sys/mca_x86.h>
56e4b86885SCheng Sean Ye #include <sys/processor.h>
57074bb90dSTom Pothier #include <sys/cmn_err.h>
58074bb90dSTom Pothier #include <sys/nvpair.h>
59074bb90dSTom Pothier #include <sys/fm/util.h>
60074bb90dSTom Pothier #include <sys/fm/protocol.h>
61074bb90dSTom Pothier #include <sys/fm/smb/fmsmb.h>
62074bb90dSTom Pothier #include <sys/cpu_module_impl.h>
63074bb90dSTom Pothier 
64074bb90dSTom Pothier /*
65074bb90dSTom Pothier  * Variable which determines if the SMBIOS supports x86 generic topology; or
66074bb90dSTom Pothier  * if legacy topolgy enumeration will occur.
67074bb90dSTom Pothier  */
68074bb90dSTom Pothier extern int x86gentopo_legacy;
69e4b86885SCheng Sean Ye 
7020c794b3Sgavinm /*
7120c794b3Sgavinm  * Outside of this file consumers use the opaque cmi_hdl_t.  This
7220c794b3Sgavinm  * definition is duplicated in the generic_cpu mdb module, so keep
7320c794b3Sgavinm  * them in-sync when making changes.
7420c794b3Sgavinm  */
7520c794b3Sgavinm typedef struct cmi_hdl_impl {
7620c794b3Sgavinm 	enum cmi_hdl_class cmih_class;		/* Handle nature */
77e4b86885SCheng Sean Ye 	const struct cmi_hdl_ops *cmih_ops;	/* Operations vector */
7820c794b3Sgavinm 	uint_t cmih_chipid;			/* Chipid of cpu resource */
798031591dSSrihari Venkatesan 	uint_t cmih_procnodeid;			/* Nodeid of cpu resource */
8020c794b3Sgavinm 	uint_t cmih_coreid;			/* Core within die */
8120c794b3Sgavinm 	uint_t cmih_strandid;			/* Thread within core */
828031591dSSrihari Venkatesan 	uint_t cmih_procnodes_per_pkg;		/* Nodes in a processor */
83e4b86885SCheng Sean Ye 	boolean_t cmih_mstrand;			/* cores are multithreaded */
8420c794b3Sgavinm 	volatile uint32_t *cmih_refcntp;	/* Reference count pointer */
8520c794b3Sgavinm 	uint64_t cmih_msrsrc;			/* MSR data source flags */
8620c794b3Sgavinm 	void *cmih_hdlpriv;			/* cmi_hw.c private data */
8720c794b3Sgavinm 	void *cmih_spec;			/* cmi_hdl_{set,get}_specific */
8820c794b3Sgavinm 	void *cmih_cmi;				/* cpu mod control structure */
8920c794b3Sgavinm 	void *cmih_cmidata;			/* cpu mod private data */
9020c794b3Sgavinm 	const struct cmi_mc_ops *cmih_mcops;	/* Memory-controller ops */
9120c794b3Sgavinm 	void *cmih_mcdata;			/* Memory-controller data */
92e4b86885SCheng Sean Ye 	uint64_t cmih_flags;			/* See CMIH_F_* below */
93074bb90dSTom Pothier 	uint16_t cmih_smbiosid;			/* SMBIOS Type 4 struct ID */
94074bb90dSTom Pothier 	uint_t cmih_smb_chipid;			/* SMBIOS factored chipid */
95074bb90dSTom Pothier 	nvlist_t *cmih_smb_bboard;		/* SMBIOS bboard nvlist */
9620c794b3Sgavinm } cmi_hdl_impl_t;
9720c794b3Sgavinm 
9820c794b3Sgavinm #define	IMPLHDL(ophdl)	((cmi_hdl_impl_t *)ophdl)
99e4b86885SCheng Sean Ye #define	HDLOPS(hdl)	((hdl)->cmih_ops)
100e4b86885SCheng Sean Ye 
101e4b86885SCheng Sean Ye #define	CMIH_F_INJACTV		0x1ULL
102a3114836SGerry Liu #define	CMIH_F_DEAD		0x2ULL
103e4b86885SCheng Sean Ye 
104e4b86885SCheng Sean Ye /*
105e4b86885SCheng Sean Ye  * Ops structure for handle operations.
106e4b86885SCheng Sean Ye  */
107e4b86885SCheng Sean Ye struct cmi_hdl_ops {
108e4b86885SCheng Sean Ye 	/*
109e4b86885SCheng Sean Ye 	 * These ops are required in an implementation.
110e4b86885SCheng Sean Ye 	 */
111e4b86885SCheng Sean Ye 	uint_t (*cmio_vendor)(cmi_hdl_impl_t *);
112e4b86885SCheng Sean Ye 	const char *(*cmio_vendorstr)(cmi_hdl_impl_t *);
113e4b86885SCheng Sean Ye 	uint_t (*cmio_family)(cmi_hdl_impl_t *);
114e4b86885SCheng Sean Ye 	uint_t (*cmio_model)(cmi_hdl_impl_t *);
115e4b86885SCheng Sean Ye 	uint_t (*cmio_stepping)(cmi_hdl_impl_t *);
116e4b86885SCheng Sean Ye 	uint_t (*cmio_chipid)(cmi_hdl_impl_t *);
1178031591dSSrihari Venkatesan 	uint_t (*cmio_procnodeid)(cmi_hdl_impl_t *);
118e4b86885SCheng Sean Ye 	uint_t (*cmio_coreid)(cmi_hdl_impl_t *);
119e4b86885SCheng Sean Ye 	uint_t (*cmio_strandid)(cmi_hdl_impl_t *);
1208031591dSSrihari Venkatesan 	uint_t (*cmio_procnodes_per_pkg)(cmi_hdl_impl_t *);
121074bb90dSTom Pothier 	uint_t (*cmio_strand_apicid)(cmi_hdl_impl_t *);
12222e4c3acSKeith M Wesolowski 	x86_chiprev_t (*cmio_chiprev)(cmi_hdl_impl_t *);
123e4b86885SCheng Sean Ye 	const char *(*cmio_chiprevstr)(cmi_hdl_impl_t *);
124e4b86885SCheng Sean Ye 	uint32_t (*cmio_getsockettype)(cmi_hdl_impl_t *);
12589e921d5SKuriakose Kuruvilla 	const char *(*cmio_getsocketstr)(cmi_hdl_impl_t *);
1262a613b59SRobert Mustacchi 	uint_t (*cmio_chipsig)(cmi_hdl_impl_t *);
127*dd23d762SRobert Mustacchi 	cmi_errno_t (*cmio_ncache)(cmi_hdl_impl_t *, uint32_t *);
128*dd23d762SRobert Mustacchi 	cmi_errno_t (*cmio_cache)(cmi_hdl_impl_t *, uint32_t, x86_cache_t *);
12989e921d5SKuriakose Kuruvilla 
130e4b86885SCheng Sean Ye 	id_t (*cmio_logical_id)(cmi_hdl_impl_t *);
131e4b86885SCheng Sean Ye 	/*
132e4b86885SCheng Sean Ye 	 * These ops are optional in an implementation.
133e4b86885SCheng Sean Ye 	 */
134e4b86885SCheng Sean Ye 	ulong_t (*cmio_getcr4)(cmi_hdl_impl_t *);
135e4b86885SCheng Sean Ye 	void (*cmio_setcr4)(cmi_hdl_impl_t *, ulong_t);
136e4b86885SCheng Sean Ye 	cmi_errno_t (*cmio_rdmsr)(cmi_hdl_impl_t *, uint_t, uint64_t *);
137e4b86885SCheng Sean Ye 	cmi_errno_t (*cmio_wrmsr)(cmi_hdl_impl_t *, uint_t, uint64_t);
138e4b86885SCheng Sean Ye 	cmi_errno_t (*cmio_msrinterpose)(cmi_hdl_impl_t *, uint_t, uint64_t);
139e4b86885SCheng Sean Ye 	void (*cmio_int)(cmi_hdl_impl_t *, int);
140e4b86885SCheng Sean Ye 	int (*cmio_online)(cmi_hdl_impl_t *, int, int *);
141074bb90dSTom Pothier 	uint16_t (*cmio_smbiosid) (cmi_hdl_impl_t *);
142074bb90dSTom Pothier 	uint_t (*cmio_smb_chipid)(cmi_hdl_impl_t *);
143074bb90dSTom Pothier 	nvlist_t *(*cmio_smb_bboard)(cmi_hdl_impl_t *);
144e4b86885SCheng Sean Ye };
145e4b86885SCheng Sean Ye 
146e4b86885SCheng Sean Ye static const struct cmi_hdl_ops cmi_hdl_ops;
14720c794b3Sgavinm 
14820c794b3Sgavinm /*
14920c794b3Sgavinm  * Handles are looked up from contexts such as polling, injection etc
15020c794b3Sgavinm  * where the context is reasonably well defined (although a poller could
15120c794b3Sgavinm  * interrupt any old thread holding any old lock).  They are also looked
15220c794b3Sgavinm  * up by machine check handlers, which may strike at inconvenient times
15320c794b3Sgavinm  * such as during handle initialization or destruction or during handle
15420c794b3Sgavinm  * lookup (which the #MC handler itself will also have to perform).
15520c794b3Sgavinm  *
15620c794b3Sgavinm  * So keeping handles in a linked list makes locking difficult when we
1572d39cb4cSVuong Nguyen  * consider #MC handlers.  Our solution is to have a look-up table indexed
15820c794b3Sgavinm  * by that which uniquely identifies a handle - chip/core/strand id -
1592d39cb4cSVuong Nguyen  * with each entry a structure including a pointer to a handle
16020c794b3Sgavinm  * structure for the resource, and a reference count for the handle.
16120c794b3Sgavinm  * Reference counts are modified atomically.  The public cmi_hdl_hold
16220c794b3Sgavinm  * always succeeds because this can only be used after handle creation
163e4b86885SCheng Sean Ye  * and before the call to destruct, so the hold count is already at least one.
16420c794b3Sgavinm  * In other functions that lookup a handle (cmi_hdl_lookup, cmi_hdl_any)
16520c794b3Sgavinm  * we must be certain that the count has not already decrmented to zero
16620c794b3Sgavinm  * before applying our hold.
16720c794b3Sgavinm  *
1682d39cb4cSVuong Nguyen  * The table is an array of maximum number of chips defined in
1692d39cb4cSVuong Nguyen  * CMI_CHIPID_ARR_SZ indexed by the chip id. If the chip is not present, the
1702d39cb4cSVuong Nguyen  * entry is NULL. Each entry is a pointer to another array which contains a
1712d39cb4cSVuong Nguyen  * list of all strands of the chip. This first level table is allocated when
1722d39cb4cSVuong Nguyen  * first we want to populate an entry. The size of the latter (per chip) table
1732d39cb4cSVuong Nguyen  * is CMI_MAX_STRANDS_PER_CHIP and it is populated when one of its cpus starts.
1742d39cb4cSVuong Nguyen  *
1752d39cb4cSVuong Nguyen  * Ideally we should only allocate to the actual number of chips, cores per
1762d39cb4cSVuong Nguyen  * chip and strand per core. The number of chips is not available until all
1772d39cb4cSVuong Nguyen  * of them are passed. The number of cores and strands are partially available.
1782d39cb4cSVuong Nguyen  * For now we stick with the above approach.
17920c794b3Sgavinm  */
1802d39cb4cSVuong Nguyen #define	CMI_MAX_CHIPID_NBITS		6	/* max chipid of 63 */
1812d39cb4cSVuong Nguyen #define	CMI_MAX_CORES_PER_CHIP_NBITS	4	/* 16 cores per chip max */
1822d39cb4cSVuong Nguyen #define	CMI_MAX_STRANDS_PER_CORE_NBITS	3	/* 8 strands per core max */
183a3c46958Sgavinm 
1842d39cb4cSVuong Nguyen #define	CMI_MAX_CHIPID			((1 << (CMI_MAX_CHIPID_NBITS)) - 1)
1852d2efdc6SVuong Nguyen #define	CMI_MAX_CORES_PER_CHIP(cbits)	(1 << (cbits))
1862d2efdc6SVuong Nguyen #define	CMI_MAX_COREID(cbits)		((1 << (cbits)) - 1)
1872d2efdc6SVuong Nguyen #define	CMI_MAX_STRANDS_PER_CORE(sbits)	(1 << (sbits))
1882d2efdc6SVuong Nguyen #define	CMI_MAX_STRANDID(sbits)		((1 << (sbits)) - 1)
1892d2efdc6SVuong Nguyen #define	CMI_MAX_STRANDS_PER_CHIP(cbits, sbits)	\
1902d2efdc6SVuong Nguyen 	(CMI_MAX_CORES_PER_CHIP(cbits) * CMI_MAX_STRANDS_PER_CORE(sbits))
191a3c46958Sgavinm 
1922d39cb4cSVuong Nguyen #define	CMI_CHIPID_ARR_SZ		(1 << CMI_MAX_CHIPID_NBITS)
19320c794b3Sgavinm 
1942d39cb4cSVuong Nguyen typedef struct cmi_hdl_ent {
195a3c46958Sgavinm 	volatile uint32_t cmae_refcnt;
196a3c46958Sgavinm 	cmi_hdl_impl_t *cmae_hdlp;
1972d39cb4cSVuong Nguyen } cmi_hdl_ent_t;
19820c794b3Sgavinm 
1992d39cb4cSVuong Nguyen static cmi_hdl_ent_t *cmi_chip_tab[CMI_CHIPID_ARR_SZ];
20020c794b3Sgavinm 
2012d2efdc6SVuong Nguyen /*
2022d2efdc6SVuong Nguyen  * Default values for the number of core and strand bits.
2032d2efdc6SVuong Nguyen  */
2042d2efdc6SVuong Nguyen uint_t cmi_core_nbits = CMI_MAX_CORES_PER_CHIP_NBITS;
2052d2efdc6SVuong Nguyen uint_t cmi_strand_nbits = CMI_MAX_STRANDS_PER_CORE_NBITS;
2062d2efdc6SVuong Nguyen static int cmi_ext_topo_check = 0;
2072d2efdc6SVuong Nguyen 
20820c794b3Sgavinm /*
20920c794b3Sgavinm  * Controls where we will source PCI config space data.
21020c794b3Sgavinm  */
21120c794b3Sgavinm #define	CMI_PCICFG_FLAG_RD_HWOK		0x0001
21220c794b3Sgavinm #define	CMI_PCICFG_FLAG_RD_INTERPOSEOK	0X0002
21320c794b3Sgavinm #define	CMI_PCICFG_FLAG_WR_HWOK		0x0004
21420c794b3Sgavinm #define	CMI_PCICFG_FLAG_WR_INTERPOSEOK	0X0008
21520c794b3Sgavinm 
21620c794b3Sgavinm static uint64_t cmi_pcicfg_flags =
21720c794b3Sgavinm     CMI_PCICFG_FLAG_RD_HWOK | CMI_PCICFG_FLAG_RD_INTERPOSEOK |
21820c794b3Sgavinm     CMI_PCICFG_FLAG_WR_HWOK | CMI_PCICFG_FLAG_WR_INTERPOSEOK;
21920c794b3Sgavinm 
22020c794b3Sgavinm /*
22120c794b3Sgavinm  * The flags for individual cpus are kept in their per-cpu handle cmih_msrsrc
22220c794b3Sgavinm  */
22320c794b3Sgavinm #define	CMI_MSR_FLAG_RD_HWOK		0x0001
22420c794b3Sgavinm #define	CMI_MSR_FLAG_RD_INTERPOSEOK	0x0002
22520c794b3Sgavinm #define	CMI_MSR_FLAG_WR_HWOK		0x0004
22620c794b3Sgavinm #define	CMI_MSR_FLAG_WR_INTERPOSEOK	0x0008
22720c794b3Sgavinm 
22820c794b3Sgavinm int cmi_call_func_ntv_tries = 3;
22920c794b3Sgavinm 
23020c794b3Sgavinm static cmi_errno_t
call_func_ntv(int cpuid,xc_func_t func,xc_arg_t arg1,xc_arg_t arg2)23120c794b3Sgavinm call_func_ntv(int cpuid, xc_func_t func, xc_arg_t arg1, xc_arg_t arg2)
23220c794b3Sgavinm {
23320c794b3Sgavinm 	cmi_errno_t rc = -1;
23420c794b3Sgavinm 	int i;
23520c794b3Sgavinm 
23620c794b3Sgavinm 	kpreempt_disable();
23720c794b3Sgavinm 
23820c794b3Sgavinm 	if (CPU->cpu_id == cpuid) {
23920c794b3Sgavinm 		(*func)(arg1, arg2, (xc_arg_t)&rc);
24020c794b3Sgavinm 	} else {
24120c794b3Sgavinm 		/*
24220c794b3Sgavinm 		 * This should not happen for a #MC trap or a poll, so
24320c794b3Sgavinm 		 * this is likely an error injection or similar.
24420c794b3Sgavinm 		 * We will try to cross call with xc_trycall - we
24520c794b3Sgavinm 		 * can't guarantee success with xc_call because
24620c794b3Sgavinm 		 * the interrupt code in the case of a #MC may
24720c794b3Sgavinm 		 * already hold the xc mutex.
24820c794b3Sgavinm 		 */
24920c794b3Sgavinm 		for (i = 0; i < cmi_call_func_ntv_tries; i++) {
25020c794b3Sgavinm 			cpuset_t cpus;
25120c794b3Sgavinm 
25220c794b3Sgavinm 			CPUSET_ONLY(cpus, cpuid);
253f34a7178SJoe Bonasera 			xc_priority(arg1, arg2, (xc_arg_t)&rc,
254f34a7178SJoe Bonasera 			    CPUSET2BV(cpus), func);
25520c794b3Sgavinm 			if (rc != -1)
25620c794b3Sgavinm 				break;
25720c794b3Sgavinm 
25820c794b3Sgavinm 			DELAY(1);
25920c794b3Sgavinm 		}
26020c794b3Sgavinm 	}
26120c794b3Sgavinm 
26220c794b3Sgavinm 	kpreempt_enable();
26320c794b3Sgavinm 
26420c794b3Sgavinm 	return (rc != -1 ? rc : CMIERR_DEADLOCK);
26520c794b3Sgavinm }
26620c794b3Sgavinm 
267e4b86885SCheng Sean Ye static uint64_t injcnt;
268e4b86885SCheng Sean Ye 
269e4b86885SCheng Sean Ye void
cmi_hdl_inj_begin(cmi_hdl_t ophdl)270e4b86885SCheng Sean Ye cmi_hdl_inj_begin(cmi_hdl_t ophdl)
271e4b86885SCheng Sean Ye {
272e4b86885SCheng Sean Ye 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
273e4b86885SCheng Sean Ye 
274e4b86885SCheng Sean Ye 	if (hdl != NULL)
275e4b86885SCheng Sean Ye 		hdl->cmih_flags |= CMIH_F_INJACTV;
276e4b86885SCheng Sean Ye 	if (injcnt++ == 0) {
277e4b86885SCheng Sean Ye 		cmn_err(CE_NOTE, "Hardware error injection/simulation "
278e4b86885SCheng Sean Ye 		    "activity noted");
279e4b86885SCheng Sean Ye 	}
280e4b86885SCheng Sean Ye }
281e4b86885SCheng Sean Ye 
282e4b86885SCheng Sean Ye void
cmi_hdl_inj_end(cmi_hdl_t ophdl)283e4b86885SCheng Sean Ye cmi_hdl_inj_end(cmi_hdl_t ophdl)
284e4b86885SCheng Sean Ye {
285e4b86885SCheng Sean Ye 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
286e4b86885SCheng Sean Ye 
287e4b86885SCheng Sean Ye 	ASSERT(hdl == NULL || hdl->cmih_flags & CMIH_F_INJACTV);
288e4b86885SCheng Sean Ye 	if (hdl != NULL)
289e4b86885SCheng Sean Ye 		hdl->cmih_flags &= ~CMIH_F_INJACTV;
290e4b86885SCheng Sean Ye }
291e4b86885SCheng Sean Ye 
292e4b86885SCheng Sean Ye boolean_t
cmi_inj_tainted(void)293e4b86885SCheng Sean Ye cmi_inj_tainted(void)
294e4b86885SCheng Sean Ye {
295e4b86885SCheng Sean Ye 	return (injcnt != 0 ? B_TRUE : B_FALSE);
296e4b86885SCheng Sean Ye }
297e4b86885SCheng Sean Ye 
29820c794b3Sgavinm /*
29920c794b3Sgavinm  *	 =======================================================
30020c794b3Sgavinm  *	|	MSR Interposition				|
30120c794b3Sgavinm  *	|	-----------------				|
30220c794b3Sgavinm  *	|							|
30320c794b3Sgavinm  *	 -------------------------------------------------------
30420c794b3Sgavinm  */
30520c794b3Sgavinm 
30620c794b3Sgavinm #define	CMI_MSRI_HASHSZ		16
30720c794b3Sgavinm #define	CMI_MSRI_HASHIDX(hdl, msr) \
3083df2e8b2SRobert Mustacchi 	((((uintptr_t)(hdl) >> 3) + (msr)) % (CMI_MSRI_HASHSZ - 1))
30920c794b3Sgavinm 
31020c794b3Sgavinm struct cmi_msri_bkt {
31120c794b3Sgavinm 	kmutex_t msrib_lock;
31220c794b3Sgavinm 	struct cmi_msri_hashent *msrib_head;
31320c794b3Sgavinm };
31420c794b3Sgavinm 
31520c794b3Sgavinm struct cmi_msri_hashent {
31620c794b3Sgavinm 	struct cmi_msri_hashent *msrie_next;
31720c794b3Sgavinm 	struct cmi_msri_hashent *msrie_prev;
31820c794b3Sgavinm 	cmi_hdl_impl_t *msrie_hdl;
31920c794b3Sgavinm 	uint_t msrie_msrnum;
32020c794b3Sgavinm 	uint64_t msrie_msrval;
32120c794b3Sgavinm };
32220c794b3Sgavinm 
32320c794b3Sgavinm #define	CMI_MSRI_MATCH(ent, hdl, req_msr) \
32420c794b3Sgavinm 	((ent)->msrie_hdl == (hdl) && (ent)->msrie_msrnum == (req_msr))
32520c794b3Sgavinm 
32620c794b3Sgavinm static struct cmi_msri_bkt msrihash[CMI_MSRI_HASHSZ];
32720c794b3Sgavinm 
32820c794b3Sgavinm static void
msri_addent(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)329e4b86885SCheng Sean Ye msri_addent(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
33020c794b3Sgavinm {
331e4b86885SCheng Sean Ye 	int idx = CMI_MSRI_HASHIDX(hdl, msr);
33220c794b3Sgavinm 	struct cmi_msri_bkt *hbp = &msrihash[idx];
33320c794b3Sgavinm 	struct cmi_msri_hashent *hep;
33420c794b3Sgavinm 
33520c794b3Sgavinm 	mutex_enter(&hbp->msrib_lock);
33620c794b3Sgavinm 
33720c794b3Sgavinm 	for (hep = hbp->msrib_head; hep != NULL; hep = hep->msrie_next) {
338e4b86885SCheng Sean Ye 		if (CMI_MSRI_MATCH(hep, hdl, msr))
33920c794b3Sgavinm 			break;
34020c794b3Sgavinm 	}
34120c794b3Sgavinm 
34220c794b3Sgavinm 	if (hep != NULL) {
343e4b86885SCheng Sean Ye 		hep->msrie_msrval = val;
34420c794b3Sgavinm 	} else {
34520c794b3Sgavinm 		hep = kmem_alloc(sizeof (*hep), KM_SLEEP);
34620c794b3Sgavinm 		hep->msrie_hdl = hdl;
347e4b86885SCheng Sean Ye 		hep->msrie_msrnum = msr;
348e4b86885SCheng Sean Ye 		hep->msrie_msrval = val;
34920c794b3Sgavinm 
35020c794b3Sgavinm 		if (hbp->msrib_head != NULL)
35120c794b3Sgavinm 			hbp->msrib_head->msrie_prev = hep;
35220c794b3Sgavinm 		hep->msrie_next = hbp->msrib_head;
35320c794b3Sgavinm 		hep->msrie_prev = NULL;
35420c794b3Sgavinm 		hbp->msrib_head = hep;
35520c794b3Sgavinm 	}
35620c794b3Sgavinm 
35720c794b3Sgavinm 	mutex_exit(&hbp->msrib_lock);
35820c794b3Sgavinm }
35920c794b3Sgavinm 
36020c794b3Sgavinm /*
36120c794b3Sgavinm  * Look for a match for the given hanlde and msr.  Return 1 with valp
36220c794b3Sgavinm  * filled if a match is found, otherwise return 0 with valp untouched.
36320c794b3Sgavinm  */
36420c794b3Sgavinm static int
msri_lookup(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t * valp)36520c794b3Sgavinm msri_lookup(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t *valp)
36620c794b3Sgavinm {
36720c794b3Sgavinm 	int idx = CMI_MSRI_HASHIDX(hdl, msr);
36820c794b3Sgavinm 	struct cmi_msri_bkt *hbp = &msrihash[idx];
36920c794b3Sgavinm 	struct cmi_msri_hashent *hep;
37020c794b3Sgavinm 
37120c794b3Sgavinm 	/*
37220c794b3Sgavinm 	 * This function is called during #MC trap handling, so we should
37320c794b3Sgavinm 	 * consider the possibility that the hash mutex is held by the
37420c794b3Sgavinm 	 * interrupted thread.  This should not happen because interposition
37520c794b3Sgavinm 	 * is an artificial injection mechanism and the #MC is requested
37620c794b3Sgavinm 	 * after adding entries, but just in case of a real #MC at an
37720c794b3Sgavinm 	 * unlucky moment we'll use mutex_tryenter here.
37820c794b3Sgavinm 	 */
37920c794b3Sgavinm 	if (!mutex_tryenter(&hbp->msrib_lock))
38020c794b3Sgavinm 		return (0);
38120c794b3Sgavinm 
38220c794b3Sgavinm 	for (hep = hbp->msrib_head; hep != NULL; hep = hep->msrie_next) {
38320c794b3Sgavinm 		if (CMI_MSRI_MATCH(hep, hdl, msr)) {
38420c794b3Sgavinm 			*valp = hep->msrie_msrval;
38520c794b3Sgavinm 			break;
38620c794b3Sgavinm 		}
38720c794b3Sgavinm 	}
38820c794b3Sgavinm 
38920c794b3Sgavinm 	mutex_exit(&hbp->msrib_lock);
39020c794b3Sgavinm 
39120c794b3Sgavinm 	return (hep != NULL);
39220c794b3Sgavinm }
39320c794b3Sgavinm 
39420c794b3Sgavinm /*
39520c794b3Sgavinm  * Remove any interposed value that matches.
39620c794b3Sgavinm  */
39720c794b3Sgavinm static void
msri_rment(cmi_hdl_impl_t * hdl,uint_t msr)39820c794b3Sgavinm msri_rment(cmi_hdl_impl_t *hdl, uint_t msr)
39920c794b3Sgavinm {
40020c794b3Sgavinm 
40120c794b3Sgavinm 	int idx = CMI_MSRI_HASHIDX(hdl, msr);
40220c794b3Sgavinm 	struct cmi_msri_bkt *hbp = &msrihash[idx];
40320c794b3Sgavinm 	struct cmi_msri_hashent *hep;
40420c794b3Sgavinm 
40520c794b3Sgavinm 	if (!mutex_tryenter(&hbp->msrib_lock))
40620c794b3Sgavinm 		return;
40720c794b3Sgavinm 
40820c794b3Sgavinm 	for (hep = hbp->msrib_head; hep != NULL; hep = hep->msrie_next) {
40920c794b3Sgavinm 		if (CMI_MSRI_MATCH(hep, hdl, msr)) {
41020c794b3Sgavinm 			if (hep->msrie_prev != NULL)
41120c794b3Sgavinm 				hep->msrie_prev->msrie_next = hep->msrie_next;
41220c794b3Sgavinm 
41320c794b3Sgavinm 			if (hep->msrie_next != NULL)
41420c794b3Sgavinm 				hep->msrie_next->msrie_prev = hep->msrie_prev;
41520c794b3Sgavinm 
41620c794b3Sgavinm 			if (hbp->msrib_head == hep)
41720c794b3Sgavinm 				hbp->msrib_head = hep->msrie_next;
41820c794b3Sgavinm 
41920c794b3Sgavinm 			kmem_free(hep, sizeof (*hep));
42020c794b3Sgavinm 			break;
42120c794b3Sgavinm 		}
42220c794b3Sgavinm 	}
42320c794b3Sgavinm 
42420c794b3Sgavinm 	mutex_exit(&hbp->msrib_lock);
42520c794b3Sgavinm }
42620c794b3Sgavinm 
42720c794b3Sgavinm /*
42820c794b3Sgavinm  *	 =======================================================
42920c794b3Sgavinm  *	|	PCI Config Space Interposition			|
43020c794b3Sgavinm  *	|	------------------------------			|
43120c794b3Sgavinm  *	|							|
43220c794b3Sgavinm  *	 -------------------------------------------------------
43320c794b3Sgavinm  */
43420c794b3Sgavinm 
43520c794b3Sgavinm /*
43620c794b3Sgavinm  * Hash for interposed PCI config space values.  We lookup on bus/dev/fun/offset
43720c794b3Sgavinm  * and then record whether the value stashed was made with a byte, word or
43820c794b3Sgavinm  * doubleword access;  we will only return a hit for an access of the
43920c794b3Sgavinm  * same size.  If you access say a 32-bit register using byte accesses
44020c794b3Sgavinm  * and then attempt to read the full 32-bit value back you will not obtain
44120c794b3Sgavinm  * any sort of merged result - you get a lookup miss.
44220c794b3Sgavinm  */
44320c794b3Sgavinm 
44420c794b3Sgavinm #define	CMI_PCII_HASHSZ		16
44520c794b3Sgavinm #define	CMI_PCII_HASHIDX(b, d, f, o) \
44620c794b3Sgavinm 	(((b) + (d) + (f) + (o)) % (CMI_PCII_HASHSZ - 1))
44720c794b3Sgavinm 
44820c794b3Sgavinm struct cmi_pcii_bkt {
44920c794b3Sgavinm 	kmutex_t pciib_lock;
45020c794b3Sgavinm 	struct cmi_pcii_hashent *pciib_head;
45120c794b3Sgavinm };
45220c794b3Sgavinm 
45320c794b3Sgavinm struct cmi_pcii_hashent {
45420c794b3Sgavinm 	struct cmi_pcii_hashent *pcii_next;
45520c794b3Sgavinm 	struct cmi_pcii_hashent *pcii_prev;
45620c794b3Sgavinm 	int pcii_bus;
45720c794b3Sgavinm 	int pcii_dev;
45820c794b3Sgavinm 	int pcii_func;
45920c794b3Sgavinm 	int pcii_reg;
46020c794b3Sgavinm 	int pcii_asize;
46120c794b3Sgavinm 	uint32_t pcii_val;
46220c794b3Sgavinm };
46320c794b3Sgavinm 
46420c794b3Sgavinm #define	CMI_PCII_MATCH(ent, b, d, f, r, asz) \
46520c794b3Sgavinm 	((ent)->pcii_bus == (b) && (ent)->pcii_dev == (d) && \
46620c794b3Sgavinm 	(ent)->pcii_func == (f) && (ent)->pcii_reg == (r) && \
46720c794b3Sgavinm 	(ent)->pcii_asize == (asz))
46820c794b3Sgavinm 
46920c794b3Sgavinm static struct cmi_pcii_bkt pciihash[CMI_PCII_HASHSZ];
47020c794b3Sgavinm 
47120c794b3Sgavinm 
47220c794b3Sgavinm /*
47320c794b3Sgavinm  * Add a new entry to the PCI interpose hash, overwriting any existing
47420c794b3Sgavinm  * entry that is found.
47520c794b3Sgavinm  */
47620c794b3Sgavinm static void
pcii_addent(int bus,int dev,int func,int reg,uint32_t val,int asz)47720c794b3Sgavinm pcii_addent(int bus, int dev, int func, int reg, uint32_t val, int asz)
47820c794b3Sgavinm {
47920c794b3Sgavinm 	int idx = CMI_PCII_HASHIDX(bus, dev, func, reg);
48020c794b3Sgavinm 	struct cmi_pcii_bkt *hbp = &pciihash[idx];
48120c794b3Sgavinm 	struct cmi_pcii_hashent *hep;
48220c794b3Sgavinm 
483e4b86885SCheng Sean Ye 	cmi_hdl_inj_begin(NULL);
484e4b86885SCheng Sean Ye 
48520c794b3Sgavinm 	mutex_enter(&hbp->pciib_lock);
48620c794b3Sgavinm 
48720c794b3Sgavinm 	for (hep = hbp->pciib_head; hep != NULL; hep = hep->pcii_next) {
48820c794b3Sgavinm 		if (CMI_PCII_MATCH(hep, bus, dev, func, reg, asz))
48920c794b3Sgavinm 			break;
49020c794b3Sgavinm 	}
49120c794b3Sgavinm 
49220c794b3Sgavinm 	if (hep != NULL) {
49320c794b3Sgavinm 		hep->pcii_val = val;
49420c794b3Sgavinm 	} else {
49520c794b3Sgavinm 		hep = kmem_alloc(sizeof (*hep), KM_SLEEP);
49620c794b3Sgavinm 		hep->pcii_bus = bus;
49720c794b3Sgavinm 		hep->pcii_dev = dev;
49820c794b3Sgavinm 		hep->pcii_func = func;
49920c794b3Sgavinm 		hep->pcii_reg = reg;
50020c794b3Sgavinm 		hep->pcii_asize = asz;
50120c794b3Sgavinm 		hep->pcii_val = val;
50220c794b3Sgavinm 
50320c794b3Sgavinm 		if (hbp->pciib_head != NULL)
50420c794b3Sgavinm 			hbp->pciib_head->pcii_prev = hep;
50520c794b3Sgavinm 		hep->pcii_next = hbp->pciib_head;
50620c794b3Sgavinm 		hep->pcii_prev = NULL;
50720c794b3Sgavinm 		hbp->pciib_head = hep;
50820c794b3Sgavinm 	}
50920c794b3Sgavinm 
51020c794b3Sgavinm 	mutex_exit(&hbp->pciib_lock);
511e4b86885SCheng Sean Ye 
512e4b86885SCheng Sean Ye 	cmi_hdl_inj_end(NULL);
51320c794b3Sgavinm }
51420c794b3Sgavinm 
51520c794b3Sgavinm /*
51620c794b3Sgavinm  * Look for a match for the given bus/dev/func/reg; return 1 with valp
51720c794b3Sgavinm  * filled if a match is found, otherwise return 0 with valp untouched.
51820c794b3Sgavinm  */
51920c794b3Sgavinm static int
pcii_lookup(int bus,int dev,int func,int reg,int asz,uint32_t * valp)52020c794b3Sgavinm pcii_lookup(int bus, int dev, int func, int reg, int asz, uint32_t *valp)
52120c794b3Sgavinm {
52220c794b3Sgavinm 	int idx = CMI_PCII_HASHIDX(bus, dev, func, reg);
52320c794b3Sgavinm 	struct cmi_pcii_bkt *hbp = &pciihash[idx];
52420c794b3Sgavinm 	struct cmi_pcii_hashent *hep;
52520c794b3Sgavinm 
52620c794b3Sgavinm 	if (!mutex_tryenter(&hbp->pciib_lock))
52720c794b3Sgavinm 		return (0);
52820c794b3Sgavinm 
52920c794b3Sgavinm 	for (hep = hbp->pciib_head; hep != NULL; hep = hep->pcii_next) {
53020c794b3Sgavinm 		if (CMI_PCII_MATCH(hep, bus, dev, func, reg, asz)) {
53120c794b3Sgavinm 			*valp = hep->pcii_val;
53220c794b3Sgavinm 			break;
53320c794b3Sgavinm 		}
53420c794b3Sgavinm 	}
53520c794b3Sgavinm 
53620c794b3Sgavinm 	mutex_exit(&hbp->pciib_lock);
53720c794b3Sgavinm 
53820c794b3Sgavinm 	return (hep != NULL);
53920c794b3Sgavinm }
54020c794b3Sgavinm 
54120c794b3Sgavinm static void
pcii_rment(int bus,int dev,int func,int reg,int asz)54220c794b3Sgavinm pcii_rment(int bus, int dev, int func, int reg, int asz)
54320c794b3Sgavinm {
54420c794b3Sgavinm 	int idx = CMI_PCII_HASHIDX(bus, dev, func, reg);
54520c794b3Sgavinm 	struct cmi_pcii_bkt *hbp = &pciihash[idx];
54620c794b3Sgavinm 	struct cmi_pcii_hashent *hep;
54720c794b3Sgavinm 
54820c794b3Sgavinm 	mutex_enter(&hbp->pciib_lock);
54920c794b3Sgavinm 
55020c794b3Sgavinm 	for (hep = hbp->pciib_head; hep != NULL; hep = hep->pcii_next) {
55120c794b3Sgavinm 		if (CMI_PCII_MATCH(hep, bus, dev, func, reg, asz)) {
55220c794b3Sgavinm 			if (hep->pcii_prev != NULL)
55320c794b3Sgavinm 				hep->pcii_prev->pcii_next = hep->pcii_next;
55420c794b3Sgavinm 
55520c794b3Sgavinm 			if (hep->pcii_next != NULL)
55620c794b3Sgavinm 				hep->pcii_next->pcii_prev = hep->pcii_prev;
55720c794b3Sgavinm 
55820c794b3Sgavinm 			if (hbp->pciib_head == hep)
55920c794b3Sgavinm 				hbp->pciib_head = hep->pcii_next;
56020c794b3Sgavinm 
56120c794b3Sgavinm 			kmem_free(hep, sizeof (*hep));
56220c794b3Sgavinm 			break;
56320c794b3Sgavinm 		}
56420c794b3Sgavinm 	}
56520c794b3Sgavinm 
56620c794b3Sgavinm 	mutex_exit(&hbp->pciib_lock);
56720c794b3Sgavinm }
56820c794b3Sgavinm 
569e4b86885SCheng Sean Ye #ifndef __xpv
570e4b86885SCheng Sean Ye 
57120c794b3Sgavinm /*
57220c794b3Sgavinm  *	 =======================================================
57320c794b3Sgavinm  *	|	Native methods					|
57420c794b3Sgavinm  *	|	--------------					|
57520c794b3Sgavinm  *	|							|
57620c794b3Sgavinm  *	| These are used when we are running native on bare-	|
57720c794b3Sgavinm  *	| metal, or simply don't know any better.		|
57820c794b3Sgavinm  *	---------------------------------------------------------
57920c794b3Sgavinm  */
58020c794b3Sgavinm 
581e4b86885SCheng Sean Ye #define	HDLPRIV(hdl)	((cpu_t *)(hdl)->cmih_hdlpriv)
582e4b86885SCheng Sean Ye 
58320c794b3Sgavinm static uint_t
ntv_vendor(cmi_hdl_impl_t * hdl)58420c794b3Sgavinm ntv_vendor(cmi_hdl_impl_t *hdl)
58520c794b3Sgavinm {
586e4b86885SCheng Sean Ye 	return (cpuid_getvendor(HDLPRIV(hdl)));
58720c794b3Sgavinm }
58820c794b3Sgavinm 
58920c794b3Sgavinm static const char *
ntv_vendorstr(cmi_hdl_impl_t * hdl)59020c794b3Sgavinm ntv_vendorstr(cmi_hdl_impl_t *hdl)
59120c794b3Sgavinm {
592e4b86885SCheng Sean Ye 	return (cpuid_getvendorstr(HDLPRIV(hdl)));
59320c794b3Sgavinm }
59420c794b3Sgavinm 
59520c794b3Sgavinm static uint_t
ntv_family(cmi_hdl_impl_t * hdl)59620c794b3Sgavinm ntv_family(cmi_hdl_impl_t *hdl)
59720c794b3Sgavinm {
598e4b86885SCheng Sean Ye 	return (cpuid_getfamily(HDLPRIV(hdl)));
59920c794b3Sgavinm }
60020c794b3Sgavinm 
60120c794b3Sgavinm static uint_t
ntv_model(cmi_hdl_impl_t * hdl)60220c794b3Sgavinm ntv_model(cmi_hdl_impl_t *hdl)
60320c794b3Sgavinm {
604e4b86885SCheng Sean Ye 	return (cpuid_getmodel(HDLPRIV(hdl)));
60520c794b3Sgavinm }
60620c794b3Sgavinm 
60720c794b3Sgavinm static uint_t
ntv_stepping(cmi_hdl_impl_t * hdl)60820c794b3Sgavinm ntv_stepping(cmi_hdl_impl_t *hdl)
60920c794b3Sgavinm {
610e4b86885SCheng Sean Ye 	return (cpuid_getstep(HDLPRIV(hdl)));
61120c794b3Sgavinm }
61220c794b3Sgavinm 
61320c794b3Sgavinm static uint_t
ntv_chipid(cmi_hdl_impl_t * hdl)61420c794b3Sgavinm ntv_chipid(cmi_hdl_impl_t *hdl)
61520c794b3Sgavinm {
61620c794b3Sgavinm 	return (hdl->cmih_chipid);
61720c794b3Sgavinm 
61820c794b3Sgavinm }
61920c794b3Sgavinm 
6208031591dSSrihari Venkatesan static uint_t
ntv_procnodeid(cmi_hdl_impl_t * hdl)6218031591dSSrihari Venkatesan ntv_procnodeid(cmi_hdl_impl_t *hdl)
6228031591dSSrihari Venkatesan {
6238031591dSSrihari Venkatesan 	return (hdl->cmih_procnodeid);
6248031591dSSrihari Venkatesan }
6258031591dSSrihari Venkatesan 
6268031591dSSrihari Venkatesan static uint_t
ntv_procnodes_per_pkg(cmi_hdl_impl_t * hdl)6278031591dSSrihari Venkatesan ntv_procnodes_per_pkg(cmi_hdl_impl_t *hdl)
6288031591dSSrihari Venkatesan {
6298031591dSSrihari Venkatesan 	return (hdl->cmih_procnodes_per_pkg);
6308031591dSSrihari Venkatesan }
6318031591dSSrihari Venkatesan 
63220c794b3Sgavinm static uint_t
ntv_coreid(cmi_hdl_impl_t * hdl)63320c794b3Sgavinm ntv_coreid(cmi_hdl_impl_t *hdl)
63420c794b3Sgavinm {
63520c794b3Sgavinm 	return (hdl->cmih_coreid);
63620c794b3Sgavinm }
63720c794b3Sgavinm 
63820c794b3Sgavinm static uint_t
ntv_strandid(cmi_hdl_impl_t * hdl)63920c794b3Sgavinm ntv_strandid(cmi_hdl_impl_t *hdl)
64020c794b3Sgavinm {
64120c794b3Sgavinm 	return (hdl->cmih_strandid);
64220c794b3Sgavinm }
64320c794b3Sgavinm 
644074bb90dSTom Pothier static uint_t
ntv_strand_apicid(cmi_hdl_impl_t * hdl)645074bb90dSTom Pothier ntv_strand_apicid(cmi_hdl_impl_t *hdl)
646074bb90dSTom Pothier {
647074bb90dSTom Pothier 	return (cpuid_get_apicid(HDLPRIV(hdl)));
648074bb90dSTom Pothier }
649074bb90dSTom Pothier 
650074bb90dSTom Pothier static uint16_t
ntv_smbiosid(cmi_hdl_impl_t * hdl)651074bb90dSTom Pothier ntv_smbiosid(cmi_hdl_impl_t *hdl)
652074bb90dSTom Pothier {
653074bb90dSTom Pothier 	return (hdl->cmih_smbiosid);
654074bb90dSTom Pothier }
655074bb90dSTom Pothier 
656074bb90dSTom Pothier static uint_t
ntv_smb_chipid(cmi_hdl_impl_t * hdl)657074bb90dSTom Pothier ntv_smb_chipid(cmi_hdl_impl_t *hdl)
658074bb90dSTom Pothier {
659074bb90dSTom Pothier 	return (hdl->cmih_smb_chipid);
660074bb90dSTom Pothier }
661074bb90dSTom Pothier 
662074bb90dSTom Pothier static nvlist_t *
ntv_smb_bboard(cmi_hdl_impl_t * hdl)663074bb90dSTom Pothier ntv_smb_bboard(cmi_hdl_impl_t *hdl)
664074bb90dSTom Pothier {
665074bb90dSTom Pothier 	return (hdl->cmih_smb_bboard);
666074bb90dSTom Pothier }
667074bb90dSTom Pothier 
66822e4c3acSKeith M Wesolowski static x86_chiprev_t
ntv_chiprev(cmi_hdl_impl_t * hdl)66920c794b3Sgavinm ntv_chiprev(cmi_hdl_impl_t *hdl)
67020c794b3Sgavinm {
671e4b86885SCheng Sean Ye 	return (cpuid_getchiprev(HDLPRIV(hdl)));
67220c794b3Sgavinm }
67320c794b3Sgavinm 
67420c794b3Sgavinm static const char *
ntv_chiprevstr(cmi_hdl_impl_t * hdl)67520c794b3Sgavinm ntv_chiprevstr(cmi_hdl_impl_t *hdl)
67620c794b3Sgavinm {
677e4b86885SCheng Sean Ye 	return (cpuid_getchiprevstr(HDLPRIV(hdl)));
67820c794b3Sgavinm }
67920c794b3Sgavinm 
68020c794b3Sgavinm static uint32_t
ntv_getsockettype(cmi_hdl_impl_t * hdl)68120c794b3Sgavinm ntv_getsockettype(cmi_hdl_impl_t *hdl)
68220c794b3Sgavinm {
683e4b86885SCheng Sean Ye 	return (cpuid_getsockettype(HDLPRIV(hdl)));
684e4b86885SCheng Sean Ye }
685e4b86885SCheng Sean Ye 
68689e921d5SKuriakose Kuruvilla static const char *
ntv_getsocketstr(cmi_hdl_impl_t * hdl)68789e921d5SKuriakose Kuruvilla ntv_getsocketstr(cmi_hdl_impl_t *hdl)
68889e921d5SKuriakose Kuruvilla {
68989e921d5SKuriakose Kuruvilla 	return (cpuid_getsocketstr(HDLPRIV(hdl)));
69089e921d5SKuriakose Kuruvilla }
69189e921d5SKuriakose Kuruvilla 
6922a613b59SRobert Mustacchi static uint_t
ntv_chipsig(cmi_hdl_impl_t * hdl)6932a613b59SRobert Mustacchi ntv_chipsig(cmi_hdl_impl_t *hdl)
6942a613b59SRobert Mustacchi {
6952a613b59SRobert Mustacchi 	return (cpuid_getsig(HDLPRIV(hdl)));
6962a613b59SRobert Mustacchi }
6972a613b59SRobert Mustacchi 
698*dd23d762SRobert Mustacchi static cmi_errno_t
cmi_cpuid_cache_to_cmi(int err)699*dd23d762SRobert Mustacchi cmi_cpuid_cache_to_cmi(int err)
700*dd23d762SRobert Mustacchi {
701*dd23d762SRobert Mustacchi 	switch (err) {
702*dd23d762SRobert Mustacchi 	case 0:
703*dd23d762SRobert Mustacchi 		return (CMI_SUCCESS);
704*dd23d762SRobert Mustacchi 	case ENOTSUP:
705*dd23d762SRobert Mustacchi 		return (CMIERR_C_NODATA);
706*dd23d762SRobert Mustacchi 	case EINVAL:
707*dd23d762SRobert Mustacchi 		return (CMIERR_C_BADCACHENO);
708*dd23d762SRobert Mustacchi 	default:
709*dd23d762SRobert Mustacchi 		return (CMIERR_UNKNOWN);
710*dd23d762SRobert Mustacchi 	}
711*dd23d762SRobert Mustacchi }
712*dd23d762SRobert Mustacchi 
713*dd23d762SRobert Mustacchi static cmi_errno_t
ntv_ncache(cmi_hdl_impl_t * hdl,uint32_t * ncache)714*dd23d762SRobert Mustacchi ntv_ncache(cmi_hdl_impl_t *hdl, uint32_t *ncache)
715*dd23d762SRobert Mustacchi {
716*dd23d762SRobert Mustacchi 	int ret = cpuid_getncaches(HDLPRIV(hdl), ncache);
717*dd23d762SRobert Mustacchi 	return (cmi_cpuid_cache_to_cmi(ret));
718*dd23d762SRobert Mustacchi }
719*dd23d762SRobert Mustacchi 
720*dd23d762SRobert Mustacchi static cmi_errno_t
ntv_cache(cmi_hdl_impl_t * hdl,uint32_t cno,x86_cache_t * cachep)721*dd23d762SRobert Mustacchi ntv_cache(cmi_hdl_impl_t *hdl, uint32_t cno, x86_cache_t *cachep)
722*dd23d762SRobert Mustacchi {
723*dd23d762SRobert Mustacchi 	int ret = cpuid_getcache(HDLPRIV(hdl), cno, cachep);
724*dd23d762SRobert Mustacchi 	return (cmi_cpuid_cache_to_cmi(ret));
725*dd23d762SRobert Mustacchi }
726*dd23d762SRobert Mustacchi 
727e4b86885SCheng Sean Ye static id_t
ntv_logical_id(cmi_hdl_impl_t * hdl)728e4b86885SCheng Sean Ye ntv_logical_id(cmi_hdl_impl_t *hdl)
729e4b86885SCheng Sean Ye {
730e4b86885SCheng Sean Ye 	return (HDLPRIV(hdl)->cpu_id);
73120c794b3Sgavinm }
73220c794b3Sgavinm 
73320c794b3Sgavinm /*ARGSUSED*/
73420c794b3Sgavinm static int
ntv_getcr4_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)73520c794b3Sgavinm ntv_getcr4_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
73620c794b3Sgavinm {
73720c794b3Sgavinm 	ulong_t *dest = (ulong_t *)arg1;
73820c794b3Sgavinm 	cmi_errno_t *rcp = (cmi_errno_t *)arg3;
73920c794b3Sgavinm 
74020c794b3Sgavinm 	*dest = getcr4();
74120c794b3Sgavinm 	*rcp = CMI_SUCCESS;
74220c794b3Sgavinm 
74320c794b3Sgavinm 	return (0);
74420c794b3Sgavinm }
74520c794b3Sgavinm 
74620c794b3Sgavinm static ulong_t
ntv_getcr4(cmi_hdl_impl_t * hdl)74720c794b3Sgavinm ntv_getcr4(cmi_hdl_impl_t *hdl)
74820c794b3Sgavinm {
749e4b86885SCheng Sean Ye 	cpu_t *cp = HDLPRIV(hdl);
75020c794b3Sgavinm 	ulong_t val;
75120c794b3Sgavinm 
7524da99751SToomas Soome 	(void) call_func_ntv(cp->cpu_id, ntv_getcr4_xc, (xc_arg_t)&val, 0);
75320c794b3Sgavinm 
75420c794b3Sgavinm 	return (val);
75520c794b3Sgavinm }
75620c794b3Sgavinm 
75720c794b3Sgavinm /*ARGSUSED*/
75820c794b3Sgavinm static int
ntv_setcr4_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)75920c794b3Sgavinm ntv_setcr4_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
76020c794b3Sgavinm {
76120c794b3Sgavinm 	ulong_t val = (ulong_t)arg1;
76220c794b3Sgavinm 	cmi_errno_t *rcp = (cmi_errno_t *)arg3;
76320c794b3Sgavinm 
76420c794b3Sgavinm 	setcr4(val);
76520c794b3Sgavinm 	*rcp = CMI_SUCCESS;
76620c794b3Sgavinm 
76720c794b3Sgavinm 	return (0);
76820c794b3Sgavinm }
76920c794b3Sgavinm 
77020c794b3Sgavinm static void
ntv_setcr4(cmi_hdl_impl_t * hdl,ulong_t val)77120c794b3Sgavinm ntv_setcr4(cmi_hdl_impl_t *hdl, ulong_t val)
77220c794b3Sgavinm {
773e4b86885SCheng Sean Ye 	cpu_t *cp = HDLPRIV(hdl);
77420c794b3Sgavinm 
7754da99751SToomas Soome 	(void) call_func_ntv(cp->cpu_id, ntv_setcr4_xc, (xc_arg_t)val, 0);
77620c794b3Sgavinm }
77720c794b3Sgavinm 
778a4e4e13fSgavinm volatile uint32_t cmi_trapped_rdmsr;
779a4e4e13fSgavinm 
78020c794b3Sgavinm /*ARGSUSED*/
78120c794b3Sgavinm static int
ntv_rdmsr_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)78220c794b3Sgavinm ntv_rdmsr_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
78320c794b3Sgavinm {
78420c794b3Sgavinm 	uint_t msr = (uint_t)arg1;
78520c794b3Sgavinm 	uint64_t *valp = (uint64_t *)arg2;
78620c794b3Sgavinm 	cmi_errno_t *rcp = (cmi_errno_t *)arg3;
78720c794b3Sgavinm 
78820c794b3Sgavinm 	on_trap_data_t otd;
78920c794b3Sgavinm 
79020c794b3Sgavinm 	if (on_trap(&otd, OT_DATA_ACCESS) == 0) {
79120c794b3Sgavinm 		if (checked_rdmsr(msr, valp) == 0)
79220c794b3Sgavinm 			*rcp = CMI_SUCCESS;
79320c794b3Sgavinm 		else
79420c794b3Sgavinm 			*rcp = CMIERR_NOTSUP;
79520c794b3Sgavinm 	} else {
79620c794b3Sgavinm 		*rcp = CMIERR_MSRGPF;
797a4e4e13fSgavinm 		atomic_inc_32(&cmi_trapped_rdmsr);
79820c794b3Sgavinm 	}
79920c794b3Sgavinm 	no_trap();
80020c794b3Sgavinm 
80120c794b3Sgavinm 	return (0);
80220c794b3Sgavinm }
80320c794b3Sgavinm 
80420c794b3Sgavinm static cmi_errno_t
ntv_rdmsr(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t * valp)80520c794b3Sgavinm ntv_rdmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t *valp)
80620c794b3Sgavinm {
807e4b86885SCheng Sean Ye 	cpu_t *cp = HDLPRIV(hdl);
808e4b86885SCheng Sean Ye 
809e4b86885SCheng Sean Ye 	if (!(hdl->cmih_msrsrc & CMI_MSR_FLAG_RD_HWOK))
810e4b86885SCheng Sean Ye 		return (CMIERR_INTERPOSE);
81120c794b3Sgavinm 
81220c794b3Sgavinm 	return (call_func_ntv(cp->cpu_id, ntv_rdmsr_xc,
81320c794b3Sgavinm 	    (xc_arg_t)msr, (xc_arg_t)valp));
81420c794b3Sgavinm }
81520c794b3Sgavinm 
816a4e4e13fSgavinm volatile uint32_t cmi_trapped_wrmsr;
817a4e4e13fSgavinm 
81820c794b3Sgavinm /*ARGSUSED*/
81920c794b3Sgavinm static int
ntv_wrmsr_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)82020c794b3Sgavinm ntv_wrmsr_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
82120c794b3Sgavinm {
82220c794b3Sgavinm 	uint_t msr = (uint_t)arg1;
82320c794b3Sgavinm 	uint64_t val = *((uint64_t *)arg2);
82420c794b3Sgavinm 	cmi_errno_t *rcp = (cmi_errno_t *)arg3;
82520c794b3Sgavinm 	on_trap_data_t otd;
82620c794b3Sgavinm 
82720c794b3Sgavinm 	if (on_trap(&otd, OT_DATA_ACCESS) == 0) {
82820c794b3Sgavinm 		if (checked_wrmsr(msr, val) == 0)
82920c794b3Sgavinm 			*rcp = CMI_SUCCESS;
83020c794b3Sgavinm 		else
83120c794b3Sgavinm 			*rcp = CMIERR_NOTSUP;
83220c794b3Sgavinm 	} else {
83320c794b3Sgavinm 		*rcp = CMIERR_MSRGPF;
834a4e4e13fSgavinm 		atomic_inc_32(&cmi_trapped_wrmsr);
83520c794b3Sgavinm 	}
83620c794b3Sgavinm 	no_trap();
83720c794b3Sgavinm 
83820c794b3Sgavinm 	return (0);
83920c794b3Sgavinm 
84020c794b3Sgavinm }
84120c794b3Sgavinm 
84220c794b3Sgavinm static cmi_errno_t
ntv_wrmsr(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)84320c794b3Sgavinm ntv_wrmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
84420c794b3Sgavinm {
845e4b86885SCheng Sean Ye 	cpu_t *cp = HDLPRIV(hdl);
846e4b86885SCheng Sean Ye 
847e4b86885SCheng Sean Ye 	if (!(hdl->cmih_msrsrc & CMI_MSR_FLAG_WR_HWOK))
848e4b86885SCheng Sean Ye 		return (CMI_SUCCESS);
84920c794b3Sgavinm 
85020c794b3Sgavinm 	return (call_func_ntv(cp->cpu_id, ntv_wrmsr_xc,
85120c794b3Sgavinm 	    (xc_arg_t)msr, (xc_arg_t)&val));
85220c794b3Sgavinm }
85320c794b3Sgavinm 
854e4b86885SCheng Sean Ye static cmi_errno_t
ntv_msrinterpose(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)855e4b86885SCheng Sean Ye ntv_msrinterpose(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
856e4b86885SCheng Sean Ye {
857e4b86885SCheng Sean Ye 	msri_addent(hdl, msr, val);
858e4b86885SCheng Sean Ye 	return (CMI_SUCCESS);
859e4b86885SCheng Sean Ye }
860e4b86885SCheng Sean Ye 
86120c794b3Sgavinm /*ARGSUSED*/
86220c794b3Sgavinm static int
ntv_int_xc(xc_arg_t arg1,xc_arg_t arg2,xc_arg_t arg3)863e3d60c9bSAdrian Frost ntv_int_xc(xc_arg_t arg1, xc_arg_t arg2, xc_arg_t arg3)
86420c794b3Sgavinm {
86520c794b3Sgavinm 	cmi_errno_t *rcp = (cmi_errno_t *)arg3;
866e3d60c9bSAdrian Frost 	int int_no = (int)arg1;
86720c794b3Sgavinm 
868e3d60c9bSAdrian Frost 	if (int_no == T_MCE)
869e3d60c9bSAdrian Frost 		int18();
870e3d60c9bSAdrian Frost 	else
871e3d60c9bSAdrian Frost 		int_cmci();
87220c794b3Sgavinm 	*rcp = CMI_SUCCESS;
87320c794b3Sgavinm 
87420c794b3Sgavinm 	return (0);
87520c794b3Sgavinm }
87620c794b3Sgavinm 
87720c794b3Sgavinm static void
ntv_int(cmi_hdl_impl_t * hdl,int int_no)878e3d60c9bSAdrian Frost ntv_int(cmi_hdl_impl_t *hdl, int int_no)
87920c794b3Sgavinm {
880e4b86885SCheng Sean Ye 	cpu_t *cp = HDLPRIV(hdl);
88120c794b3Sgavinm 
8824da99751SToomas Soome 	(void) call_func_ntv(cp->cpu_id, ntv_int_xc, (xc_arg_t)int_no, 0);
88320c794b3Sgavinm }
88420c794b3Sgavinm 
885e4b86885SCheng Sean Ye static int
ntv_online(cmi_hdl_impl_t * hdl,int new_status,int * old_status)886e4b86885SCheng Sean Ye ntv_online(cmi_hdl_impl_t *hdl, int new_status, int *old_status)
887e4b86885SCheng Sean Ye {
888a3114836SGerry Liu 	int rc;
889e4b86885SCheng Sean Ye 	processorid_t cpuid = HDLPRIV(hdl)->cpu_id;
890e4b86885SCheng Sean Ye 
891a3114836SGerry Liu 	while (mutex_tryenter(&cpu_lock) == 0) {
892a3114836SGerry Liu 		if (hdl->cmih_flags & CMIH_F_DEAD)
893a3114836SGerry Liu 			return (EBUSY);
894a3114836SGerry Liu 		delay(1);
895a3114836SGerry Liu 	}
896a3114836SGerry Liu 	rc = p_online_internal_locked(cpuid, new_status, old_status);
897a3114836SGerry Liu 	mutex_exit(&cpu_lock);
898a3114836SGerry Liu 
899a3114836SGerry Liu 	return (rc);
900e4b86885SCheng Sean Ye }
901e4b86885SCheng Sean Ye 
902e4b86885SCheng Sean Ye #else	/* __xpv */
903e4b86885SCheng Sean Ye 
90420c794b3Sgavinm /*
905e4b86885SCheng Sean Ye  *	 =======================================================
906e4b86885SCheng Sean Ye  *	|	xVM dom0 methods				|
907e4b86885SCheng Sean Ye  *	|	----------------				|
908e4b86885SCheng Sean Ye  *	|							|
909e4b86885SCheng Sean Ye  *	| These are used when we are running as dom0 in		|
910e4b86885SCheng Sean Ye  *	| a Solaris xVM context.				|
911e4b86885SCheng Sean Ye  *	---------------------------------------------------------
91220c794b3Sgavinm  */
91320c794b3Sgavinm 
914e4b86885SCheng Sean Ye #define	HDLPRIV(hdl)	((xen_mc_lcpu_cookie_t)(hdl)->cmih_hdlpriv)
915e4b86885SCheng Sean Ye 
916e4b86885SCheng Sean Ye extern uint_t _cpuid_vendorstr_to_vendorcode(char *);
917e4b86885SCheng Sean Ye 
918e4b86885SCheng Sean Ye 
919e4b86885SCheng Sean Ye static uint_t
xpv_vendor(cmi_hdl_impl_t * hdl)920e4b86885SCheng Sean Ye xpv_vendor(cmi_hdl_impl_t *hdl)
921e4b86885SCheng Sean Ye {
922e4b86885SCheng Sean Ye 	return (_cpuid_vendorstr_to_vendorcode((char *)xen_physcpu_vendorstr(
923e4b86885SCheng Sean Ye 	    HDLPRIV(hdl))));
924e4b86885SCheng Sean Ye }
925e4b86885SCheng Sean Ye 
926e4b86885SCheng Sean Ye static const char *
xpv_vendorstr(cmi_hdl_impl_t * hdl)927e4b86885SCheng Sean Ye xpv_vendorstr(cmi_hdl_impl_t *hdl)
928e4b86885SCheng Sean Ye {
929e4b86885SCheng Sean Ye 	return (xen_physcpu_vendorstr(HDLPRIV(hdl)));
930e4b86885SCheng Sean Ye }
931e4b86885SCheng Sean Ye 
932e4b86885SCheng Sean Ye static uint_t
xpv_family(cmi_hdl_impl_t * hdl)933e4b86885SCheng Sean Ye xpv_family(cmi_hdl_impl_t *hdl)
934e4b86885SCheng Sean Ye {
935e4b86885SCheng Sean Ye 	return (xen_physcpu_family(HDLPRIV(hdl)));
936e4b86885SCheng Sean Ye }
937e4b86885SCheng Sean Ye 
938e4b86885SCheng Sean Ye static uint_t
xpv_model(cmi_hdl_impl_t * hdl)939e4b86885SCheng Sean Ye xpv_model(cmi_hdl_impl_t *hdl)
940e4b86885SCheng Sean Ye {
941e4b86885SCheng Sean Ye 	return (xen_physcpu_model(HDLPRIV(hdl)));
942e4b86885SCheng Sean Ye }
943e4b86885SCheng Sean Ye 
944e4b86885SCheng Sean Ye static uint_t
xpv_stepping(cmi_hdl_impl_t * hdl)945e4b86885SCheng Sean Ye xpv_stepping(cmi_hdl_impl_t *hdl)
946e4b86885SCheng Sean Ye {
947e4b86885SCheng Sean Ye 	return (xen_physcpu_stepping(HDLPRIV(hdl)));
948e4b86885SCheng Sean Ye }
949e4b86885SCheng Sean Ye 
950e4b86885SCheng Sean Ye static uint_t
xpv_chipid(cmi_hdl_impl_t * hdl)951e4b86885SCheng Sean Ye xpv_chipid(cmi_hdl_impl_t *hdl)
952e4b86885SCheng Sean Ye {
953e4b86885SCheng Sean Ye 	return (hdl->cmih_chipid);
954e4b86885SCheng Sean Ye }
955e4b86885SCheng Sean Ye 
9568031591dSSrihari Venkatesan static uint_t
xpv_procnodeid(cmi_hdl_impl_t * hdl)9578031591dSSrihari Venkatesan xpv_procnodeid(cmi_hdl_impl_t *hdl)
9588031591dSSrihari Venkatesan {
9598031591dSSrihari Venkatesan 	return (hdl->cmih_procnodeid);
9608031591dSSrihari Venkatesan }
9618031591dSSrihari Venkatesan 
9628031591dSSrihari Venkatesan static uint_t
xpv_procnodes_per_pkg(cmi_hdl_impl_t * hdl)9638031591dSSrihari Venkatesan xpv_procnodes_per_pkg(cmi_hdl_impl_t *hdl)
9648031591dSSrihari Venkatesan {
9658031591dSSrihari Venkatesan 	return (hdl->cmih_procnodes_per_pkg);
9668031591dSSrihari Venkatesan }
9678031591dSSrihari Venkatesan 
968e4b86885SCheng Sean Ye static uint_t
xpv_coreid(cmi_hdl_impl_t * hdl)969e4b86885SCheng Sean Ye xpv_coreid(cmi_hdl_impl_t *hdl)
970e4b86885SCheng Sean Ye {
971e4b86885SCheng Sean Ye 	return (hdl->cmih_coreid);
972e4b86885SCheng Sean Ye }
973e4b86885SCheng Sean Ye 
974e4b86885SCheng Sean Ye static uint_t
xpv_strandid(cmi_hdl_impl_t * hdl)975e4b86885SCheng Sean Ye xpv_strandid(cmi_hdl_impl_t *hdl)
976e4b86885SCheng Sean Ye {
977e4b86885SCheng Sean Ye 	return (hdl->cmih_strandid);
978e4b86885SCheng Sean Ye }
979e4b86885SCheng Sean Ye 
980074bb90dSTom Pothier static uint_t
xpv_strand_apicid(cmi_hdl_impl_t * hdl)981074bb90dSTom Pothier xpv_strand_apicid(cmi_hdl_impl_t *hdl)
982074bb90dSTom Pothier {
983074bb90dSTom Pothier 	return (xen_physcpu_initial_apicid(HDLPRIV(hdl)));
984074bb90dSTom Pothier }
985074bb90dSTom Pothier 
986074bb90dSTom Pothier static uint16_t
xpv_smbiosid(cmi_hdl_impl_t * hdl)987074bb90dSTom Pothier xpv_smbiosid(cmi_hdl_impl_t *hdl)
988074bb90dSTom Pothier {
989074bb90dSTom Pothier 	return (hdl->cmih_smbiosid);
990074bb90dSTom Pothier }
991074bb90dSTom Pothier 
992074bb90dSTom Pothier static uint_t
xpv_smb_chipid(cmi_hdl_impl_t * hdl)993074bb90dSTom Pothier xpv_smb_chipid(cmi_hdl_impl_t *hdl)
994074bb90dSTom Pothier {
995074bb90dSTom Pothier 	return (hdl->cmih_smb_chipid);
996074bb90dSTom Pothier }
997074bb90dSTom Pothier 
998074bb90dSTom Pothier static nvlist_t *
xpv_smb_bboard(cmi_hdl_impl_t * hdl)999074bb90dSTom Pothier xpv_smb_bboard(cmi_hdl_impl_t *hdl)
1000074bb90dSTom Pothier {
1001074bb90dSTom Pothier 	return (hdl->cmih_smb_bboard);
1002074bb90dSTom Pothier }
1003074bb90dSTom Pothier 
100422e4c3acSKeith M Wesolowski extern x86_chiprev_t _cpuid_chiprev(uint_t, uint_t, uint_t, uint_t);
1005e4b86885SCheng Sean Ye 
100622e4c3acSKeith M Wesolowski static x86_chiprev_t
xpv_chiprev(cmi_hdl_impl_t * hdl)1007e4b86885SCheng Sean Ye xpv_chiprev(cmi_hdl_impl_t *hdl)
1008e4b86885SCheng Sean Ye {
1009e4b86885SCheng Sean Ye 	return (_cpuid_chiprev(xpv_vendor(hdl), xpv_family(hdl),
1010e4b86885SCheng Sean Ye 	    xpv_model(hdl), xpv_stepping(hdl)));
1011e4b86885SCheng Sean Ye }
1012e4b86885SCheng Sean Ye 
1013e4b86885SCheng Sean Ye extern const char *_cpuid_chiprevstr(uint_t, uint_t, uint_t, uint_t);
1014e4b86885SCheng Sean Ye 
1015e4b86885SCheng Sean Ye static const char *
xpv_chiprevstr(cmi_hdl_impl_t * hdl)1016e4b86885SCheng Sean Ye xpv_chiprevstr(cmi_hdl_impl_t *hdl)
1017e4b86885SCheng Sean Ye {
1018e4b86885SCheng Sean Ye 	return (_cpuid_chiprevstr(xpv_vendor(hdl), xpv_family(hdl),
1019e4b86885SCheng Sean Ye 	    xpv_model(hdl), xpv_stepping(hdl)));
1020e4b86885SCheng Sean Ye }
1021e4b86885SCheng Sean Ye 
1022e4b86885SCheng Sean Ye extern uint32_t _cpuid_skt(uint_t, uint_t, uint_t, uint_t);
1023e4b86885SCheng Sean Ye 
1024e4b86885SCheng Sean Ye static uint32_t
xpv_getsockettype(cmi_hdl_impl_t * hdl)1025e4b86885SCheng Sean Ye xpv_getsockettype(cmi_hdl_impl_t *hdl)
1026e4b86885SCheng Sean Ye {
1027e4b86885SCheng Sean Ye 	return (_cpuid_skt(xpv_vendor(hdl), xpv_family(hdl),
1028e4b86885SCheng Sean Ye 	    xpv_model(hdl), xpv_stepping(hdl)));
1029e4b86885SCheng Sean Ye }
1030e4b86885SCheng Sean Ye 
103189e921d5SKuriakose Kuruvilla extern const char *_cpuid_sktstr(uint_t, uint_t, uint_t, uint_t);
103289e921d5SKuriakose Kuruvilla 
103389e921d5SKuriakose Kuruvilla static const char *
xpv_getsocketstr(cmi_hdl_impl_t * hdl)103489e921d5SKuriakose Kuruvilla xpv_getsocketstr(cmi_hdl_impl_t *hdl)
103589e921d5SKuriakose Kuruvilla {
103689e921d5SKuriakose Kuruvilla 	return (_cpuid_sktstr(xpv_vendor(hdl), xpv_family(hdl),
103789e921d5SKuriakose Kuruvilla 	    xpv_model(hdl), xpv_stepping(hdl)));
103889e921d5SKuriakose Kuruvilla }
103989e921d5SKuriakose Kuruvilla 
10402a613b59SRobert Mustacchi /* ARGSUSED */
10412a613b59SRobert Mustacchi static uint_t
xpv_chipsig(cmi_hdl_impl_t * hdl)10422a613b59SRobert Mustacchi xpv_chipsig(cmi_hdl_impl_t *hdl)
10432a613b59SRobert Mustacchi {
10442a613b59SRobert Mustacchi 	return (0);
10452a613b59SRobert Mustacchi }
10462a613b59SRobert Mustacchi 
1047*dd23d762SRobert Mustacchi static cmi_errno_t
xpv_ncache(cmi_hdl_impl_t * hdl,uint32_t * ncache)1048*dd23d762SRobert Mustacchi xpv_ncache(cmi_hdl_impl_t *hdl, uint32_t *ncache)
1049*dd23d762SRobert Mustacchi {
1050*dd23d762SRobert Mustacchi 	return (CMIERR_NOTSUP);
1051*dd23d762SRobert Mustacchi }
1052*dd23d762SRobert Mustacchi 
1053*dd23d762SRobert Mustacchi static cmi_errno_t
xpv_cache(cmi_hdl_impl_t * hdl,uint32_t cno,x86_cache_t * cachep)1054*dd23d762SRobert Mustacchi xpv_cache(cmi_hdl_impl_t *hdl, uint32_t cno, x86_cache_t *cachep)
1055*dd23d762SRobert Mustacchi {
1056*dd23d762SRobert Mustacchi 	return (CMIERR_NOTSUP);
1057*dd23d762SRobert Mustacchi }
1058*dd23d762SRobert Mustacchi 
1059e4b86885SCheng Sean Ye static id_t
xpv_logical_id(cmi_hdl_impl_t * hdl)1060e4b86885SCheng Sean Ye xpv_logical_id(cmi_hdl_impl_t *hdl)
1061e4b86885SCheng Sean Ye {
1062e4b86885SCheng Sean Ye 	return (xen_physcpu_logical_id(HDLPRIV(hdl)));
1063e4b86885SCheng Sean Ye }
1064e4b86885SCheng Sean Ye 
1065e4b86885SCheng Sean Ye static cmi_errno_t
xpv_rdmsr(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t * valp)1066e4b86885SCheng Sean Ye xpv_rdmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t *valp)
1067e4b86885SCheng Sean Ye {
1068e4b86885SCheng Sean Ye 	switch (msr) {
1069e4b86885SCheng Sean Ye 	case IA32_MSR_MCG_CAP:
1070e4b86885SCheng Sean Ye 		*valp = xen_physcpu_mcg_cap(HDLPRIV(hdl));
1071e4b86885SCheng Sean Ye 		break;
1072e4b86885SCheng Sean Ye 
1073e4b86885SCheng Sean Ye 	default:
1074e4b86885SCheng Sean Ye 		return (CMIERR_NOTSUP);
1075e4b86885SCheng Sean Ye 	}
1076e4b86885SCheng Sean Ye 
1077e4b86885SCheng Sean Ye 	return (CMI_SUCCESS);
1078e4b86885SCheng Sean Ye }
1079e4b86885SCheng Sean Ye 
1080e4b86885SCheng Sean Ye /*
1081e4b86885SCheng Sean Ye  * Request the hypervisor to write an MSR for us.  The hypervisor
1082e4b86885SCheng Sean Ye  * will only accept MCA-related MSRs, as this is for MCA error
1083e4b86885SCheng Sean Ye  * simulation purposes alone.  We will pre-screen MSRs for injection
1084e4b86885SCheng Sean Ye  * so we don't bother the HV with bogus requests.  We will permit
1085e4b86885SCheng Sean Ye  * injection to any MCA bank register, and to MCG_STATUS.
1086e4b86885SCheng Sean Ye  */
1087e4b86885SCheng Sean Ye 
1088e4b86885SCheng Sean Ye #define	IS_MCA_INJ_MSR(msr) \
1089e4b86885SCheng Sean Ye 	(((msr) >= IA32_MSR_MC(0, CTL) && (msr) <= IA32_MSR_MC(10, MISC)) || \
1090e4b86885SCheng Sean Ye 	(msr) == IA32_MSR_MCG_STATUS)
1091e4b86885SCheng Sean Ye 
1092e4b86885SCheng Sean Ye static cmi_errno_t
xpv_wrmsr_cmn(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val,boolean_t intpose)1093e4b86885SCheng Sean Ye xpv_wrmsr_cmn(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val, boolean_t intpose)
1094e4b86885SCheng Sean Ye {
1095ad09f8b8SMark Johnson 	xen_mc_t xmc;
1096ad09f8b8SMark Johnson 	struct xen_mc_msrinject *mci = &xmc.u.mc_msrinject;
1097e4b86885SCheng Sean Ye 
1098e4b86885SCheng Sean Ye 	if (!(hdl->cmih_flags & CMIH_F_INJACTV))
1099e4b86885SCheng Sean Ye 		return (CMIERR_NOTSUP);		/* for injection use only! */
1100e4b86885SCheng Sean Ye 
1101e4b86885SCheng Sean Ye 	if (!IS_MCA_INJ_MSR(msr))
1102e4b86885SCheng Sean Ye 		return (CMIERR_API);
1103e4b86885SCheng Sean Ye 
1104e4b86885SCheng Sean Ye 	if (panicstr)
1105e4b86885SCheng Sean Ye 		return (CMIERR_DEADLOCK);
1106e4b86885SCheng Sean Ye 
1107ad09f8b8SMark Johnson 	mci->mcinj_cpunr = xen_physcpu_logical_id(HDLPRIV(hdl));
1108ad09f8b8SMark Johnson 	mci->mcinj_flags = intpose ? MC_MSRINJ_F_INTERPOSE : 0;
1109ad09f8b8SMark Johnson 	mci->mcinj_count = 1;	/* learn to batch sometime */
1110ad09f8b8SMark Johnson 	mci->mcinj_msr[0].reg = msr;
1111ad09f8b8SMark Johnson 	mci->mcinj_msr[0].value = val;
1112e4b86885SCheng Sean Ye 
1113ad09f8b8SMark Johnson 	return (HYPERVISOR_mca(XEN_MC_msrinject, &xmc) ==
1114349b53ddSStuart Maybee 	    0 ?  CMI_SUCCESS : CMIERR_NOTSUP);
1115e4b86885SCheng Sean Ye }
1116e4b86885SCheng Sean Ye 
1117e4b86885SCheng Sean Ye static cmi_errno_t
xpv_wrmsr(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)1118e4b86885SCheng Sean Ye xpv_wrmsr(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
1119e4b86885SCheng Sean Ye {
1120e4b86885SCheng Sean Ye 	return (xpv_wrmsr_cmn(hdl, msr, val, B_FALSE));
1121e4b86885SCheng Sean Ye }
1122e4b86885SCheng Sean Ye 
1123e4b86885SCheng Sean Ye 
1124e4b86885SCheng Sean Ye static cmi_errno_t
xpv_msrinterpose(cmi_hdl_impl_t * hdl,uint_t msr,uint64_t val)1125e4b86885SCheng Sean Ye xpv_msrinterpose(cmi_hdl_impl_t *hdl, uint_t msr, uint64_t val)
1126e4b86885SCheng Sean Ye {
1127e4b86885SCheng Sean Ye 	return (xpv_wrmsr_cmn(hdl, msr, val, B_TRUE));
1128e4b86885SCheng Sean Ye }
1129e4b86885SCheng Sean Ye 
1130e4b86885SCheng Sean Ye static void
xpv_int(cmi_hdl_impl_t * hdl,int int_no)1131e4b86885SCheng Sean Ye xpv_int(cmi_hdl_impl_t *hdl, int int_no)
1132e4b86885SCheng Sean Ye {
1133ad09f8b8SMark Johnson 	xen_mc_t xmc;
1134ad09f8b8SMark Johnson 	struct xen_mc_mceinject *mce = &xmc.u.mc_mceinject;
1135e4b86885SCheng Sean Ye 
1136e4b86885SCheng Sean Ye 	if (!(hdl->cmih_flags & CMIH_F_INJACTV))
1137e4b86885SCheng Sean Ye 		return;
1138e4b86885SCheng Sean Ye 
1139e4b86885SCheng Sean Ye 	if (int_no != T_MCE) {
1140e4b86885SCheng Sean Ye 		cmn_err(CE_WARN, "xpv_int: int_no %d unimplemented\n",
1141e4b86885SCheng Sean Ye 		    int_no);
1142e4b86885SCheng Sean Ye 	}
1143e4b86885SCheng Sean Ye 
1144ad09f8b8SMark Johnson 	mce->mceinj_cpunr = xen_physcpu_logical_id(HDLPRIV(hdl));
1145e4b86885SCheng Sean Ye 
1146ad09f8b8SMark Johnson 	(void) HYPERVISOR_mca(XEN_MC_mceinject, &xmc);
1147e4b86885SCheng Sean Ye }
1148e4b86885SCheng Sean Ye 
1149e4b86885SCheng Sean Ye static int
xpv_online(cmi_hdl_impl_t * hdl,int new_status,int * old_status)1150e4b86885SCheng Sean Ye xpv_online(cmi_hdl_impl_t *hdl, int new_status, int *old_status)
1151e4b86885SCheng Sean Ye {
1152349b53ddSStuart Maybee 	xen_sysctl_t xs;
1153349b53ddSStuart Maybee 	int op, rc, status;
1154e4b86885SCheng Sean Ye 
1155e4b86885SCheng Sean Ye 	new_status &= ~P_FORCED;
1156e4b86885SCheng Sean Ye 
1157349b53ddSStuart Maybee 	switch (new_status) {
1158349b53ddSStuart Maybee 	case P_STATUS:
1159349b53ddSStuart Maybee 		op = XEN_SYSCTL_CPU_HOTPLUG_STATUS;
1160349b53ddSStuart Maybee 		break;
1161349b53ddSStuart Maybee 	case P_FAULTED:
1162349b53ddSStuart Maybee 	case P_OFFLINE:
1163349b53ddSStuart Maybee 		op = XEN_SYSCTL_CPU_HOTPLUG_OFFLINE;
1164349b53ddSStuart Maybee 		break;
1165349b53ddSStuart Maybee 	case P_ONLINE:
1166349b53ddSStuart Maybee 		op = XEN_SYSCTL_CPU_HOTPLUG_ONLINE;
1167349b53ddSStuart Maybee 		break;
1168349b53ddSStuart Maybee 	default:
1169349b53ddSStuart Maybee 		return (-1);
1170349b53ddSStuart Maybee 	}
1171e4b86885SCheng Sean Ye 
1172349b53ddSStuart Maybee 	xs.cmd = XEN_SYSCTL_cpu_hotplug;
1173349b53ddSStuart Maybee 	xs.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
1174349b53ddSStuart Maybee 	xs.u.cpu_hotplug.cpu = xen_physcpu_logical_id(HDLPRIV(hdl));
1175349b53ddSStuart Maybee 	xs.u.cpu_hotplug.op = op;
1176349b53ddSStuart Maybee 
1177349b53ddSStuart Maybee 	if ((rc = HYPERVISOR_sysctl(&xs)) >= 0) {
1178349b53ddSStuart Maybee 		status = rc;
1179349b53ddSStuart Maybee 		rc = 0;
1180349b53ddSStuart Maybee 		switch (status) {
1181349b53ddSStuart Maybee 		case XEN_CPU_HOTPLUG_STATUS_NEW:
1182349b53ddSStuart Maybee 			*old_status = P_OFFLINE;
1183349b53ddSStuart Maybee 			break;
1184349b53ddSStuart Maybee 		case XEN_CPU_HOTPLUG_STATUS_OFFLINE:
1185349b53ddSStuart Maybee 			*old_status = P_FAULTED;
1186349b53ddSStuart Maybee 			break;
1187349b53ddSStuart Maybee 		case XEN_CPU_HOTPLUG_STATUS_ONLINE:
1188349b53ddSStuart Maybee 			*old_status = P_ONLINE;
1189349b53ddSStuart Maybee 			break;
1190349b53ddSStuart Maybee 		default:
1191349b53ddSStuart Maybee 			return (-1);
1192349b53ddSStuart Maybee 		}
1193e4b86885SCheng Sean Ye 	}
1194e4b86885SCheng Sean Ye 
1195e4b86885SCheng Sean Ye 	return (-rc);
1196e4b86885SCheng Sean Ye }
1197e4b86885SCheng Sean Ye 
1198e4b86885SCheng Sean Ye #endif
1199e4b86885SCheng Sean Ye 
1200e4b86885SCheng Sean Ye /*ARGSUSED*/
120120c794b3Sgavinm static void *
cpu_search(enum cmi_hdl_class class,uint_t chipid,uint_t coreid,uint_t strandid)120220c794b3Sgavinm cpu_search(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
120320c794b3Sgavinm     uint_t strandid)
120420c794b3Sgavinm {
1205e4b86885SCheng Sean Ye #ifdef __xpv
1206e4b86885SCheng Sean Ye 	xen_mc_lcpu_cookie_t cpi;
120720c794b3Sgavinm 
1208e4b86885SCheng Sean Ye 	for (cpi = xen_physcpu_next(NULL); cpi != NULL;
1209e4b86885SCheng Sean Ye 	    cpi = xen_physcpu_next(cpi)) {
1210e4b86885SCheng Sean Ye 		if (xen_physcpu_chipid(cpi) == chipid &&
1211e4b86885SCheng Sean Ye 		    xen_physcpu_coreid(cpi) == coreid &&
1212e4b86885SCheng Sean Ye 		    xen_physcpu_strandid(cpi) == strandid)
1213e4b86885SCheng Sean Ye 			return ((void *)cpi);
121420c794b3Sgavinm 	}
1215e4b86885SCheng Sean Ye 	return (NULL);
121620c794b3Sgavinm 
1217e4b86885SCheng Sean Ye #else	/* __xpv */
1218e4b86885SCheng Sean Ye 
1219e4b86885SCheng Sean Ye 	cpu_t *cp, *startcp;
1220e4b86885SCheng Sean Ye 
1221e4b86885SCheng Sean Ye 	kpreempt_disable();
1222e4b86885SCheng Sean Ye 	cp = startcp = CPU;
1223e4b86885SCheng Sean Ye 	do {
1224e4b86885SCheng Sean Ye 		if (cmi_ntv_hwchipid(cp) == chipid &&
1225e4b86885SCheng Sean Ye 		    cmi_ntv_hwcoreid(cp) == coreid &&
1226e4b86885SCheng Sean Ye 		    cmi_ntv_hwstrandid(cp) == strandid) {
1227e4b86885SCheng Sean Ye 			kpreempt_enable();
1228e4b86885SCheng Sean Ye 			return ((void *)cp);
1229e4b86885SCheng Sean Ye 		}
1230e4b86885SCheng Sean Ye 
1231e4b86885SCheng Sean Ye 		cp = cp->cpu_next;
1232e4b86885SCheng Sean Ye 	} while (cp != startcp);
1233e4b86885SCheng Sean Ye 	kpreempt_enable();
1234e4b86885SCheng Sean Ye 	return (NULL);
1235e4b86885SCheng Sean Ye #endif	/* __ xpv */
1236e4b86885SCheng Sean Ye }
1237e4b86885SCheng Sean Ye 
1238e4b86885SCheng Sean Ye static boolean_t
cpu_is_cmt(void * priv)1239e4b86885SCheng Sean Ye cpu_is_cmt(void *priv)
1240e4b86885SCheng Sean Ye {
1241e4b86885SCheng Sean Ye #ifdef __xpv
1242e4b86885SCheng Sean Ye 	return (xen_physcpu_is_cmt((xen_mc_lcpu_cookie_t)priv));
1243e4b86885SCheng Sean Ye #else /* __xpv */
1244e4b86885SCheng Sean Ye 	cpu_t *cp = (cpu_t *)priv;
1245e4b86885SCheng Sean Ye 
1246e4b86885SCheng Sean Ye 	int strands_per_core = cpuid_get_ncpu_per_chip(cp) /
1247e4b86885SCheng Sean Ye 	    cpuid_get_ncore_per_chip(cp);
1248e4b86885SCheng Sean Ye 
1249e4b86885SCheng Sean Ye 	return (strands_per_core > 1);
1250e4b86885SCheng Sean Ye #endif /* __xpv */
125120c794b3Sgavinm }
125220c794b3Sgavinm 
12532d39cb4cSVuong Nguyen /*
12542d39cb4cSVuong Nguyen  * Find the handle entry of a given cpu identified by a <chip,core,strand>
12552d39cb4cSVuong Nguyen  * tuple.
12562d39cb4cSVuong Nguyen  */
12572d39cb4cSVuong Nguyen static cmi_hdl_ent_t *
cmi_hdl_ent_lookup(uint_t chipid,uint_t coreid,uint_t strandid)12582d39cb4cSVuong Nguyen cmi_hdl_ent_lookup(uint_t chipid, uint_t coreid, uint_t strandid)
12592d39cb4cSVuong Nguyen {
12602d2efdc6SVuong Nguyen 	int max_strands = CMI_MAX_STRANDS_PER_CHIP(cmi_core_nbits,
12612d2efdc6SVuong Nguyen 	    cmi_strand_nbits);
12622d2efdc6SVuong Nguyen 
12632d39cb4cSVuong Nguyen 	/*
12642d39cb4cSVuong Nguyen 	 * Allocate per-chip table which contains a list of handle of
12652d39cb4cSVuong Nguyen 	 * all strands of the chip.
12662d39cb4cSVuong Nguyen 	 */
12672d39cb4cSVuong Nguyen 	if (cmi_chip_tab[chipid] == NULL) {
12682d39cb4cSVuong Nguyen 		size_t sz;
12692d39cb4cSVuong Nguyen 		cmi_hdl_ent_t *pg;
12702d39cb4cSVuong Nguyen 
12712d2efdc6SVuong Nguyen 		sz = max_strands * sizeof (cmi_hdl_ent_t);
12722d39cb4cSVuong Nguyen 		pg = kmem_zalloc(sz, KM_SLEEP);
12732d39cb4cSVuong Nguyen 
12742d39cb4cSVuong Nguyen 		/* test and set the per-chip table if it is not allocated */
12752d39cb4cSVuong Nguyen 		if (atomic_cas_ptr(&cmi_chip_tab[chipid], NULL, pg) != NULL)
12762d2efdc6SVuong Nguyen 			kmem_free(pg, sz); /* someone beats us */
12772d39cb4cSVuong Nguyen 	}
12782d39cb4cSVuong Nguyen 
12792d2efdc6SVuong Nguyen 	return (cmi_chip_tab[chipid] +
12802d2efdc6SVuong Nguyen 	    ((((coreid) & CMI_MAX_COREID(cmi_core_nbits)) << cmi_strand_nbits) |
12812d2efdc6SVuong Nguyen 	    ((strandid) & CMI_MAX_STRANDID(cmi_strand_nbits))));
12822d39cb4cSVuong Nguyen }
12832d39cb4cSVuong Nguyen 
12840ce813ffSRobert Mustacchi extern void cpuid_get_ext_topo(cpu_t *, uint_t *, uint_t *);
12852d2efdc6SVuong Nguyen 
128620c794b3Sgavinm cmi_hdl_t
cmi_hdl_create(enum cmi_hdl_class class,uint_t chipid,uint_t coreid,uint_t strandid)128720c794b3Sgavinm cmi_hdl_create(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
1288e4b86885SCheng Sean Ye     uint_t strandid)
128920c794b3Sgavinm {
129020c794b3Sgavinm 	cmi_hdl_impl_t *hdl;
1291e4b86885SCheng Sean Ye 	void *priv;
12922d39cb4cSVuong Nguyen 	cmi_hdl_ent_t *ent;
12932d2efdc6SVuong Nguyen 	uint_t vendor;
129420c794b3Sgavinm 
1295e4b86885SCheng Sean Ye #ifdef __xpv
1296e4b86885SCheng Sean Ye 	ASSERT(class == CMI_HDL_SOLARIS_xVM_MCA);
1297e4b86885SCheng Sean Ye #else
1298e4b86885SCheng Sean Ye 	ASSERT(class == CMI_HDL_NATIVE);
1299e4b86885SCheng Sean Ye #endif
1300e4b86885SCheng Sean Ye 
13012d2efdc6SVuong Nguyen 	if ((priv = cpu_search(class, chipid, coreid, strandid)) == NULL)
130220c794b3Sgavinm 		return (NULL);
130320c794b3Sgavinm 
13042d2efdc6SVuong Nguyen 	/*
13052d2efdc6SVuong Nguyen 	 * Assume all chips in the system are the same type.
13062d2efdc6SVuong Nguyen 	 * For Intel, attempt to check if extended topology is available
13072d2efdc6SVuong Nguyen 	 * CPUID.EAX=0xB. If so, get the number of core and strand bits.
13082d2efdc6SVuong Nguyen 	 */
13092d2efdc6SVuong Nguyen #ifdef __xpv
13102d2efdc6SVuong Nguyen 	vendor = _cpuid_vendorstr_to_vendorcode(
13112d2efdc6SVuong Nguyen 	    (char *)xen_physcpu_vendorstr((xen_mc_lcpu_cookie_t)priv));
13122d2efdc6SVuong Nguyen #else
13132d2efdc6SVuong Nguyen 	vendor = cpuid_getvendor((cpu_t *)priv);
13142d2efdc6SVuong Nguyen #endif
13150ce813ffSRobert Mustacchi 
13160ce813ffSRobert Mustacchi 	switch (vendor) {
13170ce813ffSRobert Mustacchi 	case X86_VENDOR_Intel:
13180ce813ffSRobert Mustacchi 	case X86_VENDOR_AMD:
13199b0429a1SPu Wen 	case X86_VENDOR_HYGON:
13200ce813ffSRobert Mustacchi 		if (cmi_ext_topo_check == 0) {
13210ce813ffSRobert Mustacchi 			cpuid_get_ext_topo((cpu_t *)priv, &cmi_core_nbits,
13220ce813ffSRobert Mustacchi 			    &cmi_strand_nbits);
13230ce813ffSRobert Mustacchi 			cmi_ext_topo_check = 1;
13240ce813ffSRobert Mustacchi 		}
13250ce813ffSRobert Mustacchi 	default:
13260ce813ffSRobert Mustacchi 		break;
13272d2efdc6SVuong Nguyen 	}
13282d2efdc6SVuong Nguyen 
13292d2efdc6SVuong Nguyen 	if (chipid > CMI_MAX_CHIPID ||
13302d2efdc6SVuong Nguyen 	    coreid > CMI_MAX_COREID(cmi_core_nbits) ||
13312d2efdc6SVuong Nguyen 	    strandid > CMI_MAX_STRANDID(cmi_strand_nbits))
133220c794b3Sgavinm 		return (NULL);
133320c794b3Sgavinm 
133420c794b3Sgavinm 	hdl = kmem_zalloc(sizeof (*hdl), KM_SLEEP);
133520c794b3Sgavinm 
133620c794b3Sgavinm 	hdl->cmih_class = class;
1337e4b86885SCheng Sean Ye 	HDLOPS(hdl) = &cmi_hdl_ops;
133820c794b3Sgavinm 	hdl->cmih_chipid = chipid;
133920c794b3Sgavinm 	hdl->cmih_coreid = coreid;
134020c794b3Sgavinm 	hdl->cmih_strandid = strandid;
1341e4b86885SCheng Sean Ye 	hdl->cmih_mstrand = cpu_is_cmt(priv);
134220c794b3Sgavinm 	hdl->cmih_hdlpriv = priv;
1343e4b86885SCheng Sean Ye #ifdef __xpv
1344e4b86885SCheng Sean Ye 	hdl->cmih_msrsrc = CMI_MSR_FLAG_RD_INTERPOSEOK |
1345e4b86885SCheng Sean Ye 	    CMI_MSR_FLAG_WR_INTERPOSEOK;
13468031591dSSrihari Venkatesan 
13478031591dSSrihari Venkatesan 	/*
13488031591dSSrihari Venkatesan 	 * XXX: need hypervisor support for procnodeid, for now assume
13498031591dSSrihari Venkatesan 	 * single-node processors (procnodeid = chipid)
13508031591dSSrihari Venkatesan 	 */
13518031591dSSrihari Venkatesan 	hdl->cmih_procnodeid = xen_physcpu_chipid((xen_mc_lcpu_cookie_t)priv);
13528031591dSSrihari Venkatesan 	hdl->cmih_procnodes_per_pkg = 1;
13538031591dSSrihari Venkatesan #else   /* __xpv */
135420c794b3Sgavinm 	hdl->cmih_msrsrc = CMI_MSR_FLAG_RD_HWOK | CMI_MSR_FLAG_RD_INTERPOSEOK |
135520c794b3Sgavinm 	    CMI_MSR_FLAG_WR_HWOK | CMI_MSR_FLAG_WR_INTERPOSEOK;
13568031591dSSrihari Venkatesan 	hdl->cmih_procnodeid = cpuid_get_procnodeid((cpu_t *)priv);
13578031591dSSrihari Venkatesan 	hdl->cmih_procnodes_per_pkg =
13588031591dSSrihari Venkatesan 	    cpuid_get_procnodes_per_pkg((cpu_t *)priv);
13598031591dSSrihari Venkatesan #endif  /* __xpv */
136020c794b3Sgavinm 
13612d39cb4cSVuong Nguyen 	ent = cmi_hdl_ent_lookup(chipid, coreid, strandid);
13622d39cb4cSVuong Nguyen 	if (ent->cmae_refcnt != 0 || ent->cmae_hdlp != NULL) {
136310569901Sgavinm 		/*
136410569901Sgavinm 		 * Somehow this (chipid, coreid, strandid) id tuple has
136510569901Sgavinm 		 * already been assigned!  This indicates that the
136610569901Sgavinm 		 * callers logic in determining these values is busted,
136710569901Sgavinm 		 * or perhaps undermined by bad BIOS setup.  Complain,
136810569901Sgavinm 		 * and refuse to initialize this tuple again as bad things
136910569901Sgavinm 		 * will happen.
137010569901Sgavinm 		 */
137110569901Sgavinm 		cmn_err(CE_NOTE, "cmi_hdl_create: chipid %d coreid %d "
137210569901Sgavinm 		    "strandid %d handle already allocated!",
137310569901Sgavinm 		    chipid, coreid, strandid);
137410569901Sgavinm 		kmem_free(hdl, sizeof (*hdl));
137510569901Sgavinm 		return (NULL);
137610569901Sgavinm 	}
137720c794b3Sgavinm 
137820c794b3Sgavinm 	/*
137920c794b3Sgavinm 	 * Once we store a nonzero reference count others can find this
138020c794b3Sgavinm 	 * handle via cmi_hdl_lookup etc.  This initial hold on the handle
138120c794b3Sgavinm 	 * is to be dropped only if some other part of cmi initialization
138220c794b3Sgavinm 	 * fails or, if it succeeds, at later cpu deconfigure.  Note the
138320c794b3Sgavinm 	 * the module private data we hold in cmih_cmi and cmih_cmidata
138420c794b3Sgavinm 	 * is still NULL at this point (the caller will fill it with
138520c794b3Sgavinm 	 * cmi_hdl_setcmi if it initializes) so consumers of handles
138620c794b3Sgavinm 	 * should always be ready for that possibility.
138720c794b3Sgavinm 	 */
13882d39cb4cSVuong Nguyen 	ent->cmae_hdlp = hdl;
13892d39cb4cSVuong Nguyen 	hdl->cmih_refcntp = &ent->cmae_refcnt;
13902d39cb4cSVuong Nguyen 	ent->cmae_refcnt = 1;
139120c794b3Sgavinm 
139220c794b3Sgavinm 	return ((cmi_hdl_t)hdl);
139320c794b3Sgavinm }
139420c794b3Sgavinm 
1395074bb90dSTom Pothier void
cmi_read_smbios(cmi_hdl_t ophdl)1396074bb90dSTom Pothier cmi_read_smbios(cmi_hdl_t ophdl)
1397074bb90dSTom Pothier {
1398074bb90dSTom Pothier 
1399bb1fad37SSrihari Venkatesan 	uint_t strand_apicid = UINT_MAX;
1400bb1fad37SSrihari Venkatesan 	uint_t chip_inst = UINT_MAX;
1401bb1fad37SSrihari Venkatesan 	uint16_t smb_id = USHRT_MAX;
1402074bb90dSTom Pothier 	int rc = 0;
1403074bb90dSTom Pothier 
1404074bb90dSTom Pothier 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1405074bb90dSTom Pothier 
1406074bb90dSTom Pothier 	/* set x86gentopo compatibility */
1407074bb90dSTom Pothier 	fm_smb_fmacompat();
1408074bb90dSTom Pothier 
1409074bb90dSTom Pothier #ifndef __xpv
1410074bb90dSTom Pothier 	strand_apicid = ntv_strand_apicid(hdl);
1411074bb90dSTom Pothier #else
1412074bb90dSTom Pothier 	strand_apicid = xpv_strand_apicid(hdl);
1413074bb90dSTom Pothier #endif
1414074bb90dSTom Pothier 
1415074bb90dSTom Pothier 	if (!x86gentopo_legacy) {
1416074bb90dSTom Pothier 		/*
1417074bb90dSTom Pothier 		 * If fm_smb_chipinst() or fm_smb_bboard() fails,
1418074bb90dSTom Pothier 		 * topo reverts to legacy mode
1419074bb90dSTom Pothier 		 */
1420074bb90dSTom Pothier 		rc = fm_smb_chipinst(strand_apicid, &chip_inst, &smb_id);
1421074bb90dSTom Pothier 		if (rc == 0) {
1422074bb90dSTom Pothier 			hdl->cmih_smb_chipid = chip_inst;
1423074bb90dSTom Pothier 			hdl->cmih_smbiosid = smb_id;
1424074bb90dSTom Pothier 		} else {
1425074bb90dSTom Pothier #ifdef DEBUG
14267991dd24STom Pothier 			cmn_err(CE_NOTE, "!cmi reads smbios chip info failed");
1427074bb90dSTom Pothier #endif /* DEBUG */
1428074bb90dSTom Pothier 			return;
1429074bb90dSTom Pothier 		}
1430074bb90dSTom Pothier 
1431074bb90dSTom Pothier 		hdl->cmih_smb_bboard  = fm_smb_bboard(strand_apicid);
1432074bb90dSTom Pothier #ifdef DEBUG
1433074bb90dSTom Pothier 		if (hdl->cmih_smb_bboard == NULL)
1434074bb90dSTom Pothier 			cmn_err(CE_NOTE,
14357991dd24STom Pothier 			    "!cmi reads smbios base boards info failed");
1436074bb90dSTom Pothier #endif /* DEBUG */
1437074bb90dSTom Pothier 	}
1438074bb90dSTom Pothier }
1439074bb90dSTom Pothier 
144020c794b3Sgavinm void
cmi_hdl_hold(cmi_hdl_t ophdl)144120c794b3Sgavinm cmi_hdl_hold(cmi_hdl_t ophdl)
144220c794b3Sgavinm {
144320c794b3Sgavinm 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
144420c794b3Sgavinm 
144520c794b3Sgavinm 	ASSERT(*hdl->cmih_refcntp != 0); /* must not be the initial hold */
144620c794b3Sgavinm 
144720c794b3Sgavinm 	atomic_inc_32(hdl->cmih_refcntp);
144820c794b3Sgavinm }
144920c794b3Sgavinm 
145020c794b3Sgavinm static int
cmi_hdl_canref(cmi_hdl_ent_t * ent)14512d39cb4cSVuong Nguyen cmi_hdl_canref(cmi_hdl_ent_t *ent)
145220c794b3Sgavinm {
145320c794b3Sgavinm 	volatile uint32_t *refcntp;
145420c794b3Sgavinm 	uint32_t refcnt;
145520c794b3Sgavinm 
14562d39cb4cSVuong Nguyen 	refcntp = &ent->cmae_refcnt;
145720c794b3Sgavinm 	refcnt = *refcntp;
145820c794b3Sgavinm 
145920c794b3Sgavinm 	if (refcnt == 0) {
146020c794b3Sgavinm 		/*
146120c794b3Sgavinm 		 * Associated object never existed, is being destroyed,
146220c794b3Sgavinm 		 * or has been destroyed.
146320c794b3Sgavinm 		 */
146420c794b3Sgavinm 		return (0);
146520c794b3Sgavinm 	}
146620c794b3Sgavinm 
146720c794b3Sgavinm 	/*
146820c794b3Sgavinm 	 * We cannot use atomic increment here because once the reference
146920c794b3Sgavinm 	 * count reaches zero it must never be bumped up again.
147020c794b3Sgavinm 	 */
147120c794b3Sgavinm 	while (refcnt != 0) {
147220c794b3Sgavinm 		if (atomic_cas_32(refcntp, refcnt, refcnt + 1) == refcnt)
147320c794b3Sgavinm 			return (1);
147420c794b3Sgavinm 		refcnt = *refcntp;
147520c794b3Sgavinm 	}
147620c794b3Sgavinm 
147720c794b3Sgavinm 	/*
147820c794b3Sgavinm 	 * Somebody dropped the reference count to 0 after our initial
147920c794b3Sgavinm 	 * check.
148020c794b3Sgavinm 	 */
148120c794b3Sgavinm 	return (0);
148220c794b3Sgavinm }
148320c794b3Sgavinm 
148420c794b3Sgavinm 
148520c794b3Sgavinm void
cmi_hdl_rele(cmi_hdl_t ophdl)148620c794b3Sgavinm cmi_hdl_rele(cmi_hdl_t ophdl)
148720c794b3Sgavinm {
148820c794b3Sgavinm 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
148920c794b3Sgavinm 
149020c794b3Sgavinm 	ASSERT(*hdl->cmih_refcntp > 0);
1491640c1670SJosef 'Jeff' Sipek 	atomic_dec_32(hdl->cmih_refcntp);
1492a3114836SGerry Liu }
149320c794b3Sgavinm 
1494a3114836SGerry Liu void
cmi_hdl_destroy(cmi_hdl_t ophdl)1495a3114836SGerry Liu cmi_hdl_destroy(cmi_hdl_t ophdl)
1496a3114836SGerry Liu {
1497a3114836SGerry Liu 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1498a3114836SGerry Liu 	cmi_hdl_ent_t *ent;
1499a3114836SGerry Liu 
1500a3114836SGerry Liu 	/* Release the reference count held by cmi_hdl_create(). */
1501a3114836SGerry Liu 	ASSERT(*hdl->cmih_refcntp > 0);
1502640c1670SJosef 'Jeff' Sipek 	atomic_dec_32(hdl->cmih_refcntp);
1503a3114836SGerry Liu 	hdl->cmih_flags |= CMIH_F_DEAD;
150420c794b3Sgavinm 
15052d39cb4cSVuong Nguyen 	ent = cmi_hdl_ent_lookup(hdl->cmih_chipid, hdl->cmih_coreid,
150620c794b3Sgavinm 	    hdl->cmih_strandid);
1507a3114836SGerry Liu 	/*
1508a3114836SGerry Liu 	 * Use busy polling instead of condition variable here because
1509a3114836SGerry Liu 	 * cmi_hdl_rele() may be called from #MC handler.
1510a3114836SGerry Liu 	 */
1511a3114836SGerry Liu 	while (cmi_hdl_canref(ent)) {
1512a3114836SGerry Liu 		cmi_hdl_rele(ophdl);
1513a3114836SGerry Liu 		delay(1);
1514a3114836SGerry Liu 	}
15152d39cb4cSVuong Nguyen 	ent->cmae_hdlp = NULL;
151620c794b3Sgavinm 
151720c794b3Sgavinm 	kmem_free(hdl, sizeof (*hdl));
151820c794b3Sgavinm }
151920c794b3Sgavinm 
152020c794b3Sgavinm void
cmi_hdl_setspecific(cmi_hdl_t ophdl,void * arg)152120c794b3Sgavinm cmi_hdl_setspecific(cmi_hdl_t ophdl, void *arg)
152220c794b3Sgavinm {
152320c794b3Sgavinm 	IMPLHDL(ophdl)->cmih_spec = arg;
152420c794b3Sgavinm }
152520c794b3Sgavinm 
152620c794b3Sgavinm void *
cmi_hdl_getspecific(cmi_hdl_t ophdl)152720c794b3Sgavinm cmi_hdl_getspecific(cmi_hdl_t ophdl)
152820c794b3Sgavinm {
152920c794b3Sgavinm 	return (IMPLHDL(ophdl)->cmih_spec);
153020c794b3Sgavinm }
153120c794b3Sgavinm 
153220c794b3Sgavinm void
cmi_hdl_setmc(cmi_hdl_t ophdl,const struct cmi_mc_ops * mcops,void * mcdata)153320c794b3Sgavinm cmi_hdl_setmc(cmi_hdl_t ophdl, const struct cmi_mc_ops *mcops, void *mcdata)
153420c794b3Sgavinm {
153520c794b3Sgavinm 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
153620c794b3Sgavinm 
153720c794b3Sgavinm 	ASSERT(hdl->cmih_mcops == NULL && hdl->cmih_mcdata == NULL);
153820c794b3Sgavinm 	hdl->cmih_mcops = mcops;
153920c794b3Sgavinm 	hdl->cmih_mcdata = mcdata;
154020c794b3Sgavinm }
154120c794b3Sgavinm 
154220c794b3Sgavinm const struct cmi_mc_ops *
cmi_hdl_getmcops(cmi_hdl_t ophdl)154320c794b3Sgavinm cmi_hdl_getmcops(cmi_hdl_t ophdl)
154420c794b3Sgavinm {
154520c794b3Sgavinm 	return (IMPLHDL(ophdl)->cmih_mcops);
154620c794b3Sgavinm }
154720c794b3Sgavinm 
154820c794b3Sgavinm void *
cmi_hdl_getmcdata(cmi_hdl_t ophdl)154920c794b3Sgavinm cmi_hdl_getmcdata(cmi_hdl_t ophdl)
155020c794b3Sgavinm {
155120c794b3Sgavinm 	return (IMPLHDL(ophdl)->cmih_mcdata);
155220c794b3Sgavinm }
155320c794b3Sgavinm 
155420c794b3Sgavinm cmi_hdl_t
cmi_hdl_lookup(enum cmi_hdl_class class,uint_t chipid,uint_t coreid,uint_t strandid)155520c794b3Sgavinm cmi_hdl_lookup(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
155620c794b3Sgavinm     uint_t strandid)
155720c794b3Sgavinm {
15582d39cb4cSVuong Nguyen 	cmi_hdl_ent_t *ent;
15594071b45aSstephh 
15602d39cb4cSVuong Nguyen 	if (chipid > CMI_MAX_CHIPID ||
15612d2efdc6SVuong Nguyen 	    coreid > CMI_MAX_COREID(cmi_core_nbits) ||
15622d2efdc6SVuong Nguyen 	    strandid > CMI_MAX_STRANDID(cmi_strand_nbits))
15634071b45aSstephh 		return (NULL);
15644071b45aSstephh 
15652d39cb4cSVuong Nguyen 	ent = cmi_hdl_ent_lookup(chipid, coreid, strandid);
156620c794b3Sgavinm 
1567e4b86885SCheng Sean Ye 	if (class == CMI_HDL_NEUTRAL)
1568e4b86885SCheng Sean Ye #ifdef __xpv
1569e4b86885SCheng Sean Ye 		class = CMI_HDL_SOLARIS_xVM_MCA;
1570e4b86885SCheng Sean Ye #else
1571e4b86885SCheng Sean Ye 		class = CMI_HDL_NATIVE;
1572e4b86885SCheng Sean Ye #endif
1573e4b86885SCheng Sean Ye 
15742d39cb4cSVuong Nguyen 	if (!cmi_hdl_canref(ent))
157520c794b3Sgavinm 		return (NULL);
157620c794b3Sgavinm 
15772d39cb4cSVuong Nguyen 	if (ent->cmae_hdlp->cmih_class != class) {
15782d39cb4cSVuong Nguyen 		cmi_hdl_rele((cmi_hdl_t)ent->cmae_hdlp);
157920c794b3Sgavinm 		return (NULL);
158020c794b3Sgavinm 	}
158120c794b3Sgavinm 
15822d39cb4cSVuong Nguyen 	return ((cmi_hdl_t)ent->cmae_hdlp);
158320c794b3Sgavinm }
158420c794b3Sgavinm 
158520c794b3Sgavinm cmi_hdl_t
cmi_hdl_any(void)158620c794b3Sgavinm cmi_hdl_any(void)
158720c794b3Sgavinm {
15882d39cb4cSVuong Nguyen 	int i, j;
15892d39cb4cSVuong Nguyen 	cmi_hdl_ent_t *ent;
15902d2efdc6SVuong Nguyen 	int max_strands = CMI_MAX_STRANDS_PER_CHIP(cmi_core_nbits,
15912d2efdc6SVuong Nguyen 	    cmi_strand_nbits);
159220c794b3Sgavinm 
15932d39cb4cSVuong Nguyen 	for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
15942d39cb4cSVuong Nguyen 		if (cmi_chip_tab[i] == NULL)
15952d39cb4cSVuong Nguyen 			continue;
15962d2efdc6SVuong Nguyen 		for (j = 0, ent = cmi_chip_tab[i]; j < max_strands;
15972d39cb4cSVuong Nguyen 		    j++, ent++) {
15982d39cb4cSVuong Nguyen 			if (cmi_hdl_canref(ent))
15992d39cb4cSVuong Nguyen 				return ((cmi_hdl_t)ent->cmae_hdlp);
16002d39cb4cSVuong Nguyen 		}
160120c794b3Sgavinm 	}
160220c794b3Sgavinm 
160320c794b3Sgavinm 	return (NULL);
160420c794b3Sgavinm }
160520c794b3Sgavinm 
160620c794b3Sgavinm void
cmi_hdl_walk(int (* cbfunc)(cmi_hdl_t,void *,void *,void *),void * arg1,void * arg2,void * arg3)160720c794b3Sgavinm cmi_hdl_walk(int (*cbfunc)(cmi_hdl_t, void *, void *, void *),
160820c794b3Sgavinm     void *arg1, void *arg2, void *arg3)
160920c794b3Sgavinm {
16102d39cb4cSVuong Nguyen 	int i, j;
16112d39cb4cSVuong Nguyen 	cmi_hdl_ent_t *ent;
16122d2efdc6SVuong Nguyen 	int max_strands = CMI_MAX_STRANDS_PER_CHIP(cmi_core_nbits,
16132d2efdc6SVuong Nguyen 	    cmi_strand_nbits);
16142d39cb4cSVuong Nguyen 
16152d39cb4cSVuong Nguyen 	for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
16162d39cb4cSVuong Nguyen 		if (cmi_chip_tab[i] == NULL)
16172d39cb4cSVuong Nguyen 			continue;
16182d2efdc6SVuong Nguyen 		for (j = 0, ent = cmi_chip_tab[i]; j < max_strands;
16192d39cb4cSVuong Nguyen 		    j++, ent++) {
16202d39cb4cSVuong Nguyen 			if (cmi_hdl_canref(ent)) {
16212d39cb4cSVuong Nguyen 				cmi_hdl_impl_t *hdl = ent->cmae_hdlp;
16222d39cb4cSVuong Nguyen 				if ((*cbfunc)((cmi_hdl_t)hdl, arg1, arg2, arg3)
16232d39cb4cSVuong Nguyen 				    == CMI_HDL_WALK_DONE) {
16242d39cb4cSVuong Nguyen 					cmi_hdl_rele((cmi_hdl_t)hdl);
16252d39cb4cSVuong Nguyen 					return;
16262d39cb4cSVuong Nguyen 				}
162720c794b3Sgavinm 				cmi_hdl_rele((cmi_hdl_t)hdl);
162820c794b3Sgavinm 			}
162920c794b3Sgavinm 		}
163020c794b3Sgavinm 	}
163120c794b3Sgavinm }
163220c794b3Sgavinm 
163320c794b3Sgavinm void
cmi_hdl_setcmi(cmi_hdl_t ophdl,void * cmi,void * cmidata)163420c794b3Sgavinm cmi_hdl_setcmi(cmi_hdl_t ophdl, void *cmi, void *cmidata)
163520c794b3Sgavinm {
163620c794b3Sgavinm 	IMPLHDL(ophdl)->cmih_cmidata = cmidata;
163720c794b3Sgavinm 	IMPLHDL(ophdl)->cmih_cmi = cmi;
163820c794b3Sgavinm }
163920c794b3Sgavinm 
164020c794b3Sgavinm void *
cmi_hdl_getcmi(cmi_hdl_t ophdl)164120c794b3Sgavinm cmi_hdl_getcmi(cmi_hdl_t ophdl)
164220c794b3Sgavinm {
164320c794b3Sgavinm 	return (IMPLHDL(ophdl)->cmih_cmi);
164420c794b3Sgavinm }
164520c794b3Sgavinm 
164620c794b3Sgavinm void *
cmi_hdl_getcmidata(cmi_hdl_t ophdl)164720c794b3Sgavinm cmi_hdl_getcmidata(cmi_hdl_t ophdl)
164820c794b3Sgavinm {
164920c794b3Sgavinm 	return (IMPLHDL(ophdl)->cmih_cmidata);
165020c794b3Sgavinm }
165120c794b3Sgavinm 
165220c794b3Sgavinm enum cmi_hdl_class
cmi_hdl_class(cmi_hdl_t ophdl)165320c794b3Sgavinm cmi_hdl_class(cmi_hdl_t ophdl)
165420c794b3Sgavinm {
165520c794b3Sgavinm 	return (IMPLHDL(ophdl)->cmih_class);
165620c794b3Sgavinm }
165720c794b3Sgavinm 
165820c794b3Sgavinm #define	CMI_HDL_OPFUNC(what, type)				\
165920c794b3Sgavinm 	type							\
166020c794b3Sgavinm 	cmi_hdl_##what(cmi_hdl_t ophdl)				\
166120c794b3Sgavinm 	{							\
1662e4b86885SCheng Sean Ye 		return (HDLOPS(IMPLHDL(ophdl))->		\
166320c794b3Sgavinm 		    cmio_##what(IMPLHDL(ophdl)));		\
166420c794b3Sgavinm 	}
166520c794b3Sgavinm 
16662a613b59SRobert Mustacchi /* BEGIN CSTYLED */
CMI_HDL_OPFUNC(vendor,uint_t)166720c794b3Sgavinm CMI_HDL_OPFUNC(vendor, uint_t)
166820c794b3Sgavinm CMI_HDL_OPFUNC(vendorstr, const char *)
166920c794b3Sgavinm CMI_HDL_OPFUNC(family, uint_t)
167020c794b3Sgavinm CMI_HDL_OPFUNC(model, uint_t)
167120c794b3Sgavinm CMI_HDL_OPFUNC(stepping, uint_t)
167220c794b3Sgavinm CMI_HDL_OPFUNC(chipid, uint_t)
16738031591dSSrihari Venkatesan CMI_HDL_OPFUNC(procnodeid, uint_t)
167420c794b3Sgavinm CMI_HDL_OPFUNC(coreid, uint_t)
167520c794b3Sgavinm CMI_HDL_OPFUNC(strandid, uint_t)
16768031591dSSrihari Venkatesan CMI_HDL_OPFUNC(procnodes_per_pkg, uint_t)
1677074bb90dSTom Pothier CMI_HDL_OPFUNC(strand_apicid, uint_t)
167822e4c3acSKeith M Wesolowski CMI_HDL_OPFUNC(chiprev, x86_chiprev_t)
167920c794b3Sgavinm CMI_HDL_OPFUNC(chiprevstr, const char *)
168020c794b3Sgavinm CMI_HDL_OPFUNC(getsockettype, uint32_t)
168189e921d5SKuriakose Kuruvilla CMI_HDL_OPFUNC(getsocketstr, const char *)
1682e4b86885SCheng Sean Ye CMI_HDL_OPFUNC(logical_id, id_t)
1683074bb90dSTom Pothier CMI_HDL_OPFUNC(smbiosid, uint16_t)
1684074bb90dSTom Pothier CMI_HDL_OPFUNC(smb_chipid, uint_t)
1685074bb90dSTom Pothier CMI_HDL_OPFUNC(smb_bboard, nvlist_t *)
16862a613b59SRobert Mustacchi CMI_HDL_OPFUNC(chipsig, uint_t)
16872a613b59SRobert Mustacchi /* END CSTYLED */
1688e4b86885SCheng Sean Ye 
1689e4b86885SCheng Sean Ye boolean_t
1690e4b86885SCheng Sean Ye cmi_hdl_is_cmt(cmi_hdl_t ophdl)
1691e4b86885SCheng Sean Ye {
1692e4b86885SCheng Sean Ye 	return (IMPLHDL(ophdl)->cmih_mstrand);
1693e4b86885SCheng Sean Ye }
169420c794b3Sgavinm 
169520c794b3Sgavinm void
cmi_hdl_int(cmi_hdl_t ophdl,int num)1696e3d60c9bSAdrian Frost cmi_hdl_int(cmi_hdl_t ophdl, int num)
169720c794b3Sgavinm {
1698e4b86885SCheng Sean Ye 	if (HDLOPS(IMPLHDL(ophdl))->cmio_int == NULL)
1699e4b86885SCheng Sean Ye 		return;
1700e4b86885SCheng Sean Ye 
1701e4b86885SCheng Sean Ye 	cmi_hdl_inj_begin(ophdl);
1702e4b86885SCheng Sean Ye 	HDLOPS(IMPLHDL(ophdl))->cmio_int(IMPLHDL(ophdl), num);
1703e4b86885SCheng Sean Ye 	cmi_hdl_inj_end(NULL);
1704e4b86885SCheng Sean Ye }
1705e4b86885SCheng Sean Ye 
1706e4b86885SCheng Sean Ye int
cmi_hdl_online(cmi_hdl_t ophdl,int new_status,int * old_status)1707e4b86885SCheng Sean Ye cmi_hdl_online(cmi_hdl_t ophdl, int new_status, int *old_status)
1708e4b86885SCheng Sean Ye {
1709e4b86885SCheng Sean Ye 	return (HDLOPS(IMPLHDL(ophdl))->cmio_online(IMPLHDL(ophdl),
1710e4b86885SCheng Sean Ye 	    new_status, old_status));
171120c794b3Sgavinm }
171220c794b3Sgavinm 
171320c794b3Sgavinm #ifndef	__xpv
171420c794b3Sgavinm /*
171520c794b3Sgavinm  * Return hardware chip instance; cpuid_get_chipid provides this directly.
171620c794b3Sgavinm  */
171720c794b3Sgavinm uint_t
cmi_ntv_hwchipid(cpu_t * cp)171820c794b3Sgavinm cmi_ntv_hwchipid(cpu_t *cp)
171920c794b3Sgavinm {
172020c794b3Sgavinm 	return (cpuid_get_chipid(cp));
172120c794b3Sgavinm }
172220c794b3Sgavinm 
17238031591dSSrihari Venkatesan /*
17248031591dSSrihari Venkatesan  * Return hardware node instance; cpuid_get_procnodeid provides this directly.
17258031591dSSrihari Venkatesan  */
17268031591dSSrihari Venkatesan uint_t
cmi_ntv_hwprocnodeid(cpu_t * cp)17278031591dSSrihari Venkatesan cmi_ntv_hwprocnodeid(cpu_t *cp)
17288031591dSSrihari Venkatesan {
17298031591dSSrihari Venkatesan 	return (cpuid_get_procnodeid(cp));
17308031591dSSrihari Venkatesan }
17318031591dSSrihari Venkatesan 
173220c794b3Sgavinm /*
173310569901Sgavinm  * Return core instance within a single chip.
173420c794b3Sgavinm  */
173520c794b3Sgavinm uint_t
cmi_ntv_hwcoreid(cpu_t * cp)173620c794b3Sgavinm cmi_ntv_hwcoreid(cpu_t *cp)
173720c794b3Sgavinm {
173810569901Sgavinm 	return (cpuid_get_pkgcoreid(cp));
173920c794b3Sgavinm }
174020c794b3Sgavinm 
174120c794b3Sgavinm /*
174220c794b3Sgavinm  * Return strand number within a single core.  cpuid_get_clogid numbers
174320c794b3Sgavinm  * all execution units (strands, or cores in unstranded models) sequentially
174420c794b3Sgavinm  * within a single chip.
174520c794b3Sgavinm  */
174620c794b3Sgavinm uint_t
cmi_ntv_hwstrandid(cpu_t * cp)174720c794b3Sgavinm cmi_ntv_hwstrandid(cpu_t *cp)
174820c794b3Sgavinm {
174920c794b3Sgavinm 	int strands_per_core = cpuid_get_ncpu_per_chip(cp) /
175020c794b3Sgavinm 	    cpuid_get_ncore_per_chip(cp);
175120c794b3Sgavinm 
175220c794b3Sgavinm 	return (cpuid_get_clogid(cp) % strands_per_core);
175320c794b3Sgavinm }
1754a3114836SGerry Liu 
1755a3114836SGerry Liu static void
cmi_ntv_hwdisable_mce_xc(void)1756a3114836SGerry Liu cmi_ntv_hwdisable_mce_xc(void)
1757a3114836SGerry Liu {
1758a3114836SGerry Liu 	ulong_t cr4;
1759a3114836SGerry Liu 
1760a3114836SGerry Liu 	cr4 = getcr4();
1761a3114836SGerry Liu 	cr4 = cr4 & (~CR4_MCE);
1762a3114836SGerry Liu 	setcr4(cr4);
1763a3114836SGerry Liu }
1764a3114836SGerry Liu 
1765a3114836SGerry Liu void
cmi_ntv_hwdisable_mce(cmi_hdl_t hdl)1766a3114836SGerry Liu cmi_ntv_hwdisable_mce(cmi_hdl_t hdl)
1767a3114836SGerry Liu {
1768a3114836SGerry Liu 	cpuset_t	set;
1769a3114836SGerry Liu 	cmi_hdl_impl_t *thdl = IMPLHDL(hdl);
1770a3114836SGerry Liu 	cpu_t *cp = HDLPRIV(thdl);
1771a3114836SGerry Liu 
1772a3114836SGerry Liu 	if (CPU->cpu_id == cp->cpu_id) {
1773a3114836SGerry Liu 		cmi_ntv_hwdisable_mce_xc();
1774a3114836SGerry Liu 	} else {
1775a3114836SGerry Liu 		CPUSET_ONLY(set, cp->cpu_id);
17764da99751SToomas Soome 		xc_call(0, 0, 0, CPUSET2BV(set),
1777a3114836SGerry Liu 		    (xc_func_t)cmi_ntv_hwdisable_mce_xc);
1778a3114836SGerry Liu 	}
1779a3114836SGerry Liu }
1780a3114836SGerry Liu 
178120c794b3Sgavinm #endif	/* __xpv */
178220c794b3Sgavinm 
178320c794b3Sgavinm void
cmi_hdlconf_rdmsr_nohw(cmi_hdl_t ophdl)178420c794b3Sgavinm cmi_hdlconf_rdmsr_nohw(cmi_hdl_t ophdl)
178520c794b3Sgavinm {
178620c794b3Sgavinm 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
178720c794b3Sgavinm 
178820c794b3Sgavinm 	hdl->cmih_msrsrc &= ~CMI_MSR_FLAG_RD_HWOK;
178920c794b3Sgavinm }
179020c794b3Sgavinm 
179120c794b3Sgavinm void
cmi_hdlconf_wrmsr_nohw(cmi_hdl_t ophdl)179220c794b3Sgavinm cmi_hdlconf_wrmsr_nohw(cmi_hdl_t ophdl)
179320c794b3Sgavinm {
179420c794b3Sgavinm 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
179520c794b3Sgavinm 
179620c794b3Sgavinm 	hdl->cmih_msrsrc &= ~CMI_MSR_FLAG_WR_HWOK;
179720c794b3Sgavinm }
179820c794b3Sgavinm 
179920c794b3Sgavinm cmi_errno_t
cmi_hdl_rdmsr(cmi_hdl_t ophdl,uint_t msr,uint64_t * valp)180020c794b3Sgavinm cmi_hdl_rdmsr(cmi_hdl_t ophdl, uint_t msr, uint64_t *valp)
180120c794b3Sgavinm {
180220c794b3Sgavinm 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
180320c794b3Sgavinm 
180420c794b3Sgavinm 	/*
180520c794b3Sgavinm 	 * Regardless of the handle class, we first check for am
180620c794b3Sgavinm 	 * interposed value.  In the xVM case you probably want to
180720c794b3Sgavinm 	 * place interposed values within the hypervisor itself, but
180820c794b3Sgavinm 	 * we still allow interposing them in dom0 for test and bringup
180920c794b3Sgavinm 	 * purposes.
181020c794b3Sgavinm 	 */
181120c794b3Sgavinm 	if ((hdl->cmih_msrsrc & CMI_MSR_FLAG_RD_INTERPOSEOK) &&
181220c794b3Sgavinm 	    msri_lookup(hdl, msr, valp))
181320c794b3Sgavinm 		return (CMI_SUCCESS);
181420c794b3Sgavinm 
1815e4b86885SCheng Sean Ye 	if (HDLOPS(hdl)->cmio_rdmsr == NULL)
1816e4b86885SCheng Sean Ye 		return (CMIERR_NOTSUP);
181720c794b3Sgavinm 
1818e4b86885SCheng Sean Ye 	return (HDLOPS(hdl)->cmio_rdmsr(hdl, msr, valp));
181920c794b3Sgavinm }
182020c794b3Sgavinm 
182120c794b3Sgavinm cmi_errno_t
cmi_hdl_wrmsr(cmi_hdl_t ophdl,uint_t msr,uint64_t val)182220c794b3Sgavinm cmi_hdl_wrmsr(cmi_hdl_t ophdl, uint_t msr, uint64_t val)
182320c794b3Sgavinm {
182420c794b3Sgavinm 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
182520c794b3Sgavinm 
182620c794b3Sgavinm 	/* Invalidate any interposed value */
182720c794b3Sgavinm 	msri_rment(hdl, msr);
182820c794b3Sgavinm 
1829e4b86885SCheng Sean Ye 	if (HDLOPS(hdl)->cmio_wrmsr == NULL)
1830e4b86885SCheng Sean Ye 		return (CMI_SUCCESS);	/* pretend all is ok */
183120c794b3Sgavinm 
1832e4b86885SCheng Sean Ye 	return (HDLOPS(hdl)->cmio_wrmsr(hdl, msr, val));
183320c794b3Sgavinm }
183420c794b3Sgavinm 
183520c794b3Sgavinm void
cmi_hdl_enable_mce(cmi_hdl_t ophdl)183620c794b3Sgavinm cmi_hdl_enable_mce(cmi_hdl_t ophdl)
183720c794b3Sgavinm {
183820c794b3Sgavinm 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1839e4b86885SCheng Sean Ye 	ulong_t cr4;
184020c794b3Sgavinm 
1841e4b86885SCheng Sean Ye 	if (HDLOPS(hdl)->cmio_getcr4 == NULL ||
1842e4b86885SCheng Sean Ye 	    HDLOPS(hdl)->cmio_setcr4 == NULL)
1843e4b86885SCheng Sean Ye 		return;
1844e4b86885SCheng Sean Ye 
1845e4b86885SCheng Sean Ye 	cr4 = HDLOPS(hdl)->cmio_getcr4(hdl);
1846e4b86885SCheng Sean Ye 
1847e4b86885SCheng Sean Ye 	HDLOPS(hdl)->cmio_setcr4(hdl, cr4 | CR4_MCE);
184820c794b3Sgavinm }
184920c794b3Sgavinm 
185020c794b3Sgavinm void
cmi_hdl_msrinterpose(cmi_hdl_t ophdl,cmi_mca_regs_t * regs,uint_t nregs)185120c794b3Sgavinm cmi_hdl_msrinterpose(cmi_hdl_t ophdl, cmi_mca_regs_t *regs, uint_t nregs)
185220c794b3Sgavinm {
185320c794b3Sgavinm 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
185420c794b3Sgavinm 	int i;
185520c794b3Sgavinm 
1856e4b86885SCheng Sean Ye 	if (HDLOPS(hdl)->cmio_msrinterpose == NULL)
1857e4b86885SCheng Sean Ye 		return;
1858e4b86885SCheng Sean Ye 
1859e4b86885SCheng Sean Ye 	cmi_hdl_inj_begin(ophdl);
1860e4b86885SCheng Sean Ye 
1861e4b86885SCheng Sean Ye 	for (i = 0; i < nregs; i++, regs++)
1862e4b86885SCheng Sean Ye 		HDLOPS(hdl)->cmio_msrinterpose(hdl, regs->cmr_msrnum,
1863e4b86885SCheng Sean Ye 		    regs->cmr_msrval);
1864e4b86885SCheng Sean Ye 
1865e4b86885SCheng Sean Ye 	cmi_hdl_inj_end(ophdl);
1866e4b86885SCheng Sean Ye }
1867e4b86885SCheng Sean Ye 
1868e4b86885SCheng Sean Ye /*ARGSUSED*/
1869e4b86885SCheng Sean Ye void
cmi_hdl_msrforward(cmi_hdl_t ophdl,cmi_mca_regs_t * regs,uint_t nregs)1870e4b86885SCheng Sean Ye cmi_hdl_msrforward(cmi_hdl_t ophdl, cmi_mca_regs_t *regs, uint_t nregs)
1871e4b86885SCheng Sean Ye {
1872e4b86885SCheng Sean Ye #ifdef __xpv
1873e4b86885SCheng Sean Ye 	cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
1874e4b86885SCheng Sean Ye 	int i;
1875e4b86885SCheng Sean Ye 
1876e4b86885SCheng Sean Ye 	for (i = 0; i < nregs; i++, regs++)
1877e4b86885SCheng Sean Ye 		msri_addent(hdl, regs->cmr_msrnum, regs->cmr_msrval);
1878e4b86885SCheng Sean Ye #endif
187920c794b3Sgavinm }
188020c794b3Sgavinm 
1881e4b86885SCheng Sean Ye 
188220c794b3Sgavinm void
cmi_pcird_nohw(void)188320c794b3Sgavinm cmi_pcird_nohw(void)
188420c794b3Sgavinm {
188520c794b3Sgavinm 	cmi_pcicfg_flags &= ~CMI_PCICFG_FLAG_RD_HWOK;
188620c794b3Sgavinm }
188720c794b3Sgavinm 
188820c794b3Sgavinm void
cmi_pciwr_nohw(void)188920c794b3Sgavinm cmi_pciwr_nohw(void)
189020c794b3Sgavinm {
189120c794b3Sgavinm 	cmi_pcicfg_flags &= ~CMI_PCICFG_FLAG_WR_HWOK;
189220c794b3Sgavinm }
189320c794b3Sgavinm 
189420c794b3Sgavinm static uint32_t
cmi_pci_get_cmn(int bus,int dev,int func,int reg,int asz,int * interpose,ddi_acc_handle_t hdl)189520c794b3Sgavinm cmi_pci_get_cmn(int bus, int dev, int func, int reg, int asz,
189620c794b3Sgavinm     int *interpose, ddi_acc_handle_t hdl)
189720c794b3Sgavinm {
189820c794b3Sgavinm 	uint32_t val;
189920c794b3Sgavinm 
190020c794b3Sgavinm 	if (cmi_pcicfg_flags & CMI_PCICFG_FLAG_RD_INTERPOSEOK &&
190120c794b3Sgavinm 	    pcii_lookup(bus, dev, func, reg, asz, &val)) {
190220c794b3Sgavinm 		if (interpose)
190320c794b3Sgavinm 			*interpose = 1;
190420c794b3Sgavinm 		return (val);
190520c794b3Sgavinm 	}
190620c794b3Sgavinm 	if (interpose)
190720c794b3Sgavinm 		*interpose = 0;
190820c794b3Sgavinm 
190920c794b3Sgavinm 	if (!(cmi_pcicfg_flags & CMI_PCICFG_FLAG_RD_HWOK))
191020c794b3Sgavinm 		return (0);
191120c794b3Sgavinm 
191220c794b3Sgavinm 	switch (asz) {
191320c794b3Sgavinm 	case 1:
191420c794b3Sgavinm 		if (hdl)
191520c794b3Sgavinm 			val = pci_config_get8(hdl, (off_t)reg);
191620c794b3Sgavinm 		else
19175667185bSSrihari Venkatesan 			val = pci_cfgacc_get8(NULL, PCI_GETBDF(bus, dev, func),
19185667185bSSrihari Venkatesan 			    reg);
191920c794b3Sgavinm 		break;
192020c794b3Sgavinm 	case 2:
192120c794b3Sgavinm 		if (hdl)
192220c794b3Sgavinm 			val = pci_config_get16(hdl, (off_t)reg);
192320c794b3Sgavinm 		else
19245667185bSSrihari Venkatesan 			val = pci_cfgacc_get16(NULL, PCI_GETBDF(bus, dev, func),
19255667185bSSrihari Venkatesan 			    reg);
192620c794b3Sgavinm 		break;
192720c794b3Sgavinm 	case 4:
192820c794b3Sgavinm 		if (hdl)
192920c794b3Sgavinm 			val = pci_config_get32(hdl, (off_t)reg);
193020c794b3Sgavinm 		else
19315667185bSSrihari Venkatesan 			val = pci_cfgacc_get32(NULL, PCI_GETBDF(bus, dev, func),
19325667185bSSrihari Venkatesan 			    reg);
193320c794b3Sgavinm 		break;
193420c794b3Sgavinm 	default:
193520c794b3Sgavinm 		val = 0;
193620c794b3Sgavinm 	}
193720c794b3Sgavinm 	return (val);
193820c794b3Sgavinm }
193920c794b3Sgavinm 
194020c794b3Sgavinm uint8_t
cmi_pci_getb(int bus,int dev,int func,int reg,int * interpose,ddi_acc_handle_t hdl)194120c794b3Sgavinm cmi_pci_getb(int bus, int dev, int func, int reg, int *interpose,
194220c794b3Sgavinm     ddi_acc_handle_t hdl)
194320c794b3Sgavinm {
194420c794b3Sgavinm 	return ((uint8_t)cmi_pci_get_cmn(bus, dev, func, reg, 1, interpose,
194520c794b3Sgavinm 	    hdl));
194620c794b3Sgavinm }
194720c794b3Sgavinm 
194820c794b3Sgavinm uint16_t
cmi_pci_getw(int bus,int dev,int func,int reg,int * interpose,ddi_acc_handle_t hdl)194920c794b3Sgavinm cmi_pci_getw(int bus, int dev, int func, int reg, int *interpose,
195020c794b3Sgavinm     ddi_acc_handle_t hdl)
195120c794b3Sgavinm {
195220c794b3Sgavinm 	return ((uint16_t)cmi_pci_get_cmn(bus, dev, func, reg, 2, interpose,
195320c794b3Sgavinm 	    hdl));
195420c794b3Sgavinm }
195520c794b3Sgavinm 
195620c794b3Sgavinm uint32_t
cmi_pci_getl(int bus,int dev,int func,int reg,int * interpose,ddi_acc_handle_t hdl)195720c794b3Sgavinm cmi_pci_getl(int bus, int dev, int func, int reg, int *interpose,
195820c794b3Sgavinm     ddi_acc_handle_t hdl)
195920c794b3Sgavinm {
196020c794b3Sgavinm 	return (cmi_pci_get_cmn(bus, dev, func, reg, 4, interpose, hdl));
196120c794b3Sgavinm }
196220c794b3Sgavinm 
196320c794b3Sgavinm void
cmi_pci_interposeb(int bus,int dev,int func,int reg,uint8_t val)196420c794b3Sgavinm cmi_pci_interposeb(int bus, int dev, int func, int reg, uint8_t val)
196520c794b3Sgavinm {
196620c794b3Sgavinm 	pcii_addent(bus, dev, func, reg, val, 1);
196720c794b3Sgavinm }
196820c794b3Sgavinm 
196920c794b3Sgavinm void
cmi_pci_interposew(int bus,int dev,int func,int reg,uint16_t val)197020c794b3Sgavinm cmi_pci_interposew(int bus, int dev, int func, int reg, uint16_t val)
197120c794b3Sgavinm {
197220c794b3Sgavinm 	pcii_addent(bus, dev, func, reg, val, 2);
197320c794b3Sgavinm }
197420c794b3Sgavinm 
197520c794b3Sgavinm void
cmi_pci_interposel(int bus,int dev,int func,int reg,uint32_t val)197620c794b3Sgavinm cmi_pci_interposel(int bus, int dev, int func, int reg, uint32_t val)
197720c794b3Sgavinm {
197820c794b3Sgavinm 	pcii_addent(bus, dev, func, reg, val, 4);
197920c794b3Sgavinm }
198020c794b3Sgavinm 
198120c794b3Sgavinm static void
cmi_pci_put_cmn(int bus,int dev,int func,int reg,int asz,ddi_acc_handle_t hdl,uint32_t val)198220c794b3Sgavinm cmi_pci_put_cmn(int bus, int dev, int func, int reg, int asz,
198320c794b3Sgavinm     ddi_acc_handle_t hdl, uint32_t val)
198420c794b3Sgavinm {
198520c794b3Sgavinm 	/*
198620c794b3Sgavinm 	 * If there is an interposed value for this register invalidate it.
198720c794b3Sgavinm 	 */
198820c794b3Sgavinm 	pcii_rment(bus, dev, func, reg, asz);
198920c794b3Sgavinm 
199020c794b3Sgavinm 	if (!(cmi_pcicfg_flags & CMI_PCICFG_FLAG_WR_HWOK))
199120c794b3Sgavinm 		return;
199220c794b3Sgavinm 
199320c794b3Sgavinm 	switch (asz) {
199420c794b3Sgavinm 	case 1:
199520c794b3Sgavinm 		if (hdl)
199620c794b3Sgavinm 			pci_config_put8(hdl, (off_t)reg, (uint8_t)val);
199720c794b3Sgavinm 		else
19985667185bSSrihari Venkatesan 			pci_cfgacc_put8(NULL, PCI_GETBDF(bus, dev, func), reg,
19995667185bSSrihari Venkatesan 			    (uint8_t)val);
200020c794b3Sgavinm 		break;
200120c794b3Sgavinm 
200220c794b3Sgavinm 	case 2:
200320c794b3Sgavinm 		if (hdl)
200420c794b3Sgavinm 			pci_config_put16(hdl, (off_t)reg, (uint16_t)val);
200520c794b3Sgavinm 		else
20065667185bSSrihari Venkatesan 			pci_cfgacc_put16(NULL, PCI_GETBDF(bus, dev, func), reg,
20075667185bSSrihari Venkatesan 			    (uint16_t)val);
200820c794b3Sgavinm 		break;
200920c794b3Sgavinm 
201020c794b3Sgavinm 	case 4:
201120c794b3Sgavinm 		if (hdl)
201220c794b3Sgavinm 			pci_config_put32(hdl, (off_t)reg, val);
201320c794b3Sgavinm 		else
20145667185bSSrihari Venkatesan 			pci_cfgacc_put32(NULL, PCI_GETBDF(bus, dev, func), reg,
20155667185bSSrihari Venkatesan 			    val);
201620c794b3Sgavinm 		break;
201720c794b3Sgavinm 
201820c794b3Sgavinm 	default:
201920c794b3Sgavinm 		break;
202020c794b3Sgavinm 	}
202120c794b3Sgavinm }
202220c794b3Sgavinm 
2023e4b86885SCheng Sean Ye void
cmi_pci_putb(int bus,int dev,int func,int reg,ddi_acc_handle_t hdl,uint8_t val)202420c794b3Sgavinm cmi_pci_putb(int bus, int dev, int func, int reg, ddi_acc_handle_t hdl,
202520c794b3Sgavinm     uint8_t val)
202620c794b3Sgavinm {
202720c794b3Sgavinm 	cmi_pci_put_cmn(bus, dev, func, reg, 1, hdl, val);
202820c794b3Sgavinm }
202920c794b3Sgavinm 
2030e4b86885SCheng Sean Ye void
cmi_pci_putw(int bus,int dev,int func,int reg,ddi_acc_handle_t hdl,uint16_t val)203120c794b3Sgavinm cmi_pci_putw(int bus, int dev, int func, int reg, ddi_acc_handle_t hdl,
203220c794b3Sgavinm     uint16_t val)
203320c794b3Sgavinm {
203420c794b3Sgavinm 	cmi_pci_put_cmn(bus, dev, func, reg, 2, hdl, val);
203520c794b3Sgavinm }
203620c794b3Sgavinm 
2037e4b86885SCheng Sean Ye void
cmi_pci_putl(int bus,int dev,int func,int reg,ddi_acc_handle_t hdl,uint32_t val)203820c794b3Sgavinm cmi_pci_putl(int bus, int dev, int func, int reg, ddi_acc_handle_t hdl,
203920c794b3Sgavinm     uint32_t val)
204020c794b3Sgavinm {
204120c794b3Sgavinm 	cmi_pci_put_cmn(bus, dev, func, reg, 4, hdl, val);
204220c794b3Sgavinm }
2043e4b86885SCheng Sean Ye 
2044*dd23d762SRobert Mustacchi cmi_errno_t
cmi_cache_ncaches(cmi_hdl_t hdl,uint32_t * ncache)2045*dd23d762SRobert Mustacchi cmi_cache_ncaches(cmi_hdl_t hdl, uint32_t *ncache)
2046*dd23d762SRobert Mustacchi {
2047*dd23d762SRobert Mustacchi 	return (HDLOPS(IMPLHDL(hdl))->cmio_ncache(IMPLHDL(hdl), ncache));
2048*dd23d762SRobert Mustacchi }
2049*dd23d762SRobert Mustacchi 
2050*dd23d762SRobert Mustacchi 
2051*dd23d762SRobert Mustacchi cmi_errno_t
cmi_cache_info(cmi_hdl_t hdl,uint32_t cno,x86_cache_t * cachep)2052*dd23d762SRobert Mustacchi cmi_cache_info(cmi_hdl_t hdl, uint32_t cno, x86_cache_t *cachep)
2053*dd23d762SRobert Mustacchi {
2054*dd23d762SRobert Mustacchi 	return (HDLOPS(IMPLHDL(hdl))->cmio_cache(IMPLHDL(hdl), cno, cachep));
2055*dd23d762SRobert Mustacchi }
2056*dd23d762SRobert Mustacchi 
2057e4b86885SCheng Sean Ye static const struct cmi_hdl_ops cmi_hdl_ops = {
2058e4b86885SCheng Sean Ye #ifdef __xpv
2059e4b86885SCheng Sean Ye 	/*
2060e4b86885SCheng Sean Ye 	 * CMI_HDL_SOLARIS_xVM_MCA - ops when we are an xVM dom0
2061e4b86885SCheng Sean Ye 	 */
2062e4b86885SCheng Sean Ye 	xpv_vendor,		/* cmio_vendor */
2063e4b86885SCheng Sean Ye 	xpv_vendorstr,		/* cmio_vendorstr */
2064e4b86885SCheng Sean Ye 	xpv_family,		/* cmio_family */
2065e4b86885SCheng Sean Ye 	xpv_model,		/* cmio_model */
2066e4b86885SCheng Sean Ye 	xpv_stepping,		/* cmio_stepping */
2067e4b86885SCheng Sean Ye 	xpv_chipid,		/* cmio_chipid */
20688031591dSSrihari Venkatesan 	xpv_procnodeid,		/* cmio_procnodeid */
2069e4b86885SCheng Sean Ye 	xpv_coreid,		/* cmio_coreid */
2070e4b86885SCheng Sean Ye 	xpv_strandid,		/* cmio_strandid */
20718031591dSSrihari Venkatesan 	xpv_procnodes_per_pkg,	/* cmio_procnodes_per_pkg */
2072074bb90dSTom Pothier 	xpv_strand_apicid,	/* cmio_strand_apicid */
2073e4b86885SCheng Sean Ye 	xpv_chiprev,		/* cmio_chiprev */
2074e4b86885SCheng Sean Ye 	xpv_chiprevstr,		/* cmio_chiprevstr */
2075e4b86885SCheng Sean Ye 	xpv_getsockettype,	/* cmio_getsockettype */
207689e921d5SKuriakose Kuruvilla 	xpv_getsocketstr,	/* cmio_getsocketstr */
20772a613b59SRobert Mustacchi 	xpv_chipsig,		/* cmio_chipsig */
2078*dd23d762SRobert Mustacchi 	xpv_ncache,		/* cmio_ncache */
2079*dd23d762SRobert Mustacchi 	xpv_cache,		/* cmio_cache */
2080e4b86885SCheng Sean Ye 	xpv_logical_id,		/* cmio_logical_id */
2081e4b86885SCheng Sean Ye 	NULL,			/* cmio_getcr4 */
2082e4b86885SCheng Sean Ye 	NULL,			/* cmio_setcr4 */
2083e4b86885SCheng Sean Ye 	xpv_rdmsr,		/* cmio_rdmsr */
2084e4b86885SCheng Sean Ye 	xpv_wrmsr,		/* cmio_wrmsr */
2085e4b86885SCheng Sean Ye 	xpv_msrinterpose,	/* cmio_msrinterpose */
2086e4b86885SCheng Sean Ye 	xpv_int,		/* cmio_int */
2087074bb90dSTom Pothier 	xpv_online,		/* cmio_online */
2088074bb90dSTom Pothier 	xpv_smbiosid,		/* cmio_smbiosid */
2089074bb90dSTom Pothier 	xpv_smb_chipid,		/* cmio_smb_chipid */
2090074bb90dSTom Pothier 	xpv_smb_bboard		/* cmio_smb_bboard */
2091e4b86885SCheng Sean Ye 
2092e4b86885SCheng Sean Ye #else	/* __xpv */
2093e4b86885SCheng Sean Ye 
2094e4b86885SCheng Sean Ye 	/*
2095e4b86885SCheng Sean Ye 	 * CMI_HDL_NATIVE - ops when apparently running on bare-metal
2096e4b86885SCheng Sean Ye 	 */
2097e4b86885SCheng Sean Ye 	ntv_vendor,		/* cmio_vendor */
2098e4b86885SCheng Sean Ye 	ntv_vendorstr,		/* cmio_vendorstr */
2099e4b86885SCheng Sean Ye 	ntv_family,		/* cmio_family */
2100e4b86885SCheng Sean Ye 	ntv_model,		/* cmio_model */
2101e4b86885SCheng Sean Ye 	ntv_stepping,		/* cmio_stepping */
2102e4b86885SCheng Sean Ye 	ntv_chipid,		/* cmio_chipid */
21038031591dSSrihari Venkatesan 	ntv_procnodeid,		/* cmio_procnodeid */
2104e4b86885SCheng Sean Ye 	ntv_coreid,		/* cmio_coreid */
2105e4b86885SCheng Sean Ye 	ntv_strandid,		/* cmio_strandid */
21068031591dSSrihari Venkatesan 	ntv_procnodes_per_pkg,	/* cmio_procnodes_per_pkg */
21078031591dSSrihari Venkatesan 	ntv_strand_apicid,	/* cmio_strand_apicid */
2108e4b86885SCheng Sean Ye 	ntv_chiprev,		/* cmio_chiprev */
2109e4b86885SCheng Sean Ye 	ntv_chiprevstr,		/* cmio_chiprevstr */
2110e4b86885SCheng Sean Ye 	ntv_getsockettype,	/* cmio_getsockettype */
211189e921d5SKuriakose Kuruvilla 	ntv_getsocketstr,	/* cmio_getsocketstr */
21122a613b59SRobert Mustacchi 	ntv_chipsig,		/* cmio_chipsig */
2113*dd23d762SRobert Mustacchi 	ntv_ncache,		/* cmio_ncache */
2114*dd23d762SRobert Mustacchi 	ntv_cache,		/* cmio_cache */
2115e4b86885SCheng Sean Ye 	ntv_logical_id,		/* cmio_logical_id */
2116e4b86885SCheng Sean Ye 	ntv_getcr4,		/* cmio_getcr4 */
2117e4b86885SCheng Sean Ye 	ntv_setcr4,		/* cmio_setcr4 */
2118e4b86885SCheng Sean Ye 	ntv_rdmsr,		/* cmio_rdmsr */
2119e4b86885SCheng Sean Ye 	ntv_wrmsr,		/* cmio_wrmsr */
2120e4b86885SCheng Sean Ye 	ntv_msrinterpose,	/* cmio_msrinterpose */
2121e4b86885SCheng Sean Ye 	ntv_int,		/* cmio_int */
2122074bb90dSTom Pothier 	ntv_online,		/* cmio_online */
2123074bb90dSTom Pothier 	ntv_smbiosid,		/* cmio_smbiosid */
2124074bb90dSTom Pothier 	ntv_smb_chipid,		/* cmio_smb_chipid */
2125074bb90dSTom Pothier 	ntv_smb_bboard		/* cmio_smb_bboard */
2126e4b86885SCheng Sean Ye #endif
2127e4b86885SCheng Sean Ye };
2128