gcpu_mca.c revision 7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fe
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/cpu_module_impl.h>
#include <sys/x86_archext.h>
#include <sys/controlregs.h>
#include <sys/sysmacros.h>
#include <sys/privregs.h>
#include "gcpu.h"
/*
* x86 architecture standard banks for IA32 and compatible processors. These
* are effectively the lowest common denominators for the MCA architecture.
*/
static const gcpu_mca_bank_t gcpu_mca_banks_ia32[] = {
};
/*
* The P6-family processors have a different layout for their banks. Note that
* MC4 comes *before* MC3 by design here (Intel's design that is, not ours).
*/
static const gcpu_mca_bank_t gcpu_mca_banks_p6[] = {
};
/*
* Initialize the Machine Check Architecture (MCA) for a generic x86 CPU.
* Refer to the IA-32 Intel Architecture Software Developer's Manual,
* Volume 3: System Programming Guide, Section 14.5 for more information.
*/
void
gcpu_mca_init(void *data)
{
int i;
/*
* We're only prepared to handle processors that have an MCG_CAP
* register. P5, K6, and earlier processors, which have their own
* more primitive way of doing machine checks, are not supported.
*/
if (!(cap & MCG_CAP_CTL_P))
return; /* do nothing if IA32_MCG_CTL register is missing */
sizeof (gcpu_mca_bank_t);
} else {
sizeof (gcpu_mca_bank_t);
}
/*
* Unlike AMD's approach of assigning one MCG_CTL bit to each machine
* check register bank, Intel doesn't describe the layout of MCG_CTL or
* promise that each bit corresponds to a bank. The generic guidance
* is simply to write all ones to MCG_CTL, enabling everything that is
* present (h/w ignores writes to the undefined bit positions). The
* code right now only handles the original four banks or the P6 banks,
* so we may enable more than we know how to read on a future CPU.
* This code can be enhanced to dynamically allocate bank state based
* upon MCG_CAP.Count if RAS ever becomes important on non-AMD CPUs.
*/
for (i = 0; i < mca->gcpu_mca_nbanks; i++) {
}
}
/*
* Initialize the Machine Check Architecture (MCA) for a generic x86 CPU.
* Refer to the IA-32 Intel Architecture Software Developer's Manual,
* Volume 3: System Programming Guide, Section 14.7 for more information.
*/
int
{
if (!(gstatus & MCG_STATUS_MCIP))
return (0); /* spurious machine check trap */
/*
* Read out the bank status values, and the address and misc registers
* if they are valid. Update our fatal status based on each bank.
* Clear the MCG_STATUS register when we're done reading the h/w state.
*/
for (i = 0; i < mca->gcpu_mca_nbanks; i++) {
data->bank_addr_data = 0;
data->bank_misc_data = 0;
if (!(bstatus & MSR_MC_STATUS_VAL))
continue;
if (bstatus & MSR_MC_STATUS_ADDRV)
if (bstatus & MSR_MC_STATUS_MISCV)
}
wrmsr(IA32_MSR_MCG_STATUS, 0);
log_enter();
if (gstatus & MCG_STATUS_EIPV) {
} else {
}
/*
* Now go back through our saved state and report it using cmn_err().
* We don't bother attempting any kind of decoding here as the actual
* values are entirely specific to the actual processor in use. We
* could break out the generic bit-fields, but you're only here if
* we didn't care enough to implement FMA support for this processor.
*/
for (i = 0; i < mca->gcpu_mca_nbanks; i++) {
if (!(bstatus & MSR_MC_STATUS_VAL))
continue;
break;
case MSR_MC_STATUS_ADDRV:
i, (u_longlong_t)bstatus,
break;
case MSR_MC_STATUS_MISCV:
i, (u_longlong_t)bstatus,
break;
default:
i, (u_longlong_t)bstatus);
}
}
log_exit();
return (fatal);
}