cmi.c revision 4156fc34b973159b0334e05ae5ec19344487bdc0
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * CDDL HEADER START
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * The contents of this file are subject to the terms of the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Common Development and Distribution License (the "License").
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * You may not use this file except in compliance with the License.
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri *
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * or http://www.opensolaris.org/os/licensing.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * See the License for the specific language governing permissions
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * and limitations under the License.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * When distributing Covered Code, include this CDDL HEADER in each
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If applicable, add the following below this CDDL HEADER, with the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * fields enclosed by brackets "[]" replaced with your own identifying
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * information: Portions Copyright [yyyy] [name of copyright owner]
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CDDL HEADER END
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Use is subject to license terms.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#pragma ident "%Z%%M% %I% %E% SMI"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Public interface to routines implemented by CPU modules
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/x86_archext.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/cpu_module_impl.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/fm/util.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/reboot.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/modctl.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/param.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/cmn_err.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/systm.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/types.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define CPUMOD_SUBDIR "cpu"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define CPUMOD_PREFIX "cpu"
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define CMI_OPS(cpu) \
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (cpu)->cpu_m.mcpu_cmi->cmi_ops
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#define CMI_DATA(cpu) \
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (cpu)->cpu_m.mcpu_cmidata
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If cleared for debugging we will not attempt to load a model-specific
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * cpu module but will load the generic cpu module instead.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint cmi_force_generic = 0;
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota/*
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota * If cleared for debugging, we will suppress panicking on fatal hardware
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota * errors. This should *only* be used for debugging; it use can and will
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * cause data corruption if actual hardware errors are detected by the system.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint cmi_panic_on_uncorrectable_error = 1;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic cmi_t *cmi_list;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic kmutex_t cmi_load_lock;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_cpu_match(cpu_t *c1, cpu_t *c2)
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (cpuid_getfamily(c1) == cpuid_getfamily(c2) &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cpuid_getmodel(c1) == cpuid_getmodel(c2) &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cpuid_getstep(c1) == cpuid_getstep(c2) &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota strcmp(cpuid_getvendorstr(c1), cpuid_getvendorstr(c2)) == 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic cmi_t *
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otacmi_load_modctl(modctl_t *modp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota uintptr_t ops;
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota cmi_t *cmi;
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota ASSERT(MUTEX_HELD(&cmi_load_lock));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (cmi = cmi_list; cmi != NULL; cmi = cmi->cmi_next) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cmi->cmi_modp == modp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (cmi);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((ops = modlookup_by_modctl(modp, "_cmi_ops")) == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmn_err(CE_WARN, "CPU module %s is invalid: no _cmi_ops "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "found\n", modp->mod_modname);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Hold the module in memory. We call to CPU modules without using the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * stubs mechanism, so these modules must be manually held in memory.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * The mod_ref acts as if another loaded module has a dependency on us.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&mod_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modp->mod_ref++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&mod_lock);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi = kmem_zalloc(sizeof (cmi_t), KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi->cmi_ops = (const cmi_ops_t *)ops;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi->cmi_modp = modp;
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi->cmi_next = cmi_list;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi_list = cmi;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota return (cmi);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic cmi_t *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_load_module(cpu_t *cp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modctl_t *modp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi_t *cmi;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int i, modid;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t s[3];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Look to see if we've already got a module loaded for a CPU just
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * like this one. If we do, then we'll re-use it.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(MUTEX_HELD(&cmi_load_lock));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&cpu_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (i = 0; i < NCPU; i++) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cpu_t *cp2 = cpu[i];
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cp2 != NULL && cp2 != cp &&
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota cp2->cpu_m.mcpu_cmi != NULL && cmi_cpu_match(cp, cp2)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&cpu_lock);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota return (cp2->cpu_m.mcpu_cmi);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&cpu_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If we can't find a match, attempt to load the appropriate module.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If that also fails, try to load the generic CPU module.
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota s[0] = cpuid_getfamily(cp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota s[1] = cpuid_getmodel(cp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota s[2] = cpuid_getstep(cp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota modid = modload_qualified(CPUMOD_SUBDIR, CPUMOD_PREFIX,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cpuid_getvendorstr(cp), ".", s, sizeof (s) / sizeof (s[0]));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (modid == -1)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modid = modload(CPUMOD_SUBDIR, CPUMOD_PREFIX ".generic");
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (modid == -1)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota modp = mod_hold_by_id(modid);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota cmi = cmi_load_modctl(modp);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota mod_release_mod(modp);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota return (cmi);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic cmi_t *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_load_generic(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modctl_t *modp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi_t *cmi;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int modid;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((modid = modload(CPUMOD_SUBDIR, CPUMOD_PREFIX ".generic")) == -1)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota modp = mod_hold_by_id(modid);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi = cmi_load_modctl(modp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mod_release_mod(modp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (cmi);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Load a CPU module for the specified CPU, and then call its cmi_init routine.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If the module returns ENOTSUP, try using the generic CPU module instead.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * If all else fails, we return -1 and the caller will panic or halt.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_load(cpu_t *cp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int err = ENOENT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi_t *cmi;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota void *data;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&cmi_load_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!cmi_force_generic && (
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ((cmi = cmi_load_module(cp)) == NULL) ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ((err = cmi->cmi_ops->cmi_init(cp, &data)) != 0 &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota err != ENOTSUP))) {
d2b539e744e90927cf7a57df3475145c279d68f9agiri cmn_err(CE_WARN, "CPU module %s failed to init CPU %d: err=%d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi ? cmi->cmi_modp->mod_modname : "<>", cp->cpu_id, err);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&cmi_load_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((cmi_force_generic || err != 0) &&
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ((cmi = cmi_load_generic()) == NULL ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (err = cmi->cmi_ops->cmi_init(cp, &data)) != 0)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmn_err(CE_WARN, "CPU module %s failed to init CPU %d: err=%d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi ? cmi->cmi_modp->mod_modname : "<>", cp->cpu_id, err);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&cmi_load_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(cp->cpu_m.mcpu_cmi == NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cp->cpu_m.mcpu_cmi = cmi;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cp->cpu_m.mcpu_cmidata = data;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmi->cmi_refcnt++;
d2b539e744e90927cf7a57df3475145c279d68f9agiri mutex_exit(&cmi_load_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (boothowto & RB_VERBOSE) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota printf("cpuid %d: initialized cpumod: %s\n",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cp->cpu_id, cmi->cmi_modp->mod_modname);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_init(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cmi_load(CPU) < 0)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota panic("failed to load module for CPU %u", CPU->cpu_id);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_post_init(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota CMI_OPS(CPU)->cmi_post_init(CMI_DATA(CPU));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Called just once from start_other_cpus when all processors are started.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * This will not be called for each cpu, so the registered op must not
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * assume it is called as such.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_post_mpstartup(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota CMI_OPS(CPU)->cmi_post_mpstartup(CMI_DATA(CPU));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otavoid
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otacmi_faulted_enter(cpu_t *cp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota CMI_OPS(cp)->cmi_faulted_enter(CMI_DATA(cp));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_faulted_exit(cpu_t *cp)
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota{
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota CMI_OPS(cp)->cmi_faulted_exit(CMI_DATA(cp));
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota}
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_scrubber_enable(cpu_t *cp, uint64_t base, uint64_t ilen, int cscontig)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (CMI_OPS(cp)->cmi_scrubber_enable(CMI_DATA(cp), base, ilen,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cscontig));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_mca_init(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota CMI_OPS(CPU)->cmi_mca_init(CMI_DATA(CPU));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_mca_trap(struct regs *rp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (CMI_OPS(CPU)->cmi_mca_trap(CMI_DATA(CPU), rp)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cmi_panic_on_uncorrectable_error)
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota fm_panic("Unrecoverable Machine-Check Exception");
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota else
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmn_err(CE_WARN, "suppressing panic from fatal #mc");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_mca_inject(cmi_mca_regs_t *regs, uint_t nregs)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int err;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kpreempt_disable();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota err = CMI_OPS(CPU)->cmi_mca_inject(CMI_DATA(CPU), regs, nregs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kpreempt_enable();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (err);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otacmi_mca_poke(void)
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota CMI_OPS(CPU)->cmi_mca_poke(CMI_DATA(CPU));
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota}
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_mc_register(cpu_t *cp, const cmi_mc_ops_t *mcops, void *mcdata)
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota{
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota CMI_OPS(cp)->cmi_mc_register(CMI_DATA(cp), mcops, mcdata);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota}
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_mc_patounum(uint64_t pa, uint8_t valid_hi, uint8_t valid_lo, uint32_t synd,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int syndtype, mc_unum_t *up)
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota{
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota const struct cmi_mc_ops *mcops;
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota cpu_t *cp = CPU;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (CMI_OPS(cp) == NULL ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (mcops = CMI_OPS(cp)->cmi_mc_getops(CMI_DATA(cp))) == NULL)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1); /* not registered yet */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (mcops->cmi_mc_patounum(CMI_DATA(cp), pa, valid_hi, valid_lo,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota synd, syndtype, up));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otacmi_mc_unumtopa(mc_unum_t *up, nvlist_t *nvl, uint64_t *pap)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota const struct cmi_mc_ops *mcops;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cpu_t *cp = CPU;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (up != NULL && nvl != NULL)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1); /* only convert from one or the other form */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (CMI_OPS(cp) == NULL ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (mcops = CMI_OPS(cp)->cmi_mc_getops(CMI_DATA(cp))) == NULL)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-1); /* not registered yet */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (mcops->cmi_mc_unumtopa(CMI_DATA(cp), up, nvl, pap));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota