summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4/sys/errclassify.h
blob: 0370f2ad17b461ac88f40918e0a1b5a719e1c500 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/*
 * 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
 * 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 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_ERRCLASSIFY_H
#define	_SYS_ERRCLASSIFY_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef	__cplusplus
extern "C" {
#endif

#ifndef	_ASM

#include <sys/errorq.h>

/*
 * Note that the order in the following must be kept in sync with that
 * in the sun4u DE cmd_memerr.c and with the cetypes array of us3_common.c
 */
typedef enum {
	/*
	 * The first byte (256 values) is for type and can be sequential.
	 */
	CE_DISP_UNKNOWN,
	CE_DISP_INTERMITTENT,
	CE_DISP_POSS_PERS,
	CE_DISP_PERS,
	CE_DISP_LEAKY,
	CE_DISP_POSS_STICKY,
	CE_DISP_STICKY,
	/*
	 * The next byte encodes the next action as a bitmask
	 */
	CE_ACT_DONE = 0x100,
	CE_ACT_LKYCHK = 0x200,
	CE_ACT_PTNRCHK = 0x400,
	/*
	 * Keep this as the last entry.  Not all entries of the type lookup
	 * table are used and this value is the "uninitialized" pattern.
	 */
	CE_DISP_BAD = 0xbadbad1
} ce_dispact_t;

/*
 * Extract disposition or action from a ce_dispact_t
 */
#define	CE_DISP(dispact) \
	(dispact & 0xff)
#define	CE_ACT(dispact) \
	(dispact & 0xff00)

/*
 * Short string names for classification types.
 */
#define	CE_DISP_DESC_U		"U"
#define	CE_DISP_DESC_I		"I"
#define	CE_DISP_DESC_PP		"PP"
#define	CE_DISP_DESC_P		"P"
#define	CE_DISP_DESC_L		"L"
#define	CE_DISP_DESC_PS		"PS"
#define	CE_DISP_DESC_S		"S"

/*
 * Various sun4u CPU types use different Ecache state encodings.
 * For CE classification the following unified scheme is used.
 */
#define	EC_STATE_M		0x4
#define	EC_STATE_O		0x3
#define	EC_STATE_E		0x2
#define	EC_STATE_S		0x1
#define	EC_STATE_I		0x0

/*
 * Macros to generate the initial CE classification table (in both kernel and
 * userland).  An array size CE_INITDISPTBL_SIZE of ce_dispact_t should be
 * defined and passed by name to ECC_INITDISPTBL_POPULATE which will populate
 * the array slots that are use and set the unused ones to CE_DISP_BAD.
 *
 * To perform a lookup use CE_DISPACT passing the name of the same
 * array and the afarmatch, ecstate, ce1 and ce2 information.
 *
 * Other macros defined here should not be used directly.
 *
 * CE_INITDISPTBL_INDEX will generate an index as follows:
 *
 *	<5>	afar match
 *	<4:2>	line state
 *	<1>	ce2 - CE seen on lddphys of scrub algorithm (after writeback)
 *	<0>	ce1 - CE seen on CASXA of scrub algorithm (before writeback)
 *
 * When the afar does not match line state must be zero.
 */
#define	CE_INITDISPTBL_SIZE	(1 << 6)
#define	CE_INITDISPTBL_INDEX(afarmatch, ecstate, ce1, ce2) \
	((afarmatch) << 5 | (ecstate) << 2 | (ce2) << 1 | (ce1))

#define	CE_DISPACT(array, afarmatch, ecstate, ce1, ce2) \
	(array[CE_INITDISPTBL_INDEX(afarmatch, ecstate, ce1, ce2)])

#define	CE_INITDISPTBL_POPULATE(a)					\
{									\
	int i;								\
	for (i = 0; i < CE_INITDISPTBL_SIZE; ++i)			\
		a[i] = CE_DISP_BAD;					\
/*									\
 *	   afar  ec	      ce1  ce2	initial disp and next action	\
 *	  match  state							\
 */									\
CE_DISPACT(a, 0, 0,		0, 0) = CE_DISP_UNKNOWN | CE_ACT_DONE; \
CE_DISPACT(a, 0, 0,		0, 1) = CE_DISP_POSS_STICKY | CE_ACT_PTNRCHK; \
CE_DISPACT(a, 0, 0,		1, 0) = CE_DISP_POSS_PERS | CE_ACT_LKYCHK; \
CE_DISPACT(a, 0, 0,		1, 1) = CE_DISP_POSS_STICKY | CE_ACT_PTNRCHK; \
CE_DISPACT(a, 1, EC_STATE_M,	0, 0) = CE_DISP_UNKNOWN | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_M,	0, 1) = CE_DISP_UNKNOWN | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_M,	1, 0) = CE_DISP_UNKNOWN | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_M,	1, 1) = CE_DISP_POSS_STICKY | CE_ACT_PTNRCHK; \
CE_DISPACT(a, 1, EC_STATE_O,	0, 0) = CE_DISP_UNKNOWN | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_O,	0, 1) = CE_DISP_UNKNOWN | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_O,	1, 0) = CE_DISP_UNKNOWN | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_O,	1, 1) = CE_DISP_POSS_STICKY | CE_ACT_PTNRCHK; \
CE_DISPACT(a, 1, EC_STATE_E,	0, 0) = CE_DISP_INTERMITTENT | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_E,	0, 1) = CE_DISP_UNKNOWN | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_E,	1, 0) = CE_DISP_POSS_PERS | CE_ACT_LKYCHK; \
CE_DISPACT(a, 1, EC_STATE_E,	1, 1) = CE_DISP_POSS_STICKY | CE_ACT_PTNRCHK; \
CE_DISPACT(a, 1, EC_STATE_S,	0, 0) = CE_DISP_INTERMITTENT | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_S,	0, 1) = CE_DISP_POSS_STICKY | CE_ACT_PTNRCHK; \
CE_DISPACT(a, 1, EC_STATE_S,	1, 0) = CE_DISP_POSS_PERS | CE_ACT_LKYCHK; \
CE_DISPACT(a, 1, EC_STATE_S,	1, 1) = CE_DISP_POSS_STICKY | CE_ACT_PTNRCHK; \
CE_DISPACT(a, 1, EC_STATE_I,	0, 0) = CE_DISP_UNKNOWN | CE_ACT_DONE; \
CE_DISPACT(a, 1, EC_STATE_I,	0, 1) = CE_DISP_POSS_STICKY | CE_ACT_PTNRCHK; \
CE_DISPACT(a, 1, EC_STATE_I,	1, 0) = CE_DISP_POSS_PERS | CE_ACT_LKYCHK; \
CE_DISPACT(a, 1, EC_STATE_I,	1, 1) = CE_DISP_POSS_STICKY | CE_ACT_PTNRCHK; \
}

#endif	/* !_ASM */

/*
 * Legacy error type names corresponding to the flt_status bits
 */
#define	ERR_TYPE_DESC_INTERMITTENT	"Intermittent"
#define	ERR_TYPE_DESC_PERSISTENT	"Persistent"
#define	ERR_TYPE_DESC_STICKY		"Sticky"
#define	ERR_TYPE_DESC_UNKNOWN		"Unknown"

/*
 * flt_disp for a CE will record all scrub test data for the extended
 * classification attempt.
 *
 * --------------------------------------------------------------------------
 * |            | partner |   |          | leaky   | partner | detector     |
 * | partner id | type    | - | skipcode | results | results | results      |
 * |63	      32|31     30|   |27      24|23     16|15      8|7            0|
 * --------------------------------------------------------------------------
 */
#define	CE_XDIAG_DTCRMASK		0xffULL
#define	CE_XDIAG_PTNRSHIFT		8
#define	CE_XDIAG_PTNRMASK		(0xffULL << CE_XDIAG_PTNRSHIFT)
#define	CE_XDIAG_LKYSHIFT		16
#define	CE_XDIAG_LKYMASK		(0xffULL << CE_XDIAG_LKYSHIFT)
#define	CE_XDIAG_SKIPCODESHIFT		24
#define	CE_XDIAG_SKIPCODEMASK		(0xfULL << CE_XDIAG_SKIPCODESHIFT)
#define	CE_XDIAG_PTNRTYPESHIFT		30
#define	CE_XDIAG_PTNRTYPEMASK		(0x3ULL << CE_XDIAG_PTNRTYPESHIFT)
#define	CE_XDIAG_PTNRIDSHIFT		32

/*
 * Given a CE flt_disp set the given field
 */
#define	CE_XDIAG_SETPTNRID(disp, id) \
	((disp) |= (uint64_t)(id) << CE_XDIAG_PTNRIDSHIFT)
#define	CE_XDIAG_SETPTNRTYPE(disp, type) \
	((disp) |= (uint64_t)type << CE_XDIAG_PTNRTYPESHIFT)
#define	CE_XDIAG_SETSKIPCODE(disp, code) \
	((disp) |= (uint64_t)code << CE_XDIAG_SKIPCODESHIFT)
#define	CE_XDIAG_SETLKYINFO(disp, result) \
	((disp) |= (uint64_t)result << CE_XDIAG_LKYSHIFT)
#define	CE_XDIAG_SETPTNRINFO(disp, result) \
	((disp) |= (uint64_t)result << CE_XDIAG_PTNRSHIFT)
#define	CE_XDIAG_SETDTCRINFO(disp, result) \
	((disp) |= (uint64_t)result)

/*
 * Given a CE flt_disp extract the requested component
 */
#define	CE_XDIAG_DTCRINFO(disp)	((disp) & CE_XDIAG_DTCRMASK)
#define	CE_XDIAG_PTNRINFO(disp)	(((disp) & CE_XDIAG_PTNRMASK) >> \
    CE_XDIAG_PTNRSHIFT)
#define	CE_XDIAG_LKYINFO(disp)	(((disp) & CE_XDIAG_LKYMASK) >> \
    CE_XDIAG_LKYSHIFT)
#define	CE_XDIAG_SKIPCODE(disp)	(((disp) & CE_XDIAG_SKIPCODEMASK) >> \
    CE_XDIAG_SKIPCODESHIFT)
#define	CE_XDIAG_PTNRTYPE(disp)	(((disp) & CE_XDIAG_PTNRTYPEMASK) >> \
    CE_XDIAG_PTNRTYPESHIFT)
#define	CE_XDIAG_PTNRID(disp)	((disp) >> CE_XDIAG_PTNRIDSHIFT)

/*
 * Format of individual detector/partner/leaky test results.  CE_XDIAG_EXTALG
 * in the detector case indicates that the extended classification algorithm
 * has been applied;  common code uses this to distinguish between old and new.
 * In the partner check and leaky check cases CE_XDIAG_EXTALG is used to
 * indicate that the given test has run and recorded its results in its
 * result field.
 */
#define	CE_XDIAG_STATE_MASK	0x7	/* Low 3 bits are for MOESI state */
#define	CE_XDIAG_AFARMATCH	0x08	/* Line at e$ index matched AFAR */
#define	CE_XDIAG_NOLOGOUT	0x10	/* Logout data unavailable */
#define	CE_XDIAG_CE1		0x20	/* CE logged on casx during scrub */
#define	CE_XDIAG_CE2		0x40	/* CE logged on post-scrub reread */
#define	CE_XDIAG_EXTALG		0x80	/* Extended algorithm applied */

/*
 * Extract classification information for detector/partner.  Expects
 * a value from one of CE_XDIAG_{DTCR,PTNR,LKY}_INFO.
 */
#define	CE_XDIAG_AFARMATCHED(c)		(((c) & CE_XDIAG_AFARMATCH) != 0)
#define	CE_XDIAG_LOGOUTVALID(c)		(((c) & CE_XDIAG_NOLOGOUT) == 0)
#define	CE_XDIAG_CE1SEEN(c)		(((c) & CE_XDIAG_CE1) != 0)
#define	CE_XDIAG_CE2SEEN(c)		(((c) & CE_XDIAG_CE2) != 0)
#define	CE_XDIAG_STATE(c)		(CE_XDIAG_AFARMATCHED(c) ? \
	((c) & CE_XDIAG_STATE_MASK) : 0)
#define	CE_XDIAG_EXT_ALG_APPLIED(c)	(((c) & CE_XDIAG_EXTALG) != 0)

/*
 * A leaky or partner test is considered valid if the line was not present
 * in cache, or was present but Invalid, at the time of the additional scrub.
 */
#define	CE_XDIAG_TESTVALID(c) (CE_XDIAG_EXT_ALG_APPLIED(c) && \
	(!CE_XDIAG_AFARMATCHED(c) || CE_XDIAG_STATE(c) == EC_STATE_I))

/*
 * Skipcodes - reasons for not applying extended diags; 4 bits
 */
#define	CE_XDIAG_SKIP_NOPP		0x1	/* Can't lookup page pointer */
#define	CE_XDIAG_SKIP_PAGEDET		0x2	/* Page deteriorating/retired */
#define	CE_XDIAG_SKIP_NOTMEM		0x3	/* AFAR is not memory */
#define	CE_XDIAG_SKIP_DUPFAIL		0x4	/* errorq recirculate failed */
#define	CE_XDIAG_SKIP_NOPTNR		0x5	/* no suitable partner avail */
#define	CE_XDIAG_SKIP_UNIPROC		0x6	/* test needs 2 or more cpus */
#define	CE_XDIAG_SKIP_ACTBAD		0x7	/* bad action lookup - bug */
#define	CE_XDIAG_SKIP_NOSCRUB		0x8	/* detector did not scrub */

/*
 * Partner type information.
 */
#define	CE_XDIAG_PTNR_REMOTE	0x0	/* partner in different lgroup */
#define	CE_XDIAG_PTNR_LOCAL	0x1	/* partner in same lgroup */
#define	CE_XDIAG_PTNR_SIBLING	0x2	/* partner is a sibling core */
#define	CE_XDIAG_PTNR_SELF	0x3	/* partnered self */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_ERRCLASSIFY_H */