7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER START
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The contents of this file are subject to the terms of the
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Common Development and Distribution License (the "License").
20c794b39650d115e17a15983b6b82e46238cf45gavinm * You may not use this file except in compliance with the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * or http://www.opensolaris.org/os/licensing.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * See the License for the specific language governing permissions
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and limitations under the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * When distributing Covered Code, include this CDDL HEADER in each
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If applicable, add the following below this CDDL HEADER, with the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * fields enclosed by brackets "[]" replaced with your own identifying
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * information: Portions Copyright [yyyy] [name of copyright owner]
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER END
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
c84b7bbef5ecc2a27799422588073deefd9db715Adrian Frost * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Copyright (c) 2010, Intel Corporation.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * All rights reserved.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/mca_x86.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/cpu_module_impl.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/cpu_module_ms.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/cmn_err.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/cpuvar.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/pghw.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/x86_archext.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/sysmacros.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/regset.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/privregs.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/systm.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/types.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/log.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/psw.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/fm/protocol.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/fm/util.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/errorq.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/mca_x86.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/fm/cpu/GMCA.h>
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier#include <sys/fm/smb/fmsmb.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/sysevent.h>
20c794b39650d115e17a15983b6b82e46238cf45gavinm#include <sys/ontrap.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "gcpu.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothierextern int x86gentopo_legacy; /* x86 generic topology support */
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesanstatic uint_t gcpu_force_addr_in_payload = 0;
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm/*
8396cacd0dc6d73fcfe4015be866d6af0e39a4f3gavinm * Clear to log telemetry found at initialization. While processor docs
8396cacd0dc6d73fcfe4015be866d6af0e39a4f3gavinm * say you should process this telemetry on all but Intel family 0x6
8396cacd0dc6d73fcfe4015be866d6af0e39a4f3gavinm * there are way too many exceptions and we want to avoid bogus
8396cacd0dc6d73fcfe4015be866d6af0e39a4f3gavinm * diagnoses.
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm */
8396cacd0dc6d73fcfe4015be866d6af0e39a4f3gavinmint gcpu_suppress_log_on_init = 1;
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * gcpu_mca_stack_flag is a debug assist option to capture a stack trace at
20c794b39650d115e17a15983b6b82e46238cf45gavinm * error logout time. The stack will be included in the ereport if the
20c794b39650d115e17a15983b6b82e46238cf45gavinm * error type selects stack inclusion, or in all cases if
20c794b39650d115e17a15983b6b82e46238cf45gavinm * gcpu_mca_stack_ereport_include is nonzero.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmint gcpu_mca_stack_flag = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinmint gcpu_mca_stack_ereport_include = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * The number of times to re-read MCA telemetry to try to obtain a
20c794b39650d115e17a15983b6b82e46238cf45gavinm * consistent snapshot if we find it to be changing under our feet.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
20c794b39650d115e17a15983b6b82e46238cf45gavinmint gcpu_mca_telemetry_retries = 5;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frostint gcpu_mca_cmci_throttling_threshold = 10;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frostint gcpu_mca_cmci_reenable_threshold = 1000;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic gcpu_error_disp_t gcpu_errtypes[] = {
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Unclassified
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_UNCLASSIFIED,
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMMON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_UNCLASSIFIED_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_UNCLASSIFIED_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Microcode ROM Parity Error
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_MC_CODE_PARITY,
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMMON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_MC_CODE_PARITY_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_MC_CODE_PARITY_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * External - BINIT# from another processor during power-on config
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_EXTERNAL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMMON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_EXTERNAL_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_EXTERNAL_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Functional redundancy check master/slave error
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_FRC,
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMMON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_FRC_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_FRC_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /*
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * Internal parity error
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost {
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost FM_EREPORT_CPU_GENERIC_INTERNAL_PARITY,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost NULL,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost FM_EREPORT_PAYLOAD_FLAGS_COMMON,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost MCAX86_SIMPLE_INTERNAL_PARITY_MASKON,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost MCAX86_SIMPLE_INTERNAL_PARITY_MASKOFF
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost },
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Internal timer error
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_INTERNAL_TIMER,
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMMON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_INTERNAL_TIMER_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_INTERNAL_TIMER_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Internal unclassified
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_INTERNAL_UNCLASS,
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMMON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_INTERNAL_UNCLASS_MASK_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_SIMPLE_INTERNAL_UNCLASS_MASK_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Compound error codes - generic memory hierarchy
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_GENMEMHIER,
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMMON, /* yes, no compound name */
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_COMPOUND_GENERIC_MEMHIER_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_COMPOUND_GENERIC_MEMHIER_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Compound error codes - TLB errors
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_TLB,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "%1$s" "TLB" "%2$s" "_ERR",
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMPOUND_ERR,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_COMPOUND_TLB_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_COMPOUND_TLB_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Compound error codes - memory hierarchy
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_MEMHIER,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "%1$s" "CACHE" "%2$s" "_" "%3$s" "_ERR",
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMPOUND_ERR,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_COMPOUND_MEMHIER_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_COMPOUND_MEMHIER_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Compound error codes - bus and interconnect errors
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_BUS_INTERCONNECT,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "BUS" "%2$s" "_" "%4$s" "_" "%3$s" "_" "%5$s" "_" "%6$s" "_ERR",
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMPOUND_ERR,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_COMPOUND_BUS_INTERCONNECT_MASKON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_COMPOUND_BUS_INTERCONNECT_MASKOFF
20c794b39650d115e17a15983b6b82e46238cf45gavinm },
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /*
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * Compound error codes - memory controller errors
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost {
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost FM_EREPORT_CPU_GENERIC_MEMORY_CONTROLLER,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost "MC" "_" "%8$s" "_" "%9$s" "_ERR",
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost FM_EREPORT_PAYLOAD_FLAGS_COMPOUND_ERR,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost MCAX86_COMPOUND_MEMORY_CONTROLLER_MASKON,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost MCAX86_COMPOUND_MEMORY_CONTROLLER_MASKOFF
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost },
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi};
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic gcpu_error_disp_t gcpu_unknown = {
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_CPU_GENERIC_UNKNOWN,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "UNKNOWN",
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMMON,
20c794b39650d115e17a15983b6b82e46238cf45gavinm 0,
20c794b39650d115e17a15983b6b82e46238cf45gavinm 0
20c794b39650d115e17a15983b6b82e46238cf45gavinm};
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic errorq_t *gcpu_mca_queue;
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic kmutex_t gcpu_mca_queue_lock;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifdef __xpv
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yestatic int isxpv = 1;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#else
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yestatic int isxpv = 0;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic const gcpu_error_disp_t *
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_disp_match(uint16_t code)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm const gcpu_error_disp_t *ged = gcpu_errtypes;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int i;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0; i < sizeof (gcpu_errtypes) / sizeof (gcpu_error_disp_t);
20c794b39650d115e17a15983b6b82e46238cf45gavinm i++, ged++) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint16_t on = ged->ged_errcode_mask_on;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint16_t off = ged->ged_errcode_mask_off;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((code & on) == on && (code & off) == 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (ged);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesanstatic uint16_t
20c794b39650d115e17a15983b6b82e46238cf45gavinmbit_strip(uint16_t code, uint16_t mask, uint16_t shift)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan return ((code & mask) >> shift);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define BIT_STRIP(code, name) \
20c794b39650d115e17a15983b6b82e46238cf45gavinm bit_strip(code, MCAX86_ERRCODE_##name##_MASK, \
20c794b39650d115e17a15983b6b82e46238cf45gavinm MCAX86_ERRCODE_##name##_SHIFT)
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define GCPU_MNEMONIC_UNDEF "undefined"
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define GCPU_MNEMONIC_RESVD "reserved"
20c794b39650d115e17a15983b6b82e46238cf45gavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Mappings of TT, LL, RRRR, PP, II and T values to compound error name
20c794b39650d115e17a15983b6b82e46238cf45gavinm * mnemonics and to ereport class name components.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstruct gcpu_mnexp {
20c794b39650d115e17a15983b6b82e46238cf45gavinm const char *mne_compound; /* used in expanding compound errname */
20c794b39650d115e17a15983b6b82e46238cf45gavinm const char *mne_ereport; /* used in expanding ereport class */
20c794b39650d115e17a15983b6b82e46238cf45gavinm};
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic struct gcpu_mnexp gcpu_TT_mnemonics[] = { /* MCAX86_ERRCODE_TT_* */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "I", FM_EREPORT_CPU_GENERIC_TT_INSTR }, /* INSTR */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "D", FM_EREPORT_CPU_GENERIC_TT_DATA }, /* DATA */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "G", FM_EREPORT_CPU_GENERIC_TT_GEN }, /* GEN */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { GCPU_MNEMONIC_UNDEF, "" }
20c794b39650d115e17a15983b6b82e46238cf45gavinm};
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic struct gcpu_mnexp gcpu_LL_mnemonics[] = { /* MCAX86_ERRCODE_LL_* */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "LO", FM_EREPORT_CPU_GENERIC_LL_L0 }, /* L0 */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "L1", FM_EREPORT_CPU_GENERIC_LL_L1 }, /* L1 */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "L2", FM_EREPORT_CPU_GENERIC_LL_L2 }, /* L2 */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "LG", FM_EREPORT_CPU_GENERIC_LL_LG } /* LG */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi};
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic struct gcpu_mnexp gcpu_RRRR_mnemonics[] = { /* MCAX86_ERRCODE_RRRR_* */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "ERR", FM_EREPORT_CPU_GENERIC_RRRR_ERR }, /* ERR */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "RD", FM_EREPORT_CPU_GENERIC_RRRR_RD }, /* RD */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "WR", FM_EREPORT_CPU_GENERIC_RRRR_WR }, /* WR */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "DRD", FM_EREPORT_CPU_GENERIC_RRRR_DRD }, /* DRD */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "DWR", FM_EREPORT_CPU_GENERIC_RRRR_DWR }, /* DWR */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "IRD", FM_EREPORT_CPU_GENERIC_RRRR_IRD }, /* IRD */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "PREFETCH", FM_EREPORT_CPU_GENERIC_RRRR_PREFETCH }, /* PREFETCH */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "EVICT", FM_EREPORT_CPU_GENERIC_RRRR_EVICT }, /* EVICT */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "SNOOP", FM_EREPORT_CPU_GENERIC_RRRR_SNOOP }, /* SNOOP */
20c794b39650d115e17a15983b6b82e46238cf45gavinm};
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic struct gcpu_mnexp gcpu_PP_mnemonics[] = { /* MCAX86_ERRCODE_PP_* */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "SRC", FM_EREPORT_CPU_GENERIC_PP_SRC }, /* SRC */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "RES", FM_EREPORT_CPU_GENERIC_PP_RES }, /* RES */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "OBS", FM_EREPORT_CPU_GENERIC_PP_OBS }, /* OBS */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "", FM_EREPORT_CPU_GENERIC_PP_GEN } /* GEN */
20c794b39650d115e17a15983b6b82e46238cf45gavinm};
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic struct gcpu_mnexp gcpu_II_mnemonics[] = { /* MCAX86_ERRCODE_II_* */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "M", FM_EREPORT_CPU_GENERIC_II_MEM }, /* MEM */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { GCPU_MNEMONIC_RESVD, "" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "IO", FM_EREPORT_CPU_GENERIC_II_IO }, /* IO */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "", FM_EREPORT_CPU_GENERIC_II_GEN } /* GEN */
20c794b39650d115e17a15983b6b82e46238cf45gavinm};
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic struct gcpu_mnexp gcpu_T_mnemonics[] = { /* MCAX86_ERRCODE_T_* */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "NOTIMEOUT", FM_EREPORT_CPU_GENERIC_T_NOTIMEOUT }, /* NONE */
20c794b39650d115e17a15983b6b82e46238cf45gavinm { "TIMEOUT", FM_EREPORT_CPU_GENERIC_T_TIMEOUT } /* TIMEOUT */
20c794b39650d115e17a15983b6b82e46238cf45gavinm};
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Froststatic struct gcpu_mnexp gcpu_CCCC_mnemonics[] = { /* MCAX86_ERRCODE_CCCC_* */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH0", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH0 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH1", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH1 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH2", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH2 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH3", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH3 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH4", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH4 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH5", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH5 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH6", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH6 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH7", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH7 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH8", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH8 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH9", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH9 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH10", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH10 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH11", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH11 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH12", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH12 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH13", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH13 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH14", FM_EREPORT_CPU_GENERIC_CCCC }, /* CH14 */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "CH", FM_EREPORT_CPU_GENERIC_CCCC } /* GEN */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost};
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Froststatic struct gcpu_mnexp gcpu_MMM_mnemonics[] = { /* MCAX86_ERRCODE_MMM_* */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "GEN", FM_EREPORT_CPU_GENERIC_MMM_ERR }, /* GEN ERR */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "RD", FM_EREPORT_CPU_GENERIC_MMM_RD }, /* READ */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "WR", FM_EREPORT_CPU_GENERIC_MMM_WR }, /* WRITE */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { "ADDR_CMD", FM_EREPORT_CPU_GENERIC_MMM_ADRCMD }, /* ADDR, CMD */
491f61a1e1c1fc54a47bbcf53dbbbe1293b93b27Yanmin Sun { "SCRUB", FM_EREPORT_CPU_GENERIC_MMM_SCRUB },
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { GCPU_MNEMONIC_RESVD, ""}, /* RESERVED */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { GCPU_MNEMONIC_RESVD, ""}, /* RESERVED */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost { GCPU_MNEMONIC_RESVD, ""} /* RESERVED */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost};
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
20c794b39650d115e17a15983b6b82e46238cf45gavinmenum gcpu_mn_namespace {
20c794b39650d115e17a15983b6b82e46238cf45gavinm GCPU_MN_NAMESPACE_COMPOUND,
20c794b39650d115e17a15983b6b82e46238cf45gavinm GCPU_MN_NAMESPACE_EREPORT
20c794b39650d115e17a15983b6b82e46238cf45gavinm};
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic const char *
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesangcpu_mnemonic(const struct gcpu_mnexp *tbl, size_t tbl_sz, uint16_t val,
20c794b39650d115e17a15983b6b82e46238cf45gavinm enum gcpu_mn_namespace nspace)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan if (val >= tbl_sz || val > 0xff)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (GCPU_MNEMONIC_UNDEF); /* for all namespaces */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm switch (nspace) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm case GCPU_MN_NAMESPACE_COMPOUND:
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (tbl[val].mne_compound);
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*NOTREACHED*/
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm case GCPU_MN_NAMESPACE_EREPORT:
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (tbl[val].mne_ereport);
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*NOTREACHED*/
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm default:
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (GCPU_MNEMONIC_UNDEF);
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*NOTREACHED*/
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * The ereport class leaf component is either a simple string with no
20c794b39650d115e17a15983b6b82e46238cf45gavinm * format specifiers, or a string with one or more embedded %n$s specifiers -
20c794b39650d115e17a15983b6b82e46238cf45gavinm * positional selection for string arguments. The kernel snprintf does
20c794b39650d115e17a15983b6b82e46238cf45gavinm * not support %n$ (and teaching it to do so is too big a headache) so
20c794b39650d115e17a15983b6b82e46238cf45gavinm * we will expand this restricted format string ourselves.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost#define GCPU_CLASS_VARCOMPS 9
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define GCPU_MNEMONIC(code, name, nspace) \
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mnemonic(gcpu_##name##_mnemonics, \
20c794b39650d115e17a15983b6b82e46238cf45gavinm sizeof (gcpu_##name##_mnemonics) / sizeof (struct gcpu_mnexp), \
20c794b39650d115e17a15983b6b82e46238cf45gavinm BIT_STRIP(code, name), nspace)
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_mn_fmt(const char *fmt, char *buf, size_t buflen, uint64_t status,
20c794b39650d115e17a15983b6b82e46238cf45gavinm enum gcpu_mn_namespace nspace)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint16_t code = MCAX86_ERRCODE(status);
20c794b39650d115e17a15983b6b82e46238cf45gavinm const char *mn[GCPU_CLASS_VARCOMPS];
20c794b39650d115e17a15983b6b82e46238cf45gavinm char *p = buf; /* current position in buf */
20c794b39650d115e17a15983b6b82e46238cf45gavinm char *q = buf + buflen; /* pointer past last char in buf */
20c794b39650d115e17a15983b6b82e46238cf45gavinm int which, expfmtchar, error;
20c794b39650d115e17a15983b6b82e46238cf45gavinm char c;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm mn[0] = GCPU_MNEMONIC(code, TT, nspace);
20c794b39650d115e17a15983b6b82e46238cf45gavinm mn[1] = GCPU_MNEMONIC(code, LL, nspace);
20c794b39650d115e17a15983b6b82e46238cf45gavinm mn[2] = GCPU_MNEMONIC(code, RRRR, nspace);
20c794b39650d115e17a15983b6b82e46238cf45gavinm mn[3] = GCPU_MNEMONIC(code, PP, nspace);
20c794b39650d115e17a15983b6b82e46238cf45gavinm mn[4] = GCPU_MNEMONIC(code, II, nspace);
20c794b39650d115e17a15983b6b82e46238cf45gavinm mn[5] = GCPU_MNEMONIC(code, T, nspace);
20c794b39650d115e17a15983b6b82e46238cf45gavinm mn[6] = (status & MSR_MC_STATUS_UC) ? "_uc" : "";
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost mn[7] = GCPU_MNEMONIC(code, CCCC, nspace);
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost mn[8] = GCPU_MNEMONIC(code, MMM, nspace);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm while (p < q - 1 && (c = *fmt++) != '\0') {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (c != '%') {
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* not the beginning of a format specifier - copy */
20c794b39650d115e17a15983b6b82e46238cf45gavinm *p++ = c;
20c794b39650d115e17a15983b6b82e46238cf45gavinm continue;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm error = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm which = -1;
20c794b39650d115e17a15983b6b82e46238cf45gavinm expfmtchar = -1;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmnextfmt:
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((c = *fmt++) == '\0')
20c794b39650d115e17a15983b6b82e46238cf45gavinm break; /* early termination of fmt specifier */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm switch (c) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm case '1':
20c794b39650d115e17a15983b6b82e46238cf45gavinm case '2':
20c794b39650d115e17a15983b6b82e46238cf45gavinm case '3':
20c794b39650d115e17a15983b6b82e46238cf45gavinm case '4':
20c794b39650d115e17a15983b6b82e46238cf45gavinm case '5':
20c794b39650d115e17a15983b6b82e46238cf45gavinm case '6':
20c794b39650d115e17a15983b6b82e46238cf45gavinm case '7':
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost case '8':
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost case '9':
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (which != -1) { /* allow only one positional digit */
20c794b39650d115e17a15983b6b82e46238cf45gavinm error++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm which = c - '1';
20c794b39650d115e17a15983b6b82e46238cf45gavinm goto nextfmt;
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*NOTREACHED*/
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm case '$':
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (which == -1) { /* no position specified */
20c794b39650d115e17a15983b6b82e46238cf45gavinm error++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm expfmtchar = 's';
20c794b39650d115e17a15983b6b82e46238cf45gavinm goto nextfmt;
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*NOTREACHED*/
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm case 's':
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (expfmtchar != 's') {
20c794b39650d115e17a15983b6b82e46238cf45gavinm error++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) snprintf(p, (uintptr_t)q - (uintptr_t)p, "%s",
20c794b39650d115e17a15983b6b82e46238cf45gavinm mn[which]);
20c794b39650d115e17a15983b6b82e46238cf45gavinm p += strlen(p);
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm default:
20c794b39650d115e17a15983b6b82e46238cf45gavinm error++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (error)
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm *p = '\0'; /* NUL termination */
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_erpt_clsfmt(const char *fmt, char *buf, size_t buflen, uint64_t status,
20c794b39650d115e17a15983b6b82e46238cf45gavinm const char *cpuclass, const char *leafclass)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm char *p = buf; /* current position in buf */
20c794b39650d115e17a15983b6b82e46238cf45gavinm char *q = buf + buflen; /* pointer past last char in buf */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) snprintf(buf, (uintptr_t)q - (uintptr_t)p, "%s.%s.",
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_ERROR_CPU, cpuclass ? cpuclass : FM_EREPORT_CPU_GENERIC);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm p += strlen(p);
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (p >= q)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (leafclass == NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mn_fmt(fmt, p, (uintptr_t)q - (uintptr_t)p, status,
20c794b39650d115e17a15983b6b82e46238cf45gavinm GCPU_MN_NAMESPACE_EREPORT);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) snprintf(p, (uintptr_t)q - (uintptr_t)p, "%s",
20c794b39650d115e17a15983b6b82e46238cf45gavinm leafclass);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * Create an "hc" scheme FMRI identifying the given cpu with
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * motherboard/chip/core/strand instance numbers.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic nvlist_t *
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_fmri_create(cmi_hdl_t hdl, nv_alloc_t *nva)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier nvlist_t *nvl, *fmri;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((nvl = fm_nvlist_create(nva)) == NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier if (!x86gentopo_legacy) {
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier fmri = cmi_hdl_smb_bboard(hdl);
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier if (fmri == NULL)
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier return (NULL);
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION,
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier NULL, NULL, fmri, 3,
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier "chip", cmi_hdl_smb_chipid(hdl),
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier "core", cmi_hdl_coreid(hdl),
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier "strand", cmi_hdl_strandid(hdl));
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier } else {
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 4,
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier "motherboard", 0,
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier "chip", cmi_hdl_chipid(hdl),
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier "core", cmi_hdl_coreid(hdl),
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier "strand", cmi_hdl_strandid(hdl));
074bb90d80fdbeb2d04a8450a55ecbc96de28785Tom Pothier }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (nvl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmint gcpu_bleat_count_thresh = 5;
20c794b39650d115e17a15983b6b82e46238cf45gavinmhrtime_t gcpu_bleat_min_interval = 10 * 1000000000ULL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Called when we are unable to propogate a logout structure onto an
20c794b39650d115e17a15983b6b82e46238cf45gavinm * errorq for subsequent ereport preparation and logging etc. The caller
20c794b39650d115e17a15983b6b82e46238cf45gavinm * should usually only decide to call this for severe errors - those we
20c794b39650d115e17a15983b6b82e46238cf45gavinm * suspect we may need to panic for.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_bleat(cmi_hdl_t hdl, gcpu_logout_t *gcl)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm hrtime_t now = gethrtime_waitfree();
20c794b39650d115e17a15983b6b82e46238cf45gavinm static hrtime_t gcpu_last_bleat;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_bank_logout_t *gbl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm static int bleatcount;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int i;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Throttle spamming of the console. The first gcpu_bleat_count_thresh
20c794b39650d115e17a15983b6b82e46238cf45gavinm * can come as fast as we like, but once we've spammed that many
20c794b39650d115e17a15983b6b82e46238cf45gavinm * to the console we require a minimum interval to pass before
20c794b39650d115e17a15983b6b82e46238cf45gavinm * any more complaints.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (++bleatcount > gcpu_bleat_count_thresh) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (now - gcpu_last_bleat < gcpu_bleat_min_interval)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm else
20c794b39650d115e17a15983b6b82e46238cf45gavinm bleatcount = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_last_bleat = now;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmn_err(CE_WARN,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost "Machine-Check Errors unlogged on chip %d core %d strand %d, "
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost "raw dump follows", cmi_hdl_chipid(hdl), cmi_hdl_coreid(hdl),
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmi_hdl_strandid(hdl));
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "MCG_STATUS 0x%016llx",
20c794b39650d115e17a15983b6b82e46238cf45gavinm (u_longlong_t)gcl->gcl_mcg_status);
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0, gbl = &gcl->gcl_data[0]; i < gcl->gcl_nbanks; i++, gbl++) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t status = gbl->gbl_status;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!(status & MSR_MC_STATUS_VAL))
20c794b39650d115e17a15983b6b82e46238cf45gavinm continue;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan /* Force ADDRV for AMD Family 0xf and above */
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan if (gcpu_force_addr_in_payload)
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan status = status | MSR_MC_STATUS_ADDRV;
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan
20c794b39650d115e17a15983b6b82e46238cf45gavinm switch (status & (MSR_MC_STATUS_ADDRV | MSR_MC_STATUS_MISCV)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm case MSR_MC_STATUS_ADDRV | MSR_MC_STATUS_MISCV:
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "Bank %d (offset 0x%llx) "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "STAT 0x%016llx ADDR 0x%016llx MISC 0x%016llx",
20c794b39650d115e17a15983b6b82e46238cf45gavinm i, IA32_MSR_MC(i, STATUS),
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan (u_longlong_t)gbl->gbl_status,
20c794b39650d115e17a15983b6b82e46238cf45gavinm (u_longlong_t)gbl->gbl_addr,
20c794b39650d115e17a15983b6b82e46238cf45gavinm (u_longlong_t)gbl->gbl_misc);
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm case MSR_MC_STATUS_ADDRV:
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "Bank %d (offset 0x%llx) "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "STAT 0x%016llx ADDR 0x%016llx",
20c794b39650d115e17a15983b6b82e46238cf45gavinm i, IA32_MSR_MC(i, STATUS),
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan (u_longlong_t)gbl->gbl_status,
20c794b39650d115e17a15983b6b82e46238cf45gavinm (u_longlong_t)gbl->gbl_addr);
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm case MSR_MC_STATUS_MISCV:
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "Bank %d (offset 0x%llx) "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "STAT 0x%016llx MISC 0x%016llx",
20c794b39650d115e17a15983b6b82e46238cf45gavinm i, IA32_MSR_MC(i, STATUS),
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan (u_longlong_t)gbl->gbl_status,
20c794b39650d115e17a15983b6b82e46238cf45gavinm (u_longlong_t)gbl->gbl_misc);
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm default:
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "Bank %d (offset 0x%llx) "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "STAT 0x%016llx",
20c794b39650d115e17a15983b6b82e46238cf45gavinm i, IA32_MSR_MC(i, STATUS),
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan (u_longlong_t)gbl->gbl_status);
20c794b39650d115e17a15983b6b82e46238cf45gavinm break;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define _GCPU_BSTATUS(status, what) \
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_NAME_MC_STATUS_##what, DATA_TYPE_BOOLEAN_VALUE, \
20c794b39650d115e17a15983b6b82e46238cf45gavinm (status) & MSR_MC_STATUS_##what ? B_TRUE : B_FALSE
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_ereport_add_logout(nvlist_t *ereport, const gcpu_logout_t *gcl,
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint_t bankno, const gcpu_error_disp_t *ged, uint16_t code)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t members = ged ? ged->ged_ereport_members :
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_FLAGS_COMMON;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t mcg = gcl->gcl_mcg_status;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int mcip = mcg & MCG_STATUS_MCIP;
20c794b39650d115e17a15983b6b82e46238cf45gavinm const gcpu_bank_logout_t *gbl = &gcl->gcl_data[bankno];
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t bstat = gbl->gbl_status;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Include the compound error name if requested and if this
20c794b39650d115e17a15983b6b82e46238cf45gavinm * is a compound error type.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (members & FM_EREPORT_PAYLOAD_FLAG_COMPOUND_ERR && ged &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm ged->ged_compound_fmt != NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm char buf[FM_MAX_CLASS];
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mn_fmt(ged->ged_compound_fmt, buf, sizeof (buf), code,
20c794b39650d115e17a15983b6b82e46238cf45gavinm GCPU_MN_NAMESPACE_COMPOUND);
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_COMPOUND_ERR,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_STRING, buf, NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Include disposition information for this error
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (members & FM_EREPORT_PAYLOAD_FLAG_DISP &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp != 0) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm int i, empty = 1;
20c794b39650d115e17a15983b6b82e46238cf45gavinm char buf[128];
20c794b39650d115e17a15983b6b82e46238cf45gavinm char *p = buf, *q = buf + 128;
20c794b39650d115e17a15983b6b82e46238cf45gavinm static struct _gcpu_disp_name {
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t dv;
20c794b39650d115e17a15983b6b82e46238cf45gavinm const char *dn;
20c794b39650d115e17a15983b6b82e46238cf45gavinm } disp_names[] = {
20c794b39650d115e17a15983b6b82e46238cf45gavinm { CMI_ERRDISP_CURCTXBAD,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "processor_context_corrupt" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm { CMI_ERRDISP_RIPV_INVALID,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "return_ip_invalid" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm { CMI_ERRDISP_UC_UNCONSTRAINED,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "unconstrained" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm { CMI_ERRDISP_FORCEFATAL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "forcefatal" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm { CMI_ERRDISP_IGNORED,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "ignored" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm { CMI_ERRDISP_PCC_CLEARED,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "corrupt_context_cleared" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm { CMI_ERRDISP_UC_CLEARED,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "uncorrected_data_cleared" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm { CMI_ERRDISP_POISONED,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "poisoned" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm { CMI_ERRDISP_INCONSISTENT,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "telemetry_unstable" },
20c794b39650d115e17a15983b6b82e46238cf45gavinm };
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0; i < sizeof (disp_names) /
20c794b39650d115e17a15983b6b82e46238cf45gavinm sizeof (struct _gcpu_disp_name); i++) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((gbl->gbl_disp & disp_names[i].dv) == 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm continue;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) snprintf(p, (uintptr_t)q - (uintptr_t)p,
20c794b39650d115e17a15983b6b82e46238cf45gavinm "%s%s", empty ? "" : ",", disp_names[i].dn);
20c794b39650d115e17a15983b6b82e46238cf45gavinm p += strlen(p);
20c794b39650d115e17a15983b6b82e46238cf45gavinm empty = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (p != buf)
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_DISP,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_STRING, buf, NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * If MCG_STATUS is included add that and an indication of whether
20c794b39650d115e17a15983b6b82e46238cf45gavinm * this ereport was the result of a machine check or poll.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (members & FM_EREPORT_PAYLOAD_FLAG_MCG_STATUS) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_MCG_STATUS,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_UINT64, mcg, NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_MCG_STATUS_MCIP,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_BOOLEAN_VALUE, mcip ? B_TRUE : B_FALSE, NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * If an instruction pointer is to be included add one provided
20c794b39650d115e17a15983b6b82e46238cf45gavinm * MCG_STATUS indicated it is valid; meaningless for polled events.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (mcip && members & FM_EREPORT_PAYLOAD_FLAG_IP &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcg & MCG_STATUS_EIPV) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_IP,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_UINT64, gcl->gcl_ip, NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Add an indication of whether the trap occured during privileged code.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (mcip && members & FM_EREPORT_PAYLOAD_FLAG_PRIV) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_PRIV,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_BOOLEAN_VALUE,
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_flags & GCPU_GCL_F_PRIV ? B_TRUE : B_FALSE, NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * If requested, add the index of the MCA bank. This indicates the
20c794b39650d115e17a15983b6b82e46238cf45gavinm * n'th bank of 4 MCA registers, and does not necessarily correspond
20c794b39650d115e17a15983b6b82e46238cf45gavinm * to MCi_* - use the bank offset to correlate
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (members & FM_EREPORT_PAYLOAD_FLAG_BANK_NUM) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport,
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Bank number */
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_NAME_BANK_NUM, DATA_TYPE_UINT8, bankno,
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Offset of MCi_CTL */
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_NAME_BANK_MSR_OFFSET, DATA_TYPE_UINT64,
20c794b39650d115e17a15983b6b82e46238cf45gavinm IA32_MSR_MC(bankno, CTL),
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Add MCi_STATUS if requested, and decode it.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (members & FM_EREPORT_PAYLOAD_FLAG_MC_STATUS) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm const char *tbes[] = {
20c794b39650d115e17a15983b6b82e46238cf45gavinm "No tracking", /* 00 */
20c794b39650d115e17a15983b6b82e46238cf45gavinm "Green - below threshold", /* 01 */
20c794b39650d115e17a15983b6b82e46238cf45gavinm "Yellow - above threshold", /* 10 */
20c794b39650d115e17a15983b6b82e46238cf45gavinm "Reserved" /* 11 */
20c794b39650d115e17a15983b6b82e46238cf45gavinm };
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport,
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Bank MCi_STATUS */
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_NAME_MC_STATUS, DATA_TYPE_UINT64, bstat,
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Overflow? */
20c794b39650d115e17a15983b6b82e46238cf45gavinm _GCPU_BSTATUS(bstat, OVER),
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Uncorrected? */
20c794b39650d115e17a15983b6b82e46238cf45gavinm _GCPU_BSTATUS(bstat, UC),
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Enabled? */
20c794b39650d115e17a15983b6b82e46238cf45gavinm _GCPU_BSTATUS(bstat, EN),
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Processor context corrupt? */
20c794b39650d115e17a15983b6b82e46238cf45gavinm _GCPU_BSTATUS(bstat, PCC),
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Error code */
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_NAME_MC_STATUS_ERRCODE,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_UINT16, MCAX86_ERRCODE(bstat),
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Model-specific error code */
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_NAME_MC_STATUS_EXTERRCODE,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_UINT16, MCAX86_MSERRCODE(bstat),
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * If MCG_CAP.TES_P indicates that that thresholding info
20c794b39650d115e17a15983b6b82e46238cf45gavinm * is present in the architural component of the bank status
20c794b39650d115e17a15983b6b82e46238cf45gavinm * then include threshold information for this bank.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcl->gcl_flags & GCPU_GCL_F_TES_P) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport,
20c794b39650d115e17a15983b6b82e46238cf45gavinm FM_EREPORT_PAYLOAD_NAME_MC_STATUS_TES,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_STRING, tbes[MCAX86_TBES_VALUE(bstat)],
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan * Add MCi_ADDR info if requested and valid. We force addition of
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan * MCi_ADDR, even if its not valid on AMD family 0xf and above,
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan * to aid in analysis of ereports, for WatchDog errors.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (members & FM_EREPORT_PAYLOAD_FLAG_MC_ADDR &&
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan ((bstat & MSR_MC_STATUS_ADDRV) ||
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan gcpu_force_addr_in_payload)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_MC_ADDR,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_UINT64, gbl->gbl_addr, NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * MCi_MISC if requested and MCi_STATUS.MISCV).
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (members & FM_EREPORT_PAYLOAD_FLAG_MC_MISC &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm bstat & MSR_MC_STATUS_MISCV) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_MC_MISC,
20c794b39650d115e17a15983b6b82e46238cf45gavinm DATA_TYPE_UINT64, gbl->gbl_misc, NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Construct and post an ereport based on the logout information from a
20c794b39650d115e17a15983b6b82e46238cf45gavinm * single MCA bank. We are not necessarily running on the cpu that
20c794b39650d115e17a15983b6b82e46238cf45gavinm * detected the error.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_ereport_post(const gcpu_logout_t *gcl, int bankidx,
20c794b39650d115e17a15983b6b82e46238cf45gavinm const gcpu_error_disp_t *ged, cms_cookie_t mscookie, uint64_t status)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_data_t *gcpu = gcl->gcl_gcpu;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_t hdl = gcpu->gcpu_hdl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm const gcpu_bank_logout_t *gbl = &gcl->gcl_data[bankidx];
20c794b39650d115e17a15983b6b82e46238cf45gavinm const char *cpuclass = NULL, *leafclass = NULL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint16_t code = MCAX86_ERRCODE(status);
20c794b39650d115e17a15983b6b82e46238cf45gavinm errorq_elem_t *eqep, *scr_eqep;
20c794b39650d115e17a15983b6b82e46238cf45gavinm nvlist_t *ereport, *detector;
20c794b39650d115e17a15983b6b82e46238cf45gavinm char buf[FM_MAX_CLASS];
20c794b39650d115e17a15983b6b82e46238cf45gavinm const char *classfmt;
20c794b39650d115e17a15983b6b82e46238cf45gavinm nv_alloc_t *nva;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (panicstr) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((eqep = errorq_reserve(ereport_errorq)) == NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm ereport = errorq_elem_nvl(ereport_errorq, eqep);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Allocate another element for scratch space, but fallback
20c794b39650d115e17a15983b6b82e46238cf45gavinm * to the one we have if that fails. We'd like to use the
20c794b39650d115e17a15983b6b82e46238cf45gavinm * additional scratch space for nvlist construction.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((scr_eqep = errorq_reserve(ereport_errorq)) != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm nva = errorq_elem_nva(ereport_errorq, scr_eqep);
20c794b39650d115e17a15983b6b82e46238cf45gavinm else
20c794b39650d115e17a15983b6b82e46238cf45gavinm nva = errorq_elem_nva(ereport_errorq, eqep);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm ereport = fm_nvlist_create(NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm nva = NULL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (ereport == NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Common payload data required by the protocol:
20c794b39650d115e17a15983b6b82e46238cf45gavinm * - ereport class
20c794b39650d115e17a15983b6b82e46238cf45gavinm * - detector
20c794b39650d115e17a15983b6b82e46238cf45gavinm * - ENA
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Ereport class - call into model-specific support to allow it to
20c794b39650d115e17a15983b6b82e46238cf45gavinm * provide a cpu class or leaf class, otherwise calculate our own.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm cms_ereport_class(hdl, mscookie, &cpuclass, &leafclass);
20c794b39650d115e17a15983b6b82e46238cf45gavinm classfmt = ged ? ged->ged_class_fmt : FM_EREPORT_CPU_GENERIC_UNKNOWN;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_erpt_clsfmt(classfmt, buf, sizeof (buf), status, cpuclass,
20c794b39650d115e17a15983b6b82e46238cf45gavinm leafclass);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * The detector FMRI.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
491f61a1e1c1fc54a47bbcf53dbbbe1293b93b27Yanmin Sun if ((detector = cms_ereport_detector(hdl, bankidx, mscookie,
491f61a1e1c1fc54a47bbcf53dbbbe1293b93b27Yanmin Sun nva)) == NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm detector = gcpu_fmri_create(hdl, nva);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Should we define a new ENA format 3?? for chip/core/strand?
20c794b39650d115e17a15983b6b82e46238cf45gavinm * It will be better when virtualized.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_ereport_set(ereport, FM_EREPORT_VERSION, buf,
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_ena_generate_cpu(gcl->gcl_timestamp,
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_chipid(hdl) << 6 | cmi_hdl_coreid(hdl) << 3 |
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_strandid(hdl), FM_ENA_FMT1), detector, NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (panicstr) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_nvlist_destroy(detector, FM_NVA_RETAIN);
20c794b39650d115e17a15983b6b82e46238cf45gavinm nv_alloc_reset(nva);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_nvlist_destroy(detector, FM_NVA_FREE);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Add the architectural ereport class-specific payload data.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_ereport_add_logout(ereport, gcl, bankidx, ged, code);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Allow model-specific code to add ereport members.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm cms_ereport_add_logout(hdl, ereport, nva, bankidx, gbl->gbl_status,
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_addr, gbl->gbl_misc, gcl->gcl_ms_logout, mscookie);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Include stack if options is turned on and either selected in
20c794b39650d115e17a15983b6b82e46238cf45gavinm * the payload member bitmask or inclusion is forced.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcpu_mca_stack_flag &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm (cms_ereport_includestack(hdl, mscookie) ==
20c794b39650d115e17a15983b6b82e46238cf45gavinm B_TRUE || gcpu_mca_stack_ereport_include)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_payload_stack_add(ereport, gcl->gcl_stack,
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_stackdepth);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye /*
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * If injection has taken place anytime in the past then note this
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * on the ereport.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (cmi_inj_tainted() == B_TRUE) {
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye fm_payload_set(ereport, "__injected", DATA_TYPE_BOOLEAN_VALUE,
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye B_TRUE, NULL);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Post ereport.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (panicstr) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (scr_eqep)
20c794b39650d115e17a15983b6b82e46238cf45gavinm errorq_cancel(ereport_errorq, scr_eqep);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) fm_ereport_post(ereport, EVCH_TRYHARD);
20c794b39650d115e17a15983b6b82e46238cf45gavinm fm_nvlist_destroy(ereport, FM_NVA_FREE);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_mca_drain(void *ignored, const void *data, const errorq_elem_t *eqe)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm const gcpu_logout_t *gcl = data;
20c794b39650d115e17a15983b6b82e46238cf45gavinm const gcpu_bank_logout_t *gbl;
c84b7bbef5ecc2a27799422588073deefd9db715Adrian Frost int ismc;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int i;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
c84b7bbef5ecc2a27799422588073deefd9db715Adrian Frost ismc = gcl->ismc;
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0, gbl = &gcl->gcl_data[0]; i < gcl->gcl_nbanks; i++, gbl++) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm const gcpu_error_disp_t *gened;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cms_cookie_t mscookie;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gbl->gbl_status & MSR_MC_STATUS_VAL &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm !(gbl->gbl_disp & CMI_ERRDISP_INCONSISTENT)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint16_t code = MCAX86_ERRCODE(gbl->gbl_status);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Perform a match based on IA32 MCA architectural
20c794b39650d115e17a15983b6b82e46238cf45gavinm * components alone.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm gened = gcpu_disp_match(code); /* may be NULL */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Now see if an model-specific match can be made.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
c84b7bbef5ecc2a27799422588073deefd9db715Adrian Frost mscookie = cms_disp_match(gcl->gcl_gcpu->gcpu_hdl, ismc,
c84b7bbef5ecc2a27799422588073deefd9db715Adrian Frost i, gbl->gbl_status, gbl->gbl_addr, gbl->gbl_misc,
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_ms_logout);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Prepare and dispatch an ereport for logging and
20c794b39650d115e17a15983b6b82e46238cf45gavinm * diagnosis.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_ereport_post(gcl, i, gened, mscookie,
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_status);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else if (gbl->gbl_status & MSR_MC_STATUS_VAL &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm (gbl->gbl_disp & CMI_ERRDISP_INCONSISTENT)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Telemetry kept changing as we tried to read
20c794b39650d115e17a15983b6b82e46238cf45gavinm * it. Force an unknown ereport leafclass but
20c794b39650d115e17a15983b6b82e46238cf45gavinm * keep the telemetry unchanged for logging.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_ereport_post(gcl, i, &gcpu_unknown, NULL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_status);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic size_t gcpu_mca_queue_datasz = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * The following code is ready to make a weak attempt at growing the
20c794b39650d115e17a15983b6b82e46238cf45gavinm * errorq structure size. Since it is not foolproof (we don't know
20c794b39650d115e17a15983b6b82e46238cf45gavinm * who may already be producing to the outgoing errorq) our caller
20c794b39650d115e17a15983b6b82e46238cf45gavinm * instead assures that we'll always be called with no greater data
20c794b39650d115e17a15983b6b82e46238cf45gavinm * size than on our first call.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic void
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_errorq_init(size_t datasz)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm int slots;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_enter(&gcpu_mca_queue_lock);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcpu_mca_queue_datasz >= datasz) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_exit(&gcpu_mca_queue_lock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm membar_producer();
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcpu_mca_queue) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mca_queue_datasz = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm errorq_destroy(gcpu_mca_queue);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm slots = MAX(GCPU_MCA_ERRS_PERCPU * max_ncpus, GCPU_MCA_MIN_ERRORS);
20c794b39650d115e17a15983b6b82e46238cf45gavinm slots = MIN(slots, GCPU_MCA_MAX_ERRORS);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mca_queue = errorq_create("gcpu_mca_queue", gcpu_mca_drain,
20c794b39650d115e17a15983b6b82e46238cf45gavinm NULL, slots, datasz, 1, ERRORQ_VITAL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcpu_mca_queue != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mca_queue_datasz = datasz;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_exit(&gcpu_mca_queue_lock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Perform MCA initialization as described in section 14.6 of Intel 64
20c794b39650d115e17a15983b6b82e46238cf45gavinm * and IA-32 Architectures Software Developer's Manual Volume 3A.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic uint_t global_nbanks;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmvoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_mca_init(cmi_hdl_t hdl)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_data_t *gcpu = cmi_hdl_getcmidata(hdl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi uint64_t cap;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint_t vendor = cmi_hdl_vendor(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint_t family = cmi_hdl_family(hdl);
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan uint_t rev = cmi_hdl_chiprev(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mca_t *mca = &gcpu->gcpu_mca;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int mcg_ctl_present;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi uint_t nbanks;
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar uint32_t ctl_skip_mask = 0;
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar uint32_t status_skip_mask = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm size_t mslsz;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int i;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost int mcg_ctl2_present;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost uint32_t cmci_capable = 0;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcpu == NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan /* We add MCi_ADDR always for AMD Family 0xf and above */
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan if (X86_CHIPFAM_ATLEAST(rev, X86_CHIPREV_AMD_F_REV_B))
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan gcpu_force_addr_in_payload = 1;
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Protect from some silly /etc/system settings.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcpu_mca_telemetry_retries < 0 || gcpu_mca_telemetry_retries > 100)
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mca_telemetry_retries = 5;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_hdl_rdmsr(hdl, IA32_MSR_MCG_CAP, &cap) != CMI_SUCCESS)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla * CPU startup code only calls cmi_mca_init if x86_featureset indicates
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla * both MCA and MCE support (i.e., X86FSET_MCA). P5, K6, and earlier
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * processors, which have their own more primitive way of doing
20c794b39650d115e17a15983b6b82e46238cf45gavinm * machine checks, will not have cmi_mca_init called since their
20c794b39650d115e17a15983b6b82e46238cf45gavinm * CPUID information will not indicate both MCA and MCE features.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla ASSERT(is_x86_feature(x86_featureset, X86FSET_MCA));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Determine whether the IA32_MCG_CTL register is present. If it
20c794b39650d115e17a15983b6b82e46238cf45gavinm * is we will enable all features by writing -1 to it towards
20c794b39650d115e17a15983b6b82e46238cf45gavinm * the end of this initialization; if it is absent then volume 3A
20c794b39650d115e17a15983b6b82e46238cf45gavinm * says we must nonetheless continue to initialize the individual
20c794b39650d115e17a15983b6b82e46238cf45gavinm * banks.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcg_ctl_present = cap & MCG_CAP_CTL_P;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost mcg_ctl2_present = cap & MCG_CAP_CTL2_P;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * We squirell values away for inspection/debugging.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm mca->gcpu_mca_bioscfg.bios_mcg_cap = cap;
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (mcg_ctl_present)
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MCG_CTL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm &mca->gcpu_mca_bioscfg.bios_mcg_ctl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Determine the number of error-reporting banks implemented.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm mca->gcpu_mca_nbanks = nbanks = cap & MCG_CAP_COUNT_MASK;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (nbanks != 0 && global_nbanks == 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm global_nbanks = nbanks; /* no race - BSP will get here first */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * If someone is hiding the number of banks (perhaps we are fully
20c794b39650d115e17a15983b6b82e46238cf45gavinm * virtualized?) or if this processor has more banks than the
20c794b39650d115e17a15983b6b82e46238cf45gavinm * first to set global_nbanks then bail. The latter requirement
20c794b39650d115e17a15983b6b82e46238cf45gavinm * is because we need to size our errorq data structure and we
20c794b39650d115e17a15983b6b82e46238cf45gavinm * don't want to have to grow the errorq (destroy and recreate)
20c794b39650d115e17a15983b6b82e46238cf45gavinm * which may just lose some telemetry.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (nbanks == 0 || nbanks > global_nbanks)
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm mca->gcpu_mca_bioscfg.bios_bankcfg = kmem_zalloc(nbanks *
20c794b39650d115e17a15983b6b82e46238cf45gavinm sizeof (struct gcpu_bios_bankcfg), KM_SLEEP);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Calculate the size we need to allocate for a gcpu_logout_t
20c794b39650d115e17a15983b6b82e46238cf45gavinm * with a gcl_data array big enough for all banks of this cpu.
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Add any space requested by the model-specific logout support.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm mslsz = cms_logout_size(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm mca->gcpu_mca_lgsz = sizeof (gcpu_logout_t) +
20c794b39650d115e17a15983b6b82e46238cf45gavinm (nbanks - 1) * sizeof (gcpu_bank_logout_t) + mslsz;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0; i < GCPU_MCA_LOGOUT_NUM; i++) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_logout_t *gcl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm mca->gcpu_mca_logout[i] = gcl =
20c794b39650d115e17a15983b6b82e46238cf45gavinm kmem_zalloc(mca->gcpu_mca_lgsz, KM_SLEEP);
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_gcpu = gcpu;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_nbanks = nbanks;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_ms_logout = (mslsz == 0) ? NULL :
20c794b39650d115e17a15983b6b82e46238cf45gavinm (char *)(&gcl->gcl_data[0]) + nbanks *
20c794b39650d115e17a15983b6b82e46238cf45gavinm sizeof (gcpu_bank_logout_t);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifdef __xpv
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye gcpu_xpv_mca_init(nbanks);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
20c794b39650d115e17a15983b6b82e46238cf45gavinm mca->gcpu_mca_nextpoll_idx = GCPU_MCA_LOGOUT_POLLER_1;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost mca->gcpu_bank_cmci = kmem_zalloc(sizeof (gcpu_mca_cmci_t) * nbanks,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost KM_SLEEP);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Create our errorq to transport the logout structures. This
20c794b39650d115e17a15983b6b82e46238cf45gavinm * can fail so users of gcpu_mca_queue must be prepared for NULL.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_errorq_init(mca->gcpu_mca_lgsz);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Not knowing which, if any, banks are shared between cores we
20c794b39650d115e17a15983b6b82e46238cf45gavinm * assure serialization of MCA bank initialization by each cpu
20c794b39650d115e17a15983b6b82e46238cf45gavinm * on the chip. On chip architectures in which some banks are
20c794b39650d115e17a15983b6b82e46238cf45gavinm * shared this will mean the shared resource is initialized more
20c794b39650d115e17a15983b6b82e46238cf45gavinm * than once - we're simply aiming to avoid simultaneous MSR writes
20c794b39650d115e17a15983b6b82e46238cf45gavinm * to the shared resource.
20c794b39650d115e17a15983b6b82e46238cf45gavinm *
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Even with these precautions, some platforms may yield a GP fault
20c794b39650d115e17a15983b6b82e46238cf45gavinm * if a core other than a designated master tries to write anything
20c794b39650d115e17a15983b6b82e46238cf45gavinm * but all 0's to MCi_{STATUS,ADDR,CTL}. So we will perform
20c794b39650d115e17a15983b6b82e46238cf45gavinm * those writes under on_trap protection.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_enter(&gcpu->gcpu_shared->gcpus_cfglock);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Initialize poller data, but don't start polling yet.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mca_poll_init(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Work out which MCA banks we will initialize. In MCA logout
20c794b39650d115e17a15983b6b82e46238cf45gavinm * code we will only read those banks which we initialize here.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0; i < nbanks; i++) {
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar boolean_t skipctl = cms_bankctl_skipinit(hdl, i);
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar boolean_t skipstatus = cms_bankstatus_skipinit(hdl, i);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar if (!cms_present(hdl)) {
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar /*
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar * Model-specific support is not present, try to use
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar * sane defaults.
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar *
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar * On AMD family 6 processors, reports about spurious
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar * machine checks indicate that bank 0 should be
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar * skipped.
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar *
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar * On Intel family 6 processors, the documentation tells
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar * us not to write to MC0_CTL.
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar *
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar */
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar if (i == 0 && family == 6) {
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar switch (vendor) {
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar case X86_VENDOR_AMD:
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar skipstatus = B_TRUE;
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar /*FALLTHRU*/
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar case X86_VENDOR_Intel:
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar skipctl = B_TRUE;
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar break;
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar }
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar }
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar }
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar ctl_skip_mask |= skipctl << i;
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar status_skip_mask |= skipstatus << i;
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar if (skipctl && skipstatus)
20c794b39650d115e17a15983b6b82e46238cf45gavinm continue;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar * Record which MCA banks were enabled, from the point of view
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar * of the whole chip (if some cores share a bank we must be
20c794b39650d115e17a15983b6b82e46238cf45gavinm * sure either can logout from it).
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm atomic_or_32(&gcpu->gcpu_shared->gcpus_actv_banks, 1 << i);
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /*
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * check CMCI capability
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost */
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost if (mcg_ctl2_present) {
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost uint64_t ctl2;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost uint32_t cap = 0;
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC_CTL2(i), &ctl2);
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost if (ctl2 & MSR_MC_CTL2_EN)
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost continue;
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost ctl2 |= MSR_MC_CTL2_EN;
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MC_CTL2(i), ctl2);
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC_CTL2(i), &ctl2);
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost mca->gcpu_bank_cmci[i].cmci_cap = cap =
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost (ctl2 & MSR_MC_CTL2_EN) ? 1 : 0;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (cap)
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmci_capable ++;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /*
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * Set threshold to 1 while unset the en field, to avoid
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * CMCI trigged before APIC LVT entry init.
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost */
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost ctl2 = ctl2 & (~MSR_MC_CTL2_EN) | 1;
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MC_CTL2(i), ctl2);
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /*
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * init cmci related count
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost mca->gcpu_bank_cmci[i].cmci_enabled = 0;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost mca->gcpu_bank_cmci[i].drtcmci = 0;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost mca->gcpu_bank_cmci[i].ncmci = 0;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (cmci_capable)
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost cmi_enable_cmci = 1;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Log any valid telemetry lurking in the MCA banks, but do not
20c794b39650d115e17a15983b6b82e46238cf45gavinm * clear the status registers. Ignore the disposition returned -
20c794b39650d115e17a15983b6b82e46238cf45gavinm * we have already paniced or reset for any nasty errors found here.
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm *
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm * Intel vol 3A says that we should not do this on family 0x6,
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm * and that for any extended family the BIOS clears things
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm * on power-on reset so you'll only potentially find valid telemetry
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm * on warm reset (we do it for both - on power-on reset we should
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm * just see zeroes).
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm *
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm * AMD docs since K7 say we should process anything we find here.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm if (!gcpu_suppress_log_on_init &&
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm (vendor == X86_VENDOR_Intel && family >= 0xf ||
fa2e767ebc4f144f2041d566b0b7a9d45e8c6f1agavinm vendor == X86_VENDOR_AMD))
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost gcpu_mca_logout(hdl, NULL, -1ULL, NULL, B_FALSE,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost GCPU_MPT_WHAT_POKE_ERR);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Initialize all MCi_CTL and clear all MCi_STATUS, allowing the
20c794b39650d115e17a15983b6b82e46238cf45gavinm * model-specific module the power of veto.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0; i < nbanks; i++) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm struct gcpu_bios_bankcfg *bcfgp =
20c794b39650d115e17a15983b6b82e46238cf45gavinm mca->gcpu_mca_bioscfg.bios_bankcfg + i;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Stash inherited bank MCA state, even for banks we will
20c794b39650d115e17a15983b6b82e46238cf45gavinm * not initialize ourselves. Do not read the MISC register
20c794b39650d115e17a15983b6b82e46238cf45gavinm * unconditionally - on some processors that will #GP on
20c794b39650d115e17a15983b6b82e46238cf45gavinm * banks that do not implement the MISC register (would be
20c794b39650d115e17a15983b6b82e46238cf45gavinm * caught by on_trap, anyway).
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC(i, CTL),
20c794b39650d115e17a15983b6b82e46238cf45gavinm &bcfgp->bios_bank_ctl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC(i, STATUS),
20c794b39650d115e17a15983b6b82e46238cf45gavinm &bcfgp->bios_bank_status);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan if ((bcfgp->bios_bank_status & MSR_MC_STATUS_ADDRV) ||
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan gcpu_force_addr_in_payload) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC(i, ADDR),
20c794b39650d115e17a15983b6b82e46238cf45gavinm &bcfgp->bios_bank_addr);
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
25f476773dea2a0ee593dcf662a38d5f02487196gavinm /*
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * In some old BIOS the status value after boot can indicate
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * MISCV when there is actually no MISC register for
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * that bank. The following read could therefore
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * aggravate a general protection fault. This should be
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * caught by on_trap, but the #GP fault handler is busted
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * and can suffer a double fault even before we get to
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * trap() to check for on_trap protection. Until that
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * issue is fixed we remove the one access that we know
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * can cause a #GP.
25f476773dea2a0ee593dcf662a38d5f02487196gavinm *
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * if (bcfgp->bios_bank_status & MSR_MC_STATUS_MISCV)
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC(i, MISC),
25f476773dea2a0ee593dcf662a38d5f02487196gavinm * &bcfgp->bios_bank_misc);
25f476773dea2a0ee593dcf662a38d5f02487196gavinm */
25f476773dea2a0ee593dcf662a38d5f02487196gavinm bcfgp->bios_bank_misc = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar if (!(ctl_skip_mask & (1 << i))) {
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MC(i, CTL),
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar cms_bankctl_val(hdl, i, -1ULL));
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
521f69c05c5de4e5f848122e2fc5b8f1c6a9e0c6Jakub Jermar if (!(status_skip_mask & (1 << i))) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MC(i, STATUS),
20c794b39650d115e17a15983b6b82e46238cf45gavinm cms_bankstatus_val(hdl, i, 0ULL));
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Now let the model-specific support perform further initialization
20c794b39650d115e17a15983b6b82e46238cf45gavinm * of non-architectural features.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm cms_mca_init(hdl, nbanks);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MCG_STATUS, 0ULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm membar_producer();
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* enable all machine-check features */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (mcg_ctl_present)
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MCG_CTL,
20c794b39650d115e17a15983b6b82e46238cf45gavinm cms_mcgctl_val(hdl, nbanks, -1ULL));
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_exit(&gcpu->gcpu_shared->gcpus_cfglock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* enable machine-check exception in CR4 */
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_hdl_enable_mce(hdl);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic uint64_t
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_mca_process(cmi_hdl_t hdl, struct regs *rp, int nerr, gcpu_data_t *gcpu,
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_logout_t *gcl, int ismc, gcpu_mce_status_t *mcesp)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
20c794b39650d115e17a15983b6b82e46238cf45gavinm int curctxbad = 0, unconstrained = 0, forcefatal = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi gcpu_mca_t *mca = &gcpu->gcpu_mca;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int nbanks = mca->gcpu_mca_nbanks;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mce_status_t mce;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_bank_logout_t *gbl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t disp = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int i;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (mcesp == NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp = &mce;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_nerr = nerr;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_npcc = mcesp->mce_npcc_ok = mcesp->mce_nuc =
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_nuc_ok = mcesp->mce_nuc_poisoned =
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_forcefatal = mcesp->mce_ignored = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * If this a machine check then if the return instruction pointer
20c794b39650d115e17a15983b6b82e46238cf45gavinm * is not valid the current context is lost.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (ismc && !(gcl->gcl_mcg_status & MCG_STATUS_RIPV))
20c794b39650d115e17a15983b6b82e46238cf45gavinm disp |= CMI_ERRDISP_RIPV_INVALID;
c84b7bbef5ecc2a27799422588073deefd9db715Adrian Frost gcl->ismc = ismc;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0, gbl = &gcl->gcl_data[0]; i < nbanks; i++, gbl++) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t mcistatus = gbl->gbl_status;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint32_t ms_scope;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int pcc, uc;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int poisoned;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!(mcistatus & MSR_MC_STATUS_VAL))
20c794b39650d115e17a15983b6b82e46238cf45gavinm continue;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gbl->gbl_disp & CMI_ERRDISP_INCONSISTENT)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi continue;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm pcc = (mcistatus & MSR_MC_STATUS_PCC) != 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uc = (mcistatus & MSR_MC_STATUS_UC) != 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_npcc += pcc;
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_nuc += uc;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm ms_scope = cms_error_action(hdl, ismc, i, mcistatus,
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_addr, gbl->gbl_misc, gcl->gcl_ms_logout);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (pcc && ms_scope & CMS_ERRSCOPE_CURCONTEXT_OK) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm pcc = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_npcc_ok++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp |= CMI_ERRDISP_PCC_CLEARED;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (uc && ms_scope & CMS_ERRSCOPE_CLEARED_UC) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm uc = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_nuc_ok++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp |= CMI_ERRDISP_UC_CLEARED;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (uc) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm poisoned = (ms_scope & CMS_ERRSCOPE_POISONED) != 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (poisoned) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_nuc_poisoned++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp |= CMI_ERRDISP_POISONED;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if ((ms_scope & CMS_ERRSCOPE_IGNORE_ERR) == 0) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * We're not being instructed to ignore the error,
20c794b39650d115e17a15983b6b82e46238cf45gavinm * so apply our standard disposition logic to it.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (uc && !poisoned) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm unconstrained++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp |= disp |
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_ERRDISP_UC_UNCONSTRAINED;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (pcc && ismc) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm curctxbad++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp |= disp |
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_ERRDISP_CURCTXBAD;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Even if the above may not indicate that the error
20c794b39650d115e17a15983b6b82e46238cf45gavinm * is terminal, model-specific support may insist
20c794b39650d115e17a15983b6b82e46238cf45gavinm * that we treat it as such. Such errors wil be
20c794b39650d115e17a15983b6b82e46238cf45gavinm * fatal even if discovered via poll.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (ms_scope & CMS_ERRSCOPE_FORCE_FATAL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm forcefatal++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_forcefatal++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp |= disp |
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_ERRDISP_FORCEFATAL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_ignored++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp |= disp | CMI_ERRDISP_IGNORED;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (unconstrained > 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm disp |= CMI_ERRDISP_UC_UNCONSTRAINED;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (curctxbad > 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm disp |= CMI_ERRDISP_CURCTXBAD;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (forcefatal > 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm disp |= CMI_ERRDISP_FORCEFATAL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcpu_mca_queue != NULL) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm int how;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (ismc) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm how = cmi_mce_response(rp, disp) ?
20c794b39650d115e17a15983b6b82e46238cf45gavinm ERRORQ_ASYNC : /* no panic, so arrange drain */
20c794b39650d115e17a15983b6b82e46238cf45gavinm ERRORQ_SYNC; /* panic flow will drain */
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm how = (disp & CMI_ERRDISP_FORCEFATAL &&
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_panic_on_ue()) ?
20c794b39650d115e17a15983b6b82e46238cf45gavinm ERRORQ_SYNC : /* poller will panic */
20c794b39650d115e17a15983b6b82e46238cf45gavinm ERRORQ_ASYNC; /* no panic */
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm errorq_dispatch(gcpu_mca_queue, gcl, mca->gcpu_mca_lgsz, how);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else if (disp != 0) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_bleat(hdl, gcl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_disp = disp;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (disp);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Gather error telemetry from our source, and then submit it for
20c794b39650d115e17a15983b6b82e46238cf45gavinm * processing.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define IS_MCE_CANDIDATE(status) (((status) & MSR_MC_STATUS_EN) != 0 && \
20c794b39650d115e17a15983b6b82e46238cf45gavinm ((status) & (MSR_MC_STATUS_UC | MSR_MC_STATUS_PCC)) != 0)
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm#define STATUS_EQV(s1, s2) \
20c794b39650d115e17a15983b6b82e46238cf45gavinm (((s1) & ~MSR_MC_STATUS_OVER) == ((s2) & ~MSR_MC_STATUS_OVER))
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinmstatic uint32_t gcpu_deferrred_polled_clears;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Froststatic void
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frostgcpu_cmci_logout(cmi_hdl_t hdl, int bank, gcpu_mca_cmci_t *bank_cmci_p,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost uint64_t status, int what)
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost{
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost uint64_t ctl2;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (bank_cmci_p->cmci_cap && (what == GCPU_MPT_WHAT_CYC_ERR) &&
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost (!(status & MSR_MC_STATUS_VAL) || ((status & MSR_MC_STATUS_VAL) &&
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost !(status & MSR_MC_STATUS_CEC_MASK)))) {
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (!(bank_cmci_p->cmci_enabled)) {
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /*
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * when cmci is disabled, and the bank has no error or
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * no corrected error for
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * gcpu_mca_cmci_reenable_threshold consecutive polls,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * turn on this bank's cmci.
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost bank_cmci_p->drtcmci ++;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (bank_cmci_p->drtcmci >=
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost gcpu_mca_cmci_reenable_threshold) {
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /* turn on cmci */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost (void) cmi_hdl_rdmsr(hdl,
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost IA32_MSR_MC_CTL2(bank), &ctl2);
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost ctl2 |= MSR_MC_CTL2_EN;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost (void) cmi_hdl_wrmsr(hdl,
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost IA32_MSR_MC_CTL2(bank), ctl2);
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /* reset counter and set flag */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost bank_cmci_p->drtcmci = 0;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost bank_cmci_p->cmci_enabled = 1;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost }
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost } else {
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /*
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * when cmci is enabled,if is in cyclic poll and the
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * bank has no error or no corrected error, reset ncmci
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * counter
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost bank_cmci_p->ncmci = 0;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost }
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost }
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost}
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Froststatic void
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frostgcpu_cmci_throttle(cmi_hdl_t hdl, int bank, gcpu_mca_cmci_t *bank_cmci_p,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost int what)
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost{
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost uint64_t ctl2 = 0;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /*
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * if cmci of this bank occurred beyond
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * gcpu_mca_cmci_throttling_threshold between 2 polls,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost * turn off this bank's CMCI;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (bank_cmci_p->cmci_enabled && what == GCPU_MPT_WHAT_CMCI_ERR) {
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /* if it is cmci trap, increase the count */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost bank_cmci_p->ncmci++;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost if (bank_cmci_p->ncmci >= gcpu_mca_cmci_throttling_threshold) {
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /* turn off cmci */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC_CTL2(bank),
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost &ctl2);
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost ctl2 &= ~MSR_MC_CTL2_EN;
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MC_CTL2(bank),
728f047ccdb8a96a1aecc448cb87706241a08c94Adrian Frost ctl2);
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost /* clear the flag and count */
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost bank_cmci_p->cmci_enabled = 0;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost bank_cmci_p->ncmci = 0;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost }
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost }
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Froststatic void
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frostclear_mc(int first, int last, int ismc, boolean_t clrstatus,
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost cmi_hdl_t hdl, gcpu_logout_t *gcl, gcpu_logout_t *pgcl)
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost{
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost int i;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost gcpu_bank_logout_t *gbl, *pgbl;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost uint64_t status;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen if (first < 0 || last < 0)
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen return;
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen for (i = first, gbl = &gcl->gcl_data[first]; i <= last; i++, gbl++) {
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost status = gbl->gbl_status;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost if (status == 0)
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost continue;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost if (clrstatus == B_FALSE)
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost goto serialize;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost /*
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * For i86xpv we always clear status in order to invalidate
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * the interposed telemetry.
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost *
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * For native machine checks we always clear status here. For
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * native polls we must be a little more cautious since there
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * is an outside chance that we may clear telemetry from a
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * shared MCA bank on which a sibling core is machine checking.
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost *
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * For polled observations of errors that look like they may
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * produce a machine check (UC/PCC and ENabled, although these
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * do not guarantee a machine check on error occurence)
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * we will not clear the status at this wakeup unless
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * we saw the same status at the previous poll. We will
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * always process and log the current observations - it
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * is only the clearing of MCi_STATUS which may be
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * deferred until the next wakeup.
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost */
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost if (isxpv || ismc || !IS_MCE_CANDIDATE(status)) {
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MC(i, STATUS), 0ULL);
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost goto serialize;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost }
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost /*
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * We have a polled observation of a machine check
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * candidate. If we saw essentially the same status at the
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * last poll then clear the status now since this appears
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * not to be a #MC candidate after all. If we see quite
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * different status now then do not clear, but reconsider at
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * the next poll. In no actual machine check clears
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * the status in the interim then the status should not
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * keep changing forever (meaning we'd never clear it)
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * since before long we'll simply have latched the highest-
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * priority error and set the OVerflow bit. Nonetheless
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * we count how many times we defer clearing and after
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * a while insist on clearing the status.
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost */
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost pgbl = &pgcl->gcl_data[i];
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost if (pgbl->gbl_clrdefcnt != 0) {
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost /* We deferred clear on this bank at last wakeup */
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost if (STATUS_EQV(status, pgcl->gcl_data[i].gbl_status) ||
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost pgbl->gbl_clrdefcnt > 5) {
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost /*
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * Status is unchanged so clear it now and,
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * since we have already logged this info,
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * avoid logging it again.
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost */
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost gbl->gbl_status = 0;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost (void) cmi_hdl_wrmsr(hdl,
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost IA32_MSR_MC(i, STATUS), 0ULL);
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost } else {
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost /* Record deferral for next wakeup */
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost gbl->gbl_clrdefcnt = pgbl->gbl_clrdefcnt + 1;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost }
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost } else {
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost /* Record initial deferral for next wakeup */
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost gbl->gbl_clrdefcnt = 1;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost gcpu_deferrred_polled_clears++;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost }
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frostserialize:
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost {
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost#ifdef __xpv
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost ;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost#else
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost /*
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * Intel Vol 3A says to execute a serializing
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * instruction here, ie CPUID. Well WRMSR is also
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * defined to be serializing, so the status clear above
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * should suffice. To be a good citizen, and since
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * some clears are deferred, we'll execute a CPUID
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost * instruction here.
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost */
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost struct cpuid_regs tmp;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost (void) __cpuid_insn(&tmp);
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost#endif
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost }
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost }
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost}
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye/*ARGSUSED5*/
20c794b39650d115e17a15983b6b82e46238cf45gavinmvoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_mca_logout(cmi_hdl_t hdl, struct regs *rp, uint64_t bankmask,
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost gcpu_mce_status_t *mcesp, boolean_t clrstatus, int what)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_data_t *gcpu = cmi_hdl_getcmidata(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mca_t *mca = &gcpu->gcpu_mca;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int nbanks = mca->gcpu_mca_nbanks;
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen gcpu_bank_logout_t *gbl, *pgbl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_logout_t *gcl, *pgcl;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int ismc = (rp != NULL);
20c794b39650d115e17a15983b6b82e46238cf45gavinm int ispoll = !ismc;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int i, nerr = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_errno_t err;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t mcg_status;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t disp;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t cap;
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen int first = -1;
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen int last = -1;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost int willpanic = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_hdl_rdmsr(hdl, IA32_MSR_MCG_STATUS, &mcg_status) !=
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_SUCCESS || cmi_hdl_rdmsr(hdl, IA32_MSR_MCG_CAP, &cap) !=
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_SUCCESS) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (mcesp != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_nerr = mcesp->mce_disp = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm return;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (ismc) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl = mca->gcpu_mca_logout[GCPU_MCA_LOGOUT_EXCEPTION];
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm int pidx = mca->gcpu_mca_nextpoll_idx;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int ppidx = (pidx == GCPU_MCA_LOGOUT_POLLER_1) ?
20c794b39650d115e17a15983b6b82e46238cf45gavinm GCPU_MCA_LOGOUT_POLLER_2 : GCPU_MCA_LOGOUT_POLLER_1;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl = mca->gcpu_mca_logout[pidx]; /* current logout */
20c794b39650d115e17a15983b6b82e46238cf45gavinm pgcl = mca->gcpu_mca_logout[ppidx]; /* previous logout */
20c794b39650d115e17a15983b6b82e46238cf45gavinm mca->gcpu_mca_nextpoll_idx = ppidx; /* switch next time */
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_timestamp = gethrtime_waitfree();
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_mcg_status = mcg_status;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_ip = rp ? rp->r_pc : 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_flags = (rp && USERMODE(rp->r_cs)) ? GCPU_GCL_F_PRIV : 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cap & MCG_CAP_TES_P)
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_flags |= GCPU_GCL_F_TES_P;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0, gbl = &gcl->gcl_data[0]; i < nbanks; i++, gbl++) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t status, status2, addr, misc;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int retries = gcpu_mca_telemetry_retries;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_status = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_clrdefcnt = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Only logout from MCA banks we have initialized from at
20c794b39650d115e17a15983b6b82e46238cf45gavinm * least one core. If a core shares an MCA bank with another
20c794b39650d115e17a15983b6b82e46238cf45gavinm * but perhaps lost the race to initialize it, then it must
20c794b39650d115e17a15983b6b82e46238cf45gavinm * still be allowed to logout from the shared bank.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!(gcpu->gcpu_shared->gcpus_actv_banks & 1 << i))
20c794b39650d115e17a15983b6b82e46238cf45gavinm continue;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * On a poll look only at the banks we've been asked to check.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (rp == NULL && !(bankmask & 1 << i))
20c794b39650d115e17a15983b6b82e46238cf45gavinm continue;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_hdl_rdmsr(hdl, IA32_MSR_MC(i, STATUS), &status) !=
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_SUCCESS)
20c794b39650d115e17a15983b6b82e46238cf45gavinm continue;
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost gcpu_cmci_logout(hdl, i, &mca->gcpu_bank_cmci[i], status, what);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
20c794b39650d115e17a15983b6b82e46238cf45gavinmretry:
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!(status & MSR_MC_STATUS_VAL))
20c794b39650d115e17a15983b6b82e46238cf45gavinm continue;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen /* First and last bank that have valid status */
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen if (first < 0)
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost first = i;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost last = i;
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost
20c794b39650d115e17a15983b6b82e46238cf45gavinm addr = -1;
20c794b39650d115e17a15983b6b82e46238cf45gavinm misc = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan if ((status & MSR_MC_STATUS_ADDRV) ||
2c8230b0dc207870ae2a092351f10fe53091275bSrihari Venkatesan gcpu_force_addr_in_payload)
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC(i, ADDR), &addr);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (status & MSR_MC_STATUS_MISCV)
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_rdmsr(hdl, IA32_MSR_MC(i, MISC), &misc);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost gcpu_cmci_throttle(hdl, i, &mca->gcpu_bank_cmci[i], what);
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Allow the model-specific code to extract bank telemetry.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm cms_bank_logout(hdl, i, status, addr, misc, gcl->gcl_ms_logout);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Not all cpu models assure us that the status/address/misc
20c794b39650d115e17a15983b6b82e46238cf45gavinm * data will not change during the above sequence of MSR reads,
20c794b39650d115e17a15983b6b82e46238cf45gavinm * or that it can only change by the addition of the OVerflow
20c794b39650d115e17a15983b6b82e46238cf45gavinm * bit to the status register. If the status has changed
20c794b39650d115e17a15983b6b82e46238cf45gavinm * other than in the overflow bit then we attempt to reread
20c794b39650d115e17a15983b6b82e46238cf45gavinm * for a consistent snapshot, but eventually give up and
20c794b39650d115e17a15983b6b82e46238cf45gavinm * go with what we've got. We only perform this check
20c794b39650d115e17a15983b6b82e46238cf45gavinm * for a poll - a further #MC during a #MC will reset, and
20c794b39650d115e17a15983b6b82e46238cf45gavinm * polled errors should not overwrite higher-priority
20c794b39650d115e17a15983b6b82e46238cf45gavinm * trapping errors (but could set the overflow bit).
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (ispoll && (err = cmi_hdl_rdmsr(hdl, IA32_MSR_MC(i, STATUS),
20c794b39650d115e17a15983b6b82e46238cf45gavinm &status2)) == CMI_SUCCESS) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (!STATUS_EQV(status, status2)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (retries-- > 0) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm status = status2;
20c794b39650d115e17a15983b6b82e46238cf45gavinm goto retry;
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp |=
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_ERRDISP_INCONSISTENT;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else if (ispoll && err != CMI_SUCCESS) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_disp |= CMI_ERRDISP_INCONSISTENT;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm nerr++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_status = status;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_addr = addr;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gbl->gbl_misc = misc;
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen /*
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen * For polled observation, if the count of deferred status
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen * clears updated in the clear_mc() is nonzero and the
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen * MCi_STATUS has not changed, the last wakeup has produced
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen * the ereport of the error. Therefore, clear the status in
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen * this wakeup to avoid duplicate ereport.
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen */
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen pgbl = &pgcl->gcl_data[i];
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen if (!isxpv && ispoll && IS_MCE_CANDIDATE(status) &&
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen pgbl->gbl_clrdefcnt != 0) {
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen if (STATUS_EQV(status, pgcl->gcl_data[i].gbl_status)) {
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen gbl->gbl_status = 0;
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen (void) cmi_hdl_wrmsr(hdl,
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen IA32_MSR_MC(i, STATUS), 0ULL);
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen }
1cb355fb19d9ed7ae61b0e03c94386f1cd79b6c6Vuong Nguyen }
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcpu_mca_stack_flag)
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_stackdepth = getpcstack(gcl->gcl_stack, FM_STK_DEPTH);
20c794b39650d115e17a15983b6b82e46238cf45gavinm else
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcl->gcl_stackdepth = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Decide our disposition for this error or errors, and submit for
20c794b39650d115e17a15983b6b82e46238cf45gavinm * logging and subsequent diagnosis.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (nerr != 0) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm disp = gcpu_mca_process(hdl, rp, nerr, gcpu, gcl, ismc, mcesp);
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost willpanic = (ismc && cmi_mce_response(rp, disp) == 0);
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost if (!willpanic)
0ad0f0b2adb964c7bd56bbf5a831721e1a67beafAdrian Frost clear_mc(first, last, ismc, clrstatus, hdl, gcl, pgcl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm disp = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (mcesp) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm mcesp->mce_nerr = mcesp->mce_disp = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Clear MCG_STATUS if MCIP is set (machine check in progress).
20c794b39650d115e17a15983b6b82e46238cf45gavinm * If a second #MC had occured before now the system would have
20c794b39650d115e17a15983b6b82e46238cf45gavinm * reset. We can only do thise once gcpu_mca_process has copied
20c794b39650d115e17a15983b6b82e46238cf45gavinm * the logout structure.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (ismc && mcg_status & MCG_STATUS_MCIP)
20c794b39650d115e17a15983b6b82e46238cf45gavinm (void) cmi_hdl_wrmsr(hdl, IA32_MSR_MCG_STATUS, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * At this point we have read and logged all telemetry that is visible
20c794b39650d115e17a15983b6b82e46238cf45gavinm * under the MCA. On architectures for which the NorthBridge is
20c794b39650d115e17a15983b6b82e46238cf45gavinm * on-chip this may include NB-observed errors, but where the NB
20c794b39650d115e17a15983b6b82e46238cf45gavinm * is off chip it may have been the source of the #MC request and
20c794b39650d115e17a15983b6b82e46238cf45gavinm * so we must call into the memory-controller driver to give it
20c794b39650d115e17a15983b6b82e46238cf45gavinm * a chance to log errors.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (ismc) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmi_mc_logout(hdl, 1, willpanic);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#ifndef __xpv
20c794b39650d115e17a15983b6b82e46238cf45gavinmint gcpu_mca_trap_vomit_summary = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * On a native machine check exception we come here from mcetrap via
20c794b39650d115e17a15983b6b82e46238cf45gavinm * cmi_mca_trap. A machine check on one cpu of a chip does not trap others
20c794b39650d115e17a15983b6b82e46238cf45gavinm * cpus of the chip, so it is possible that another cpu on this chip could
20c794b39650d115e17a15983b6b82e46238cf45gavinm * initiate a poll while we're in the #mc handler; it is also possible that
20c794b39650d115e17a15983b6b82e46238cf45gavinm * this trap has occured during a poll on this cpu. So we must acquire
20c794b39650d115e17a15983b6b82e46238cf45gavinm * the chip-wide poll lock, but be careful to avoid deadlock.
20c794b39650d115e17a15983b6b82e46238cf45gavinm *
20c794b39650d115e17a15983b6b82e46238cf45gavinm * The 'data' pointer cannot be NULL due to init order.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinmuint64_t
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_mca_trap(cmi_hdl_t hdl, struct regs *rp)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_data_t *gcpu = cmi_hdl_getcmidata(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm kmutex_t *poll_lock = NULL;
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_mce_status_t mce;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t mcg_status;
20c794b39650d115e17a15983b6b82e46238cf45gavinm int tooklock = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cmi_hdl_rdmsr(hdl, IA32_MSR_MCG_STATUS, &mcg_status) !=
20c794b39650d115e17a15983b6b82e46238cf45gavinm CMI_SUCCESS || !(mcg_status & MCG_STATUS_MCIP))
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (0);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Synchronize with any poller from another core that may happen
20c794b39650d115e17a15983b6b82e46238cf45gavinm * to share access to one or more of the MCA banks.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (gcpu->gcpu_shared != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm poll_lock = &gcpu->gcpu_shared->gcpus_poll_lock;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (poll_lock != NULL && !mutex_owned(poll_lock)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * The lock is not owned by the thread we have
20c794b39650d115e17a15983b6b82e46238cf45gavinm * interrupted. Spin for this adaptive lock.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm while (!mutex_tryenter(poll_lock)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm while (mutex_owner(poll_lock) != NULL)
20c794b39650d115e17a15983b6b82e46238cf45gavinm ;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm tooklock = 1;
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
e3d60c9bd991a9826cbfa63b10595d44e123b9c4Adrian Frost gcpu_mca_logout(hdl, rp, 0, &mce, B_TRUE, GCPU_MPT_WHAT_MC_ERR);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (tooklock)
20c794b39650d115e17a15983b6b82e46238cf45gavinm mutex_exit(poll_lock);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm /*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * gcpu_mca_trap_vomit_summary may be set for debug assistance.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (mce.mce_nerr != 0 && gcpu_mca_trap_vomit_summary) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm cmn_err(CE_WARN, "MCE: %u errors, disp=0x%llx, "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "%u PCC (%u ok), "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "%u UC (%d ok, %u poisoned), "
20c794b39650d115e17a15983b6b82e46238cf45gavinm "%u forcefatal, %u ignored",
20c794b39650d115e17a15983b6b82e46238cf45gavinm mce.mce_nerr, (u_longlong_t)mce.mce_disp,
20c794b39650d115e17a15983b6b82e46238cf45gavinm mce.mce_npcc, mce.mce_npcc_ok,
20c794b39650d115e17a15983b6b82e46238cf45gavinm mce.mce_nuc, mce.mce_nuc_ok, mce.mce_nuc_poisoned,
20c794b39650d115e17a15983b6b82e46238cf45gavinm mce.mce_forcefatal, mce.mce_ignored);
20c794b39650d115e17a15983b6b82e46238cf45gavinm }
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (mce.mce_disp);
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye#endif
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*ARGSUSED*/
20c794b39650d115e17a15983b6b82e46238cf45gavinmvoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_faulted_enter(cmi_hdl_t hdl)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm /* Nothing to do here */
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*ARGSUSED*/
20c794b39650d115e17a15983b6b82e46238cf45gavinmvoid
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_faulted_exit(cmi_hdl_t hdl)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu_data_t *gcpu = cmi_hdl_getcmidata(hdl);
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm gcpu->gcpu_mca.gcpu_mca_flags |= GCPU_MCA_F_UNFAULTING;
20c794b39650d115e17a15983b6b82e46238cf45gavinm}
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Write the requested values to the indicated MSRs. Having no knowledge
20c794b39650d115e17a15983b6b82e46238cf45gavinm * of the model-specific requirements for writing to these model-specific
20c794b39650d115e17a15983b6b82e46238cf45gavinm * registers, we will only blindly write to those MSRs if the 'force'
20c794b39650d115e17a15983b6b82e46238cf45gavinm * argument is nonzero. That option should only be used in prototyping
20c794b39650d115e17a15983b6b82e46238cf45gavinm * and debugging.
20c794b39650d115e17a15983b6b82e46238cf45gavinm */
20c794b39650d115e17a15983b6b82e46238cf45gavinm/*ARGSUSED*/
20c794b39650d115e17a15983b6b82e46238cf45gavinmcmi_errno_t
20c794b39650d115e17a15983b6b82e46238cf45gavinmgcpu_msrinject(cmi_hdl_t hdl, cmi_mca_regs_t *regs, uint_t nregs,
20c794b39650d115e17a15983b6b82e46238cf45gavinm int force)
20c794b39650d115e17a15983b6b82e46238cf45gavinm{
20c794b39650d115e17a15983b6b82e46238cf45gavinm int i, errs = 0;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm for (i = 0; i < nregs; i++) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint_t msr = regs[i].cmr_msrnum;
20c794b39650d115e17a15983b6b82e46238cf45gavinm uint64_t val = regs[i].cmr_msrval;
20c794b39650d115e17a15983b6b82e46238cf45gavinm
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cms_present(hdl)) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm if (cms_msrinject(hdl, msr, val) != CMS_SUCCESS)
20c794b39650d115e17a15983b6b82e46238cf45gavinm errs++;
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else if (force) {
20c794b39650d115e17a15983b6b82e46238cf45gavinm errs += (cmi_hdl_wrmsr(hdl, msr, val) != CMI_SUCCESS);
20c794b39650d115e17a15983b6b82e46238cf45gavinm } else {
20c794b39650d115e17a15983b6b82e46238cf45gavinm errs++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
20c794b39650d115e17a15983b6b82e46238cf45gavinm return (errs == 0 ? CMI_SUCCESS : CMIERR_UNKNOWN);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* deconfigure gcpu_mca_init() */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liugcpu_mca_fini(cmi_hdl_t hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu gcpu_data_t *gcpu = cmi_hdl_getcmidata(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu gcpu_mca_t *mca = &gcpu->gcpu_mca;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int i;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla * CPU startup code only calls cmi_mca_init if x86_featureset indicates
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla * both MCA and MCE support (i.e., X86FSET_MCA). P5, K6, and earlier
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * processors, which have their own more primitive way of doing
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * machine checks, will not have cmi_mca_init called since their
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * CPUID information will not indicate both MCA and MCE features.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
7417cfdecea1902cef03c0d61a72df97d945925dKuriakose Kuruvilla if (!is_x86_feature(x86_featureset, X86FSET_MCA))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#ifndef __xpv
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * disable machine check in CR4
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmi_ntv_hwdisable_mce(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#endif
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&gcpu->gcpu_shared->gcpus_cfglock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu gcpu_mca_poll_fini(hdl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&gcpu->gcpu_shared->gcpus_cfglock);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * free resources allocated during init
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mca->gcpu_bank_cmci != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kmem_free(mca->gcpu_bank_cmci, sizeof (gcpu_mca_cmci_t) *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mca->gcpu_mca_nbanks);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; i < GCPU_MCA_LOGOUT_NUM; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mca->gcpu_mca_logout[i] != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kmem_free(mca->gcpu_mca_logout[i], mca->gcpu_mca_lgsz);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mca->gcpu_mca_bioscfg.bios_bankcfg != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu kmem_free(mca->gcpu_mca_bioscfg.bios_bankcfg,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sizeof (struct gcpu_bios_bankcfg) * mca->gcpu_mca_nbanks);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}