gcpu.h revision 20c794b39650d115e17a15983b6b82e46238cf45
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#ifndef _GCPU_H
28#define	_GCPU_H
29
30#pragma ident	"%Z%%M%	%I%	%E% SMI"
31
32#include <sys/types.h>
33#include <sys/cpu_module_impl.h>
34#include <sys/cpu_module_ms.h>
35#include <sys/ksynch.h>
36#include <sys/systm.h>
37#include <sys/fm/util.h>
38
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43#define	GCPU_MCA_ERRS_PERCPU	10	/* errorq slots per cpu */
44#define	GCPU_MCA_MIN_ERRORS	30	/* minimum total errorq slots */
45#define	GCPU_MCA_MAX_ERRORS	100	/* maximum total errorq slots */
46
47typedef struct gcpu_data gcpu_data_t;
48
49#define	GCPU_ERRCODE_MASK_ALL		0xffff
50
51typedef struct gcpu_error_disp {
52	const char *ged_class_fmt;	/* ereport class formatter (last bit) */
53	const char *ged_compound_fmt;	/* compound error formatter */
54	uint64_t ged_ereport_members;	/* ereport payload members */
55	uint16_t ged_errcode_mask_on;	/* errcode bits that must be set ... */
56	uint16_t ged_errcode_mask_off;	/* ... and must be clear for a match */
57} gcpu_error_disp_t;
58
59/*
60 * For errorq_dispatch we need to have a single contiguous structure
61 * capturing all our logout data.  We do not know in advance how many
62 * error detector banks there are in this cpu model, so we'll manually
63 * allocate additional space for the gcl_banks array below.
64 */
65typedef struct gcpu_bank_logout {
66	uint64_t gbl_status;		/* MCi_STATUS value */
67	uint64_t gbl_addr;		/* MCi_ADDR value */
68	uint64_t gbl_misc;		/* MCi_MISC value */
69	uint64_t gbl_disp;		/* Error disposition for this bank */
70	uint32_t gbl_clrdefcnt;		/* Count of deferred status clears */
71} gcpu_bank_logout_t;
72
73/*
74 * The data structure we "logout" all error telemetry from all banks of
75 * a cpu to.  The gcl_data array declared with 1 member below will actually
76 * have gcl_nbanks members - variable with the actual cpu model present.
77 * After the gcl_data array there is a further model-specific array that
78 * may be allocated, and gcl_ms_logout will point to that if present.
79 * This cpu logout data must form one contiguous chunk of memory for
80 * dispatch with errorq_dispatch.
81 */
82typedef struct gcpu_logout {
83	gcpu_data_t *gcl_gcpu;		/* pointer to per-cpu gcpu_data_t */
84	uintptr_t gcl_ip;		/* instruction pointer from #mc trap */
85	uint64_t gcl_timestamp;		/* gethrtime() at logout */
86	uint64_t gcl_mcg_status;	/* MCG_STATUS register value */
87	uint64_t gcl_flags;		/* Flags */
88	pc_t gcl_stack[FM_STK_DEPTH];	/* saved stack trace, if any */
89	int gcl_stackdepth;		/* saved stack trace depth */
90	int gcl_nbanks;			/* number of banks in array below */
91	void *gcl_ms_logout;		/* Model-specific area after gcl_data */
92	gcpu_bank_logout_t gcl_data[1];	/* Bank logout areas - must be last */
93} gcpu_logout_t;
94
95/*
96 * gcl_flag values
97 */
98#define	GCPU_GCL_F_PRIV		0x1	/* #MC during privileged code */
99#define	GCPU_GCL_F_TES_P	0x2	/* MCG_CAP indicates TES_P */
100
101struct gcpu_bios_bankcfg {
102	uint64_t bios_bank_ctl;
103	uint64_t bios_bank_status;
104	uint64_t bios_bank_addr;
105	uint64_t bios_bank_misc;
106};
107
108struct gcpu_bios_cfg {
109	uint64_t bios_mcg_cap;
110	uint64_t bios_mcg_ctl;
111	struct gcpu_bios_bankcfg *bios_bankcfg;
112};
113
114#define	GCPU_MPT_WHAT_CYC_ERR		0	/* cyclic-induced poll */
115#define	GCPU_MPT_WHAT_POKE_ERR		1	/* manually-induced poll */
116#define	GCPU_MPT_WHAT_UNFAULTING	2	/* discarded error state */
117
118typedef struct gcpu_mca_poll_trace {
119	hrtime_t mpt_when;		/* timestamp of event */
120	uint8_t mpt_what;		/* GCPU_MPT_WHAT_* (which event?) */
121	uint8_t mpt_nerr;		/* number of errors discovered */
122	uint16_t mpt_pad1;
123	uint32_t mpt_pad2;
124} gcpu_mca_poll_trace_t;
125
126typedef struct gcpu_mca_poll_trace_ctl {
127	gcpu_mca_poll_trace_t *mptc_tbufs;	/* trace buffers */
128	uint_t mptc_curtrace;			/* last buffer filled */
129} gcpu_mca_poll_trace_ctl_t;
130
131/* Index for gcpu_mca_logout array below */
132#define	GCPU_MCA_LOGOUT_EXCEPTION	0	/* area for #MC */
133#define	GCPU_MCA_LOGOUT_POLLER_1	1	/* next/prev poll area */
134#define	GCPU_MCA_LOGOUT_POLLER_2	2	/* prev/next poll area */
135#define	GCPU_MCA_LOGOUT_NUM		3
136
137typedef struct gcpu_mca {
138	gcpu_logout_t *gcpu_mca_logout[GCPU_MCA_LOGOUT_NUM];
139	uint32_t gcpu_mca_nextpoll_idx;	/* logout area for next poll */
140	struct gcpu_bios_cfg gcpu_mca_bioscfg;
141	uint_t gcpu_mca_nbanks;
142	uint32_t gcpu_actv_banks;	/* MCA banks we initialized */
143	size_t gcpu_mca_lgsz;		/* size of gcpu_mca_logout structs */
144	uint_t gcpu_mca_flags;		/* GCPU_MCA_F_* */
145	hrtime_t gcpu_mca_lastpoll;
146	gcpu_mca_poll_trace_ctl_t gcpu_mca_polltrace;
147} gcpu_mca_t;
148
149typedef struct gcpu_mce_status {
150	uint_t mce_nerr;	/* total errors found in logout of all banks */
151	uint64_t mce_disp;	/* Disposition information */
152	uint_t mce_npcc;	/* number of errors with PCC */
153	uint_t mce_npcc_ok;	/* PCC with CMS_ERRSCOPE_CURCONTEXT_OK */
154	uint_t mce_nuc;		/* number of errors with UC */
155	uint_t mce_nuc_ok;	/* UC with CMS_ERRSCOPE_CLEARED_UC */
156	uint_t mce_nuc_poisoned; /* UC with CMS_ERRSCOPE_POISONED */
157	uint_t mce_forcefatal;	/* CMS_ERRSCOPE_FORCE_FATAL */
158	uint_t mce_ignored;	/* CMS_ERRSCOPE_IGNORE_ERR */
159} gcpu_mce_status_t;
160
161/*
162 * Flags for gcpu_mca_flags
163 */
164#define	GCPU_MCA_F_UNFAULTING		0x1	/* CPU exiting faulted state */
165
166/*
167 * State shared by all cpus on a chip
168 */
169struct gcpu_chipshared {
170	kmutex_t gcpus_cfglock;		/* serial MCA config from chip cores */
171	kmutex_t gcpus_poll_lock;	/* serialize pollers on the same chip */
172	uint32_t gcpus_actv_banks;	/* MCA bank numbers active on chip */
173};
174
175struct gcpu_data {
176	gcpu_mca_t gcpu_mca;			/* MCA state for this CPU */
177	cmi_hdl_t gcpu_hdl;			/* associated handle */
178	struct gcpu_chipshared *gcpu_shared;	/* Shared state for the chip */
179};
180
181#ifdef _KERNEL
182
183struct regs;
184
185/*
186 * CMI implementation
187 */
188extern int gcpu_init(cmi_hdl_t, void **);
189extern void gcpu_post_startup(cmi_hdl_t);
190extern void gcpu_post_mpstartup(cmi_hdl_t);
191extern void gcpu_faulted_enter(cmi_hdl_t);
192extern void gcpu_faulted_exit(cmi_hdl_t);
193extern void gcpu_mca_init(cmi_hdl_t);
194extern cmi_errno_t gcpu_msrinject(cmi_hdl_t, cmi_mca_regs_t *, uint_t, int);
195extern uint64_t gcpu_mca_trap(cmi_hdl_t, struct regs *);
196extern void gcpu_hdl_poke(cmi_hdl_t);
197
198/*
199 * Local functions
200 */
201extern void gcpu_mca_poll_init(cmi_hdl_t);
202extern void gcpu_mca_poll_start(cmi_hdl_t);
203extern void gcpu_mca_logout(cmi_hdl_t, struct regs *, uint64_t,
204    gcpu_mce_status_t *, boolean_t);
205
206#endif /* _KERNEL */
207
208#ifdef __cplusplus
209}
210#endif
211
212#endif /* _GCPU_H */
213