/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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.
 */

/*
 * eversholt rules for generic x86 MCA
 *
 * Most propogations are generated by preprocessor macros.  The event
 * declarations are deliberately not part of the propogation macros
 * so that we know we have full coverage - propogations defined without
 * events, or events not used in propogations, will produce compiler
 * whinges.
 */

#pragma dictionary "GMCA"

/*
 * Ereports for Simple error codes.
 */

#define SMPL_EVENT(leafclass) \
	event ereport.cpu.generic-x86.leafclass@chip/core/strand { within(1s) }

SMPL_EVENT(unknown);	
SMPL_EVENT(unclassified);
SMPL_EVENT(microcode_rom_parity);
SMPL_EVENT(external);
SMPL_EVENT(frc);
SMPL_EVENT(internal_timer);
SMPL_EVENT(internal_parity);
SMPL_EVENT(internal_unclassified);

/*
 * Propogations for all but "external" and "unknown" simple errors.
 * If the error is uncorrected we produce a fault immediately by incrementing
 * by N+1, otherwise we declare a fault when the SERD engine trips.
 */

#define	SMPL_N	3

engine serd.cpu.generic-x86.simple@chip/core/strand, N=SMPL_N, T=72h;
event fault.cpu.generic-x86.internal@chip/core/strand,
    engine=serd.cpu.generic-x86.simple@chip/core/strand;

prop fault.cpu.generic-x86.internal@chip/core/strand
    { payloadprop("error_uncorrected") == 1 ?
	setserdincrement(SMPL_N + 1) : 1 } (1)->
    ereport.cpu.generic-x86.microcode_rom_parity@chip/core/strand,
    ereport.cpu.generic-x86.internal_timer@chip/core/strand,
    ereport.cpu.generic-x86.internal_parity@chip/core/strand,
    ereport.cpu.generic-x86.unclassified@chip/core/strand,
    ereport.cpu.generic-x86.internal_unclassified@chip/core/strand,
    ereport.cpu.generic-x86.frc@chip/core/strand;

/*
 * Ereports for Compound error codes.  These are in pairs "foo" and "foo_uc"
 * for the corrected and uncorrected version of each error type.  All are
 * detected at chip/core[/strand].
 */

#define	CMPND_EVENT(leafclass) \
	event ereport.cpu.generic-x86.leafclass@chip/core/strand \
	{ within(1s) }; \
	event ereport.cpu.generic-x86.leafclass/**/_uc@chip/core/strand \
	{ within(1s) }

/*
 * Ereports for Compound error codes - generic memory hierarchy errors
 */
CMPND_EVENT(l0cache);
CMPND_EVENT(l1cache);
CMPND_EVENT(l2cache);
CMPND_EVENT(cache);

/*
 * Ereports for Compound error codes - TLB errors
 */
CMPND_EVENT(l0dtlb);
CMPND_EVENT(l1dtlb);
CMPND_EVENT(l2dtlb);
CMPND_EVENT(dtlb);

CMPND_EVENT(l0itlb);
CMPND_EVENT(l1itlb);
CMPND_EVENT(l2itlb);
CMPND_EVENT(itlb);

CMPND_EVENT(l0tlb);
CMPND_EVENT(l1tlb);
CMPND_EVENT(l2tlb);
CMPND_EVENT(tlb);

/*
 * Ereports for Compound error codes - memory hierarchy errors
 */
CMPND_EVENT(l0dcache);
CMPND_EVENT(l1dcache);
CMPND_EVENT(l2dcache);
CMPND_EVENT(dcache);

CMPND_EVENT(l0icache);
CMPND_EVENT(l1icache);
CMPND_EVENT(l2icache);
CMPND_EVENT(icache);

/*
 * Ereports for Compound error codes - bus and interconnect errors
 */
CMPND_EVENT(bus_interconnect);
CMPND_EVENT(bus_interconnect_memory);
CMPND_EVENT(bus_interconnect_io);
CMPND_EVENT(mc);

/*
 * Compound error propogations
 *
 * We resist the temptation propogate, for example, a single dcache fault
 * to all ereports mentioning dcache (l0dcache, l1dcache, l2dcache, dcache).
 * Instead we will diagnose a distinct fault for each possible cache level,
 * whether or not current chips have dcaches at all levels.
 *
 * Corrected errors are SERDed and produce a fault when the engine fires;
 * the same fault is diagnosed immediately for a corresponding uncorrected
 * error by incrementing the serd engine by n + 1.
 */

#define	CMPND_FLT_PROP_1(erptleaf, fltleaf, n, t) \
	engine serd.cpu.generic-x86.fltleaf@chip/core/strand, N=n, T=t;	\
	event fault.cpu.generic-x86.fltleaf@chip/core/strand,		\
	    engine=serd.cpu.generic-x86.fltleaf@chip/core/strand;	\
									\
        prop fault.cpu.generic-x86.fltleaf@chip/core/strand (0)->	\
            ereport.cpu.generic-x86.erptleaf@chip/core/strand;		\
	prop fault.cpu.generic-x86.fltleaf@chip/core/strand		\
	    { setserdincrement(n + 1) } (0)->				\
	    ereport.cpu.generic-x86.erptleaf/**/_uc@chip/core/strand

#define	CMPND_FLT_PROP_2(erptleaf, fltleaf, n, t) \
	engine serd.cpu.generic-x86.fltleaf@chip/core/strand, N=n, T=t;	\
	event fault.cpu.generic-x86.fltleaf@chip/core/strand, retire=0,	\
	    response=0, engine=serd.cpu.generic-x86.fltleaf@chip/core/strand;\
									\
        prop fault.cpu.generic-x86.fltleaf@chip/core/strand (0)->	\
            ereport.cpu.generic-x86.erptleaf@chip/core/strand;		\
	prop fault.cpu.generic-x86.fltleaf@chip/core/strand		\
	    { setserdincrement(n + 1) } (0)->				\
	    ereport.cpu.generic-x86.erptleaf/**/_uc@chip/core/strand

CMPND_FLT_PROP_1(l0cache, l0cache, 3, 72h);
CMPND_FLT_PROP_1(l1cache, l1cache, 3, 72h);
CMPND_FLT_PROP_1(l2cache, l2cache, 3, 72h);
CMPND_FLT_PROP_1(cache, cache, 12, 72h);

CMPND_FLT_PROP_1(l0dtlb, l0dtlb, 3, 72h);
CMPND_FLT_PROP_1(l1dtlb, l1dtlb, 3, 72h);
CMPND_FLT_PROP_1(l2dtlb, l2dtlb, 3, 72h);
CMPND_FLT_PROP_1(dtlb, dtlb, 12, 72h);

CMPND_FLT_PROP_1(l0itlb, l0itlb, 3, 72h);
CMPND_FLT_PROP_1(l1itlb, l1itlb, 3, 72h);
CMPND_FLT_PROP_1(l2itlb, l2itlb, 3, 72h);
CMPND_FLT_PROP_1(itlb, itlb, 12, 72h);

CMPND_FLT_PROP_1(l0tlb, l0tlb, 3, 72h);
CMPND_FLT_PROP_1(l1tlb, l1tlb, 3, 72h);
CMPND_FLT_PROP_1(l2tlb, l2tlb, 3, 72h);
CMPND_FLT_PROP_1(tlb, tlb, 12, 72h);

CMPND_FLT_PROP_1(l0dcache, l0dcache, 3, 72h);
CMPND_FLT_PROP_1(l1dcache, l1dcache, 3, 72h);
CMPND_FLT_PROP_1(l2dcache, l2dcache, 3, 72h);
CMPND_FLT_PROP_1(dcache, dcache, 12, 72h);

CMPND_FLT_PROP_1(l0icache, l0icache, 3, 72h);
CMPND_FLT_PROP_1(l1icache, l1icache, 3, 72h);
CMPND_FLT_PROP_1(l2icache, l2icache, 3, 72h);
CMPND_FLT_PROP_1(icache, icache, 12, 72h);

CMPND_FLT_PROP_2(bus_interconnect, bus_interconnect, 10, 72h);
CMPND_FLT_PROP_2(bus_interconnect_memory, bus_interconnect_memory, 10, 72h);
CMPND_FLT_PROP_2(bus_interconnect_io, bus_interconnect_io, 10, 72h);

CMPND_FLT_PROP_2(mc, mc, 10, 72h);

/*
 * Discards - not enough info to diagnose.
 */
event upset.discard@chip/core/strand;

prop upset.discard@chip/core/strand (0)->
    ereport.cpu.generic-x86.external@chip/core/strand,
    ereport.cpu.generic-x86.unknown@chip/core/strand;