gcpu_poll_ntv.c revision a31148363f598def767ac48c5d82e1572e44b935
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2010, Intel Corporation.
* All rights reserved.
*/
/*
* Native MCA polling. We establish an ommipresent cyclic to fire on all
* online cpus to check their MCA state and log any valid errors for
* diagnosis.
*/
#include <sys/x86_archext.h>
#include "gcpu.h"
static cyclic_id_t gcpu_mca_poll_cycid;
static volatile uint_t gcpu_mca_poll_inits;
extern int gcpu_poll_trace_always;
extern uint_t gcpu_poll_trace_nent;
/*
* Return nonzero of the given handle should poll the MCH. We stick with
* the same handle as before unless the timestamp has not been updated
* for a while. There is no need to keep a hold on the mch_poll_owner
* handle.
*/
static kmutex_t mch_poll_lock;
static hrtime_t mch_poll_timestamp;
static cmi_hdl_t mch_poll_owner;
static int
{
int dopoll = 0;
mch_poll_timestamp == 0) {
dopoll = 1;
} else if (mch_poll_owner == hdl) {
dopoll = 1;
}
if (dopoll)
return (dopoll);
}
static void
{
int willpanic;
/* Enable CMCI in first poll if is supported */
int i;
for (i = 0; i < mca->gcpu_mca_nbanks; i++) {
&ctl2);
ctl2 |= MSR_MC_CTL2_EN;
ctl2);
}
}
}
int i;
/*
* On the first cyclic poll after unfaulting a CPU we
* clear the status registers; see gcpu_faulted_exit
* for details. We don't do this if the poll was
* initiated manually (presumably from some injection
* activity).
*/
if (what == GCPU_MPT_WHAT_CYC_ERR) {
for (i = 0; i < mca->gcpu_mca_nbanks; i++) {
(void) cmi_hdl_wrmsr(hdl,
}
return;
}
}
/*
* Logout errors of the MCA banks of this cpu.
*/
if (what == GCPU_MPT_WHAT_CMCI_ERR) {
/*
* for CMCI, all banks should be scanned for log out
*/
bankmask = -1ULL;
} else {
}
if (what != GCPU_MPT_WHAT_CMCI_ERR) {
/*
* Call to the memory-controller driver which may report some
* errors not visible under the MCA (for off-chip NB).
* Since there is typically a single MCH we arrange that
* just one cpu perform this task at each cyclic fire.
*/
if (mch_pollowner(hdl))
}
/*
* In the common case any polled error is considered non-fatal,
* even if it indicates PCC or UC etc. The only condition on which
* we will panic for a polled error is if model-specific support
* forces the error to be terminal regardless of how it is
* encountered.
*/
if (willpanic) {
#ifdef DEBUG
"%u PCC (%u ok), "
"%u UC (%u ok, %u poisoned), "
"%u forcefatal, %u ignored",
#endif
fm_panic("Unrecoverable Machine-Check Exception (Polled)");
}
}
/*
* See gcpu_mca_trap for an explanation of why preemption is disabled here.
* Note that we disable preemption and then contend for an adaptive mutex -
* we could block during the mutex operation, but once we return with the
* mutex held we nust perform no operation that can block and we cannot
* be preempted so we will stay on cpu for the duration. The disabling
* of preemption also means we cannot migrate cpus once we have returned
* with the mutex held - cyclic invocations can't migrate, anyway, but
* others could if they have failed to bind before this point.
*/
static void
{
return;
}
static void
gcpu_ntv_mca_poll_cyclic(void *arg)
{
}
/*ARGSUSED*/
static void
{
/*
* Lookup and hold a handle for this cpu (any hold released in
* our offline function). If we chose not to initialize a handle
* for this cpu back at cmi_init time then this lookup will return
* NULL, so the cyh_func we appoint must be prepared for that.
*/
}
/*ARGSUSED*/
static void
{
}
static void
gcpu_ntv_mca_poll_start(void)
{
if (gcpu_mca_poll_interval == 0 || gcpu_mca_poll_inits == 0)
return;
}
/*
* gcpu_mca_poll_init is called from gcpu_mca_init for each cpu handle
* that we initialize for. It should prepare for polling by allocating
* control structures and the like, but must not kick polling off yet.
*/
void
{
}
/* deconfigure gcpu_mca_poll_init() */
void
{
}
}
void
{
}
void
{
}
void
{
}