3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm/*
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * CDDL HEADER START
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm *
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * The contents of this file are subject to the terms of the
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * Common Development and Distribution License (the "License").
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * You may not use this file except in compliance with the License.
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm *
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * or http://www.opensolaris.org/os/licensing.
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * See the License for the specific language governing permissions
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * and limitations under the License.
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm *
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * When distributing Covered Code, include this CDDL HEADER in each
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * If applicable, add the following below this CDDL HEADER, with the
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * fields enclosed by brackets "[]" replaced with your own identifying
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * information: Portions Copyright [yyyy] [name of copyright owner]
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm *
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm * CDDL HEADER END
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm */
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Use is subject to license terms.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Public interface to routines implemented by CPU modules
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/types.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/atomic.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/x86_archext.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/cpu_module_impl.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/cpu_module_ms.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/fm/util.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/reboot.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/modctl.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/param.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/cmn_err.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/systm.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/fm/protocol.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/pcb.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/ontrap.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/psw.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/privregs.h>
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#include <sys/machsystm.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Set to force cmi_init to fail.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmint cmi_no_init = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Set to avoid MCA initialization.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmint cmi_no_mca_init = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm/*
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * If cleared for debugging we will not attempt to load a model-specific
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * cpu module but will load the generic cpu module instead.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm */
8a40a695ee676a322b094e9afe5375567bfb51e3gavinmint cmi_force_generic = 0;
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If cleared for debugging, we will suppress panicking on fatal hardware
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * errors. This should *only* be used for debugging; it use can and will
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * cause data corruption if actual hardware errors are detected by the system.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint cmi_panic_on_uncorrectable_error = 1;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost/*
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * Set to indicate whether we are able to enable cmci interrupt.
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frostint cmi_enable_cmci = 0;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Subdirectory (relative to the module search path) in which we will
20c794b39650d115e17a15983b6b82e46238cf45gavinm * look for cpu modules.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CPUMOD_SUBDIR "cpu"
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * CPU modules have a filenames such as "cpu.AuthenticAMD.15" and
20c794b39650d115e17a15983b6b82e46238cf45gavinm * "cpu.generic" - the "cpu" prefix is specified by the following.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CPUMOD_PREFIX "cpu"
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Structure used to keep track of cpu modules we have loaded and their ops
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmtypedef struct cmi {
20c794b39650d115e17a15983b6b82e46238cf45gavinm struct cmi *cmi_next;
20c794b39650d115e17a15983b6b82e46238cf45gavinm struct cmi *cmi_prev;
20c794b39650d115e17a15983b6b82e46238cf45gavinm const cmi_ops_t *cmi_ops;
20c794b39650d115e17a15983b6b82e46238cf45gavinm struct modctl *cmi_modp;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint_t cmi_refcnt;
20c794b39650d115e17a15983b6b82e46238cf45gavinm} cmi_t;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic cmi_t *cmi_list;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic const cmi_mc_ops_t *cmi_mc_global_ops;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void *cmi_mc_global_data;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic kmutex_t cmi_load_lock;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Functions we need from cmi_hw.c that are not part of the cpu_module.h
20c794b39650d115e17a15983b6b82e46238cf45gavinm * interface.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeextern cmi_hdl_t cmi_hdl_create(enum cmi_hdl_class, uint_t, uint_t, uint_t);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuextern void cmi_hdl_destroy(cmi_hdl_t ophdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinmextern void cmi_hdl_setcmi(cmi_hdl_t, void *, void *);
20c794b39650d115e17a15983b6b82e46238cf45gavinmextern void *cmi_hdl_getcmi(cmi_hdl_t);
20c794b39650d115e17a15983b6b82e46238cf45gavinmextern void cmi_hdl_setmc(cmi_hdl_t, const struct cmi_mc_ops *, void *);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeextern void cmi_hdl_inj_begin(cmi_hdl_t);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yeextern void cmi_hdl_inj_end(cmi_hdl_t);
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothierextern void cmi_read_smbios(cmi_hdl_t);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define HDL2CMI(hdl) cmi_hdl_getcmi(hdl)
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_OPS(cmi) (cmi)->cmi_ops
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_OP_PRESENT(cmi, op) ((cmi) && CMI_OPS(cmi)->op != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_MATCH_VENDOR 0 /* Just match on vendor */
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_MATCH_FAMILY 1 /* Match down to family */
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_MATCH_MODEL 2 /* Match down to model */
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_MATCH_STEPPING 3 /* Match down to stepping */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_link(cmi_t *cmi)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(MUTEX_HELD(&cmi_load_lock));
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_prev = NULL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_next = cmi_list;
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_list != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_list->cmi_prev = cmi;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_list = cmi;
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_unlink(cmi_t *cmi)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(MUTEX_HELD(&cmi_load_lock));
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(cmi->cmi_refcnt == 0);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi->cmi_prev != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_prev = cmi->cmi_next;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi->cmi_next != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_next->cmi_prev = cmi->cmi_prev;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_list == cmi)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_list = cmi->cmi_next;
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Hold the module in memory. We call to CPU modules without using the
20c794b39650d115e17a15983b6b82e46238cf45gavinm * stubs mechanism, so these modules must be manually held in memory.
20c794b39650d115e17a15983b6b82e46238cf45gavinm * The mod_ref acts as if another loaded module has a dependency on us.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_hold(cmi_t *cmi)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(MUTEX_HELD(&cmi_load_lock));
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_enter(&mod_lock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_modp->mod_ref++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_exit(&mod_lock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_refcnt++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_rele(cmi_t *cmi)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(MUTEX_HELD(&cmi_load_lock));
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_enter(&mod_lock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_modp->mod_ref--;
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_exit(&mod_lock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (--cmi->cmi_refcnt == 0) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_unlink(cmi);
20c794b39650d115e17a15983b6b82e46238cf45gavinm kmem_free(cmi, sizeof (cmi_t));
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic cmi_ops_t *
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_getops(modctl_t *modp)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_ops_t *ops;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((ops = (cmi_ops_t *)modlookup_by_modctl(modp, "_cmi_ops")) ==
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "cpu module '%s' is invalid: no _cmi_ops "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "found", modp->mod_modname);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (ops->cmi_init == NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "cpu module '%s' is invalid: no cmi_init "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "entry point", modp->mod_modname);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (ops);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic cmi_t *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindicmi_load_modctl(modctl_t *modp)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_ops_t *ops;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uintptr_t ver;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi cmi_t *cmi;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_api_ver_t apiver;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ASSERT(MUTEX_HELD(&cmi_load_lock));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (cmi = cmi_list; cmi != NULL; cmi = cmi->cmi_next) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (cmi->cmi_modp == modp)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (cmi);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((ver = modlookup_by_modctl(modp, "_cmi_api_version")) == NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Apparently a cpu module before versioning was introduced -
20c794b39650d115e17a15983b6b82e46238cf45gavinm * we call this version 0.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm apiver = CMI_API_VERSION_0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm apiver = *((cmi_api_ver_t *)ver);
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!CMI_API_VERSION_CHKMAGIC(apiver)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "cpu module '%s' is invalid: "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "_cmi_api_version 0x%x has bad magic",
20c794b39650d115e17a15983b6b82e46238cf45gavinm modp->mod_modname, apiver);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (apiver != CMI_API_VERSION) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "cpu module '%s' has API version %d, "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "kernel requires API version %d", modp->mod_modname,
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_API_VERSION_TOPRINT(apiver),
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_API_VERSION_TOPRINT(CMI_API_VERSION));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((ops = cmi_getops(modp)) == NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi = kmem_zalloc(sizeof (*cmi), KM_SLEEP);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_ops = ops;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi cmi->cmi_modp = modp;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_link(cmi);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (cmi);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic int
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_cpu_match(cmi_hdl_t hdl1, cmi_hdl_t hdl2, int match)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (match >= CMI_MATCH_VENDOR &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_vendor(hdl1) != cmi_hdl_vendor(hdl2))
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (0);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (match >= CMI_MATCH_FAMILY &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_family(hdl1) != cmi_hdl_family(hdl2))
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (0);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (match >= CMI_MATCH_MODEL &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_model(hdl1) != cmi_hdl_model(hdl2))
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (0);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (match >= CMI_MATCH_STEPPING &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_stepping(hdl1) != cmi_hdl_stepping(hdl2))
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (0);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (1);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic int
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_search_list_cb(cmi_hdl_t whdl, void *arg1, void *arg2, void *arg3)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t thdl = (cmi_hdl_t)arg1;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int match = *((int *)arg2);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t *rsltp = (cmi_hdl_t *)arg3;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_cpu_match(thdl, whdl, match)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_hold(whdl); /* short-term hold */
20c794b39650d115e17a15983b6b82e46238cf45gavinm *rsltp = whdl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMI_HDL_WALK_DONE);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMI_HDL_WALK_NEXT);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic cmi_t *
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_search_list(cmi_hdl_t hdl, int match)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t dhdl = NULL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi = NULL;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ASSERT(MUTEX_HELD(&cmi_load_lock));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_walk(cmi_search_list_cb, (void *)hdl, (void *)&match, &dhdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (dhdl) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi = HDL2CMI(dhdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(dhdl); /* held in cmi_search_list_cb */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (cmi);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic cmi_t *
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_load_module(cmi_hdl_t hdl, int match, int *chosenp)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm modctl_t *modp;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int modid;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint_t s[3];
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(MUTEX_HELD(&cmi_load_lock));
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(match == CMI_MATCH_STEPPING || match == CMI_MATCH_MODEL ||
20c794b39650d115e17a15983b6b82e46238cf45gavinm match == CMI_MATCH_FAMILY || match == CMI_MATCH_VENDOR);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Have we already loaded a module for a cpu with the same
20c794b39650d115e17a15983b6b82e46238cf45gavinm * vendor/family/model/stepping?
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((cmi = cmi_search_list(hdl, match)) != NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hold(cmi);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (cmi);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm s[0] = cmi_hdl_family(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm s[1] = cmi_hdl_model(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm s[2] = cmi_hdl_stepping(hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi modid = modload_qualified(CPUMOD_SUBDIR, CPUMOD_PREFIX,
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_vendorstr(hdl), ".", s, match, chosenp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (modid == -1)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi modp = mod_hold_by_id(modid);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi cmi = cmi_load_modctl(modp);
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hold(cmi);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mod_release_mod(modp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (cmi);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Try to load a cpu module with specific support for this chip type.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic cmi_t *
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_load_specific(cmi_hdl_t hdl, void **datap)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int err;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int i;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(MUTEX_HELD(&cmi_load_lock));
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = CMI_MATCH_STEPPING; i >= CMI_MATCH_VENDOR; i--) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm int suffixlevel;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((cmi = cmi_load_module(hdl, i, &suffixlevel)) == NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * A module has loaded and has a _cmi_ops structure, and the
20c794b39650d115e17a15983b6b82e46238cf45gavinm * module has been held for this instance. Call its cmi_init
20c794b39650d115e17a15983b6b82e46238cf45gavinm * entry point - we expect success (0) or ENOTSUP.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((err = cmi->cmi_ops->cmi_init(hdl, datap)) == 0) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (boothowto & RB_VERBOSE) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm printf("initialized cpu module '%s' on "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "chip %d core %d strand %d\n",
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_modp->mod_modname,
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_chipid(hdl), cmi_hdl_coreid(hdl),
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_strandid(hdl));
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (cmi);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else if (err != ENOTSUP) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "failed to init cpu module '%s' on "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "chip %d core %d strand %d: err=%d\n",
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi->cmi_modp->mod_modname,
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_chipid(hdl), cmi_hdl_coreid(hdl),
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_strandid(hdl), err);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * The module failed or declined to init, so release
20c794b39650d115e17a15983b6b82e46238cf45gavinm * it and update i to be equal to the number
20c794b39650d115e17a15983b6b82e46238cf45gavinm * of suffices actually used in the last module path.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_rele(cmi);
20c794b39650d115e17a15983b6b82e46238cf45gavinm i = suffixlevel;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Load the generic IA32 MCA cpu module, which may still supplement
20c794b39650d115e17a15983b6b82e46238cf45gavinm * itself with model-specific support through cpu model-specific modules.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic cmi_t *
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_load_generic(cmi_hdl_t hdl, void **datap)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi modctl_t *modp;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi cmi_t *cmi;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int modid;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int err;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(MUTEX_HELD(&cmi_load_lock));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((modid = modload(CPUMOD_SUBDIR, CPUMOD_PREFIX ".generic")) == -1)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi modp = mod_hold_by_id(modid);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi cmi = cmi_load_modctl(modp);
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hold(cmi);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mod_release_mod(modp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi == NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((err = cmi->cmi_ops->cmi_init(hdl, datap)) != 0) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (err != ENOTSUP)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, CPUMOD_PREFIX ".generic failed to "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "init: err=%d", err);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_rele(cmi);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (cmi);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_hdl_t
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_init(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye uint_t strandid)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi = NULL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t hdl;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi void *data;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_no_init) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_no_mca_init = 1;
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mutex_enter(&cmi_load_lock);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if ((hdl = cmi_hdl_create(class, chipid, coreid, strandid)) == NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mutex_exit(&cmi_load_lock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "There will be no MCA support on chip %d "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "core %d strand %d (cmi_hdl_create returned NULL)\n",
20c794b39650d115e17a15983b6b82e46238cf45gavinm chipid, coreid, strandid);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!cmi_force_generic)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi = cmi_load_specific(hdl, &data);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi == NULL && (cmi = cmi_load_generic(hdl, &data)) == NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "There will be no MCA support on chip %d "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "core %d strand %d\n", chipid, coreid, strandid);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mutex_exit(&cmi_load_lock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_setcmi(hdl, cmi, data);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm cms_init(hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier cmi_read_smbios(hdl);
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_exit(&cmi_load_lock);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * cmi_fini is called on DR deconfigure of a cpu resource.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * It should not be called at simple offline of a cpu.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_fini(cmi_hdl_t hdl)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi = HDL2CMI(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cms_present(hdl))
20c794b39650d115e17a15983b6b82e46238cf45gavinm cms_fini(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (CMI_OP_PRESENT(cmi, cmi_fini))
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_OPS(cmi)->cmi_fini(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmi_hdl_destroy(hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * cmi_post_startup is called from post_startup for the boot cpu only (no
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * other cpus are started yet).
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_post_startup(void)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t hdl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_no_mca_init != 0 ||
20c794b39650d115e17a15983b6b82e46238cf45gavinm (hdl = cmi_hdl_any()) == NULL) /* short-term hold */
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi = HDL2CMI(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (CMI_OP_PRESENT(cmi, cmi_post_startup))
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_OPS(cmi)->cmi_post_startup(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm/*
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Called just once from start_other_cpus when all processors are started.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * This will not be called for each cpu, so the registered op must not
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * assume it is called as such. We are not necessarily executing on
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * the boot cpu.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm */
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinmvoid
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinmcmi_post_mpstartup(void)
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t hdl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_no_mca_init != 0 ||
20c794b39650d115e17a15983b6b82e46238cf45gavinm (hdl = cmi_hdl_any()) == NULL) /* short-term hold */
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi = HDL2CMI(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (CMI_OP_PRESENT(cmi, cmi_post_mpstartup))
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_OPS(cmi)->cmi_post_mpstartup(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmvoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_faulted_enter(cmi_hdl_t hdl)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi = HDL2CMI(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_no_mca_init != 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (CMI_OP_PRESENT(cmi, cmi_faulted_enter))
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_OPS(cmi)->cmi_faulted_enter(hdl);
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm}
3ad553a7dabf3c8bcb69dd1ceeb13938fa526aedgavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_faulted_exit(cmi_hdl_t hdl)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi = HDL2CMI(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_no_mca_init != 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (CMI_OP_PRESENT(cmi, cmi_faulted_exit))
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_OPS(cmi)->cmi_faulted_exit(hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_mca_init(cmi_hdl_t hdl)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_no_mca_init != 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi = HDL2CMI(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (CMI_OP_PRESENT(cmi, cmi_mca_init))
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_OPS(cmi)->cmi_mca_init(hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_RESPONSE_PANIC 0x0 /* panic must have value 0 */
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_RESPONSE_NONE 0x1
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_RESPONSE_CKILL 0x2
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_RESPONSE_REBOOT 0x3 /* not implemented */
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_RESPONSE_ONTRAP_PROT 0x4
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define CMI_RESPONSE_LOFAULT_PROT 0x5
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Return 0 if we will panic in response to this machine check, otherwise
20c794b39650d115e17a15983b6b82e46238cf45gavinm * non-zero. If the caller is cmi_mca_trap in this file then the nonzero
20c794b39650d115e17a15983b6b82e46238cf45gavinm * return values are to be interpreted from CMI_RESPONSE_* above.
20c794b39650d115e17a15983b6b82e46238cf45gavinm *
20c794b39650d115e17a15983b6b82e46238cf45gavinm * This function must just return what will be done without actually
20c794b39650d115e17a15983b6b82e46238cf45gavinm * doing anything; this includes not changing the regs.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_mce_response(struct regs *rp, uint64_t disp)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm int panicrsp = cmi_panic_on_uncorrectable_error ? CMI_RESPONSE_PANIC :
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_RESPONSE_NONE;
20c794b39650d115e17a15983b6b82e46238cf45gavinm on_trap_data_t *otp;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm ASSERT(rp != NULL); /* don't call for polling, only on #MC */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * If no bits are set in the disposition then there is nothing to
20c794b39650d115e17a15983b6b82e46238cf45gavinm * worry about and we do not need to trampoline to ontrap or
20c794b39650d115e17a15983b6b82e46238cf45gavinm * lofault handlers.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (disp == 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMI_RESPONSE_NONE);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Unconstrained errors cannot be forgiven, even by ontrap or
20c794b39650d115e17a15983b6b82e46238cf45gavinm * lofault protection. The data is not poisoned and may not
20c794b39650d115e17a15983b6b82e46238cf45gavinm * even belong to the trapped context - eg a writeback of
20c794b39650d115e17a15983b6b82e46238cf45gavinm * data that is found to be bad.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (disp & CMI_ERRDISP_UC_UNCONSTRAINED)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (panicrsp);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * ontrap OT_DATA_EC and lofault protection forgive any disposition
20c794b39650d115e17a15983b6b82e46238cf45gavinm * other than unconstrained, even those normally forced fatal.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((otp = curthread->t_ontrap) != NULL && otp->ot_prot & OT_DATA_EC)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMI_RESPONSE_ONTRAP_PROT);
20c794b39650d115e17a15983b6b82e46238cf45gavinm else if (curthread->t_lofault)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMI_RESPONSE_LOFAULT_PROT);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Forced-fatal errors are terminal even in user mode.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (disp & CMI_ERRDISP_FORCEFATAL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (panicrsp);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * If the trapped context is corrupt or we have no instruction pointer
20c794b39650d115e17a15983b6b82e46238cf45gavinm * to resume at (and aren't trampolining to a fault handler)
20c794b39650d115e17a15983b6b82e46238cf45gavinm * then in the kernel case we must panic and in usermode we
20c794b39650d115e17a15983b6b82e46238cf45gavinm * kill the affected contract.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (disp & (CMI_ERRDISP_CURCTXBAD | CMI_ERRDISP_RIPV_INVALID))
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (USERMODE(rp->r_cs) ? CMI_RESPONSE_CKILL : panicrsp);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Anything else is harmless
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMI_RESPONSE_NONE);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinmint cma_mca_trap_panic_suppressed = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_mca_panic(void)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_panic_on_uncorrectable_error) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_panic("Unrecoverable Machine-Check Exception");
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "suppressing panic from fatal #mc");
20c794b39650d115e17a15983b6b82e46238cf45gavinm cma_mca_trap_panic_suppressed++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmint cma_mca_trap_contract_kills = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinmint cma_mca_trap_ontrap_forgiven = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinmint cma_mca_trap_lofault_forgiven = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Native #MC handler - we branch to here from mcetrap
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindicmi_mca_trap(struct regs *rp)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm#ifndef __xpv
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t hdl = NULL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t disp;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int s;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_no_mca_init != 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * This function can call cmn_err, and the cpu module cmi_mca_trap
20c794b39650d115e17a15983b6b82e46238cf45gavinm * entry point may also elect to call cmn_err (e.g., if it can't
20c794b39650d115e17a15983b6b82e46238cf45gavinm * log the error onto an errorq, say very early in boot).
20c794b39650d115e17a15983b6b82e46238cf45gavinm * We need to let cprintf know that we must not block.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm s = spl8();
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((hdl = cmi_hdl_lookup(CMI_HDL_NATIVE, cmi_ntv_hwchipid(CPU),
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_ntv_hwcoreid(CPU), cmi_ntv_hwstrandid(CPU))) == NULL ||
20c794b39650d115e17a15983b6b82e46238cf45gavinm (cmi = HDL2CMI(hdl)) == NULL ||
20c794b39650d115e17a15983b6b82e46238cf45gavinm !CMI_OP_PRESENT(cmi, cmi_mca_trap)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "#MC exception on cpuid %d: %s",
20c794b39650d115e17a15983b6b82e46238cf45gavinm CPU->cpu_id,
20c794b39650d115e17a15983b6b82e46238cf45gavinm hdl ? "handle lookup ok but no #MC handler found" :
20c794b39650d115e17a15983b6b82e46238cf45gavinm "handle lookup failed");
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (hdl != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm splx(s);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm disp = CMI_OPS(cmi)->cmi_mca_trap(hdl, rp);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm switch (cmi_mce_response(rp, disp)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm default:
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "Invalid response from cmi_mce_response");
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*FALLTHRU*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm case CMI_RESPONSE_PANIC:
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_mca_panic();
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm case CMI_RESPONSE_NONE:
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm case CMI_RESPONSE_CKILL:
20c794b39650d115e17a15983b6b82e46238cf45gavinm ttolwp(curthread)->lwp_pcb.pcb_flags |= ASYNC_HWERR;
20c794b39650d115e17a15983b6b82e46238cf45gavinm aston(curthread);
20c794b39650d115e17a15983b6b82e46238cf45gavinm cma_mca_trap_contract_kills++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm case CMI_RESPONSE_ONTRAP_PROT: {
20c794b39650d115e17a15983b6b82e46238cf45gavinm on_trap_data_t *otp = curthread->t_ontrap;
20c794b39650d115e17a15983b6b82e46238cf45gavinm otp->ot_trap = OT_DATA_EC;
20c794b39650d115e17a15983b6b82e46238cf45gavinm rp->r_pc = otp->ot_trampoline;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cma_mca_trap_ontrap_forgiven++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm case CMI_RESPONSE_LOFAULT_PROT:
20c794b39650d115e17a15983b6b82e46238cf45gavinm rp->r_r0 = EFAULT;
20c794b39650d115e17a15983b6b82e46238cf45gavinm rp->r_pc = curthread->t_lofault;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cma_mca_trap_lofault_forgiven++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm splx(s);
20c794b39650d115e17a15983b6b82e46238cf45gavinm#endif /* __xpv */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_hdl_poke(cmi_hdl_t hdl)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi = HDL2CMI(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!CMI_OP_PRESENT(cmi, cmi_hdl_poke))
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_OPS(cmi)->cmi_hdl_poke(hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frostvoid
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frostcmi_cmci_trap()
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost{
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmi_hdl_t hdl = NULL;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmi_t *cmi;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (cmi_no_mca_init != 0)
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost return;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if ((hdl = cmi_hdl_lookup(CMI_HDL_NATIVE, cmi_ntv_hwchipid(CPU),
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmi_ntv_hwcoreid(CPU), cmi_ntv_hwstrandid(CPU))) == NULL ||
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost (cmi = HDL2CMI(hdl)) == NULL ||
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost !CMI_OP_PRESENT(cmi, cmi_cmci_trap)) {
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmn_err(CE_WARN, "CMCI interrupt on cpuid %d: %s",
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost CPU->cpu_id,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost hdl ? "handle lookup ok but no CMCI handler found" :
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost "handle lookup failed");
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (hdl != NULL)
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmi_hdl_rele(hdl);
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost return;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost }
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost CMI_OPS(cmi)->cmi_cmci_trap(hdl);
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmi_hdl_rele(hdl);
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif /* __xpv */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_mc_register(cmi_hdl_t hdl, const cmi_mc_ops_t *mcops, void *mcdata)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!cmi_no_mca_init)
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_setmc(hdl, mcops, mcdata);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
a31148363f598def767ac48c5d82e1572e44b935Gerry Liucmi_errno_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liucmi_mc_register_global(const cmi_mc_ops_t *mcops, void *mcdata)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!cmi_no_mca_init) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmi_mc_global_ops != NULL || cmi_mc_global_data != NULL ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mcops == NULL || mcops->cmi_mc_patounum == NULL ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mcops->cmi_mc_unumtopa == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (CMIERR_UNKNOWN);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmi_mc_global_data = mcdata;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmi_mc_global_ops = mcops;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (CMI_SUCCESS);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yevoid
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yecmi_mc_sw_memscrub_disable(void)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye memscrub_disable();
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_errno_t
4156fc34b973159b0334e05ae5ec19344487bdc0gavinmcmi_mc_patounum(uint64_t pa, uint8_t valid_hi, uint8_t valid_lo, uint32_t synd,
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm int syndtype, mc_unum_t *up)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const struct cmi_mc_ops *mcops;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t hdl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_errno_t rv;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmi_no_mca_init)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (CMIERR_MC_ABSENT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmi_mc_global_ops != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmi_mc_global_ops->cmi_mc_patounum == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (CMIERR_MC_NOTSUP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (cmi_mc_global_ops->cmi_mc_patounum(cmi_mc_global_data,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pa, valid_hi, valid_lo, synd, syndtype, up));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((hdl = cmi_hdl_any()) == NULL) /* short-term hold */
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMIERR_MC_ABSENT);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((mcops = cmi_hdl_getmcops(hdl)) == NULL ||
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcops->cmi_mc_patounum == NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMIERR_MC_NOTSUP);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm rv = mcops->cmi_mc_patounum(cmi_hdl_getmcdata(hdl), pa, valid_hi,
20c794b39650d115e17a15983b6b82e46238cf45gavinm valid_lo, synd, syndtype, up);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (rv);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_errno_t
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindicmi_mc_unumtopa(mc_unum_t *up, nvlist_t *nvl, uint64_t *pap)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const struct cmi_mc_ops *mcops;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t hdl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_errno_t rv;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye nvlist_t *hcsp;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (up != NULL && nvl != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMIERR_API); /* convert from just one form */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmi_no_mca_init)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (CMIERR_MC_ABSENT);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmi_mc_global_ops != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmi_mc_global_ops->cmi_mc_unumtopa == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (CMIERR_MC_NOTSUP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (cmi_mc_global_ops->cmi_mc_unumtopa(cmi_mc_global_data,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu up, nvl, pap));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((hdl = cmi_hdl_any()) == NULL) /* short-term hold */
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMIERR_MC_ABSENT);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((mcops = cmi_hdl_getmcops(hdl)) == NULL ||
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcops->cmi_mc_unumtopa == NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (nvl != NULL && nvlist_lookup_nvlist(nvl,
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye FM_FMRI_HC_SPECIFIC, &hcsp) == 0 &&
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye (nvlist_lookup_uint64(hcsp,
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye "asru-" FM_FMRI_HC_SPECIFIC_PHYSADDR, pap) == 0 ||
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye nvlist_lookup_uint64(hcsp, FM_FMRI_HC_SPECIFIC_PHYSADDR,
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye pap) == 0)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMIERR_MC_PARTIALUNUMTOPA);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (mcops && mcops->cmi_mc_unumtopa == NULL ?
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMIERR_MC_NOTSUP : CMIERR_MC_ABSENT);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm rv = mcops->cmi_mc_unumtopa(cmi_hdl_getmcdata(hdl), up, nvl, pap);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_rele(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (rv);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmvoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_mc_logout(cmi_hdl_t hdl, boolean_t ismc, boolean_t sync)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm const struct cmi_mc_ops *mcops;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmi_no_mca_init)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cmi_mc_global_ops != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mcops = cmi_mc_global_ops;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mcops = cmi_hdl_getmcops(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mcops != NULL && mcops->cmi_mc_logout != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcops->cmi_mc_logout(hdl, ismc, sync);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_errno_t
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_hdl_msrinject(cmi_hdl_t hdl, cmi_mca_regs_t *regs, uint_t nregs,
20c794b39650d115e17a15983b6b82e46238cf45gavinm int force)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_t *cmi = cmi_hdl_getcmi(hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye cmi_errno_t rc;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!CMI_OP_PRESENT(cmi, cmi_msrinject))
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (CMIERR_NOTSUP);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye cmi_hdl_inj_begin(hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye rc = CMI_OPS(cmi)->cmi_msrinject(hdl, regs, nregs, force);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye cmi_hdl_inj_end(hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return (rc);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmboolean_t
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_panic_on_ue(void)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (cmi_panic_on_uncorrectable_error ? B_TRUE : B_FALSE);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yevoid
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yecmi_panic_callback(void)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye{
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye cmi_hdl_t hdl;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye cmi_t *cmi;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (cmi_no_mca_init || (hdl = cmi_hdl_any()) == NULL)
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye return;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye cmi = cmi_hdl_getcmi(hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (CMI_OP_PRESENT(cmi, cmi_panic_callback))
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye CMI_OPS(cmi)->cmi_panic_callback();
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye cmi_hdl_rele(hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye}