1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Machine check exception header file.
4  *
5  * Copyright 2013 IBM Corporation
6  * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
7  */
8 
9 #ifndef __ASM_PPC64_MCE_H__
10 #define __ASM_PPC64_MCE_H__
11 
12 #include <linux/bitops.h>
13 
14 enum MCE_Version {
15 	MCE_V1 = 1,
16 };
17 
18 enum MCE_Severity {
19 	MCE_SEV_NO_ERROR = 0,
20 	MCE_SEV_WARNING = 1,
21 	MCE_SEV_SEVERE = 2,
22 	MCE_SEV_FATAL = 3,
23 };
24 
25 enum MCE_Disposition {
26 	MCE_DISPOSITION_RECOVERED = 0,
27 	MCE_DISPOSITION_NOT_RECOVERED = 1,
28 };
29 
30 enum MCE_Initiator {
31 	MCE_INITIATOR_UNKNOWN = 0,
32 	MCE_INITIATOR_CPU = 1,
33 	MCE_INITIATOR_PCI = 2,
34 	MCE_INITIATOR_ISA = 3,
35 	MCE_INITIATOR_MEMORY= 4,
36 	MCE_INITIATOR_POWERMGM = 5,
37 };
38 
39 enum MCE_ErrorType {
40 	MCE_ERROR_TYPE_UNKNOWN = 0,
41 	MCE_ERROR_TYPE_UE = 1,
42 	MCE_ERROR_TYPE_SLB = 2,
43 	MCE_ERROR_TYPE_ERAT = 3,
44 	MCE_ERROR_TYPE_TLB = 4,
45 	MCE_ERROR_TYPE_USER = 5,
46 	MCE_ERROR_TYPE_RA = 6,
47 	MCE_ERROR_TYPE_LINK = 7,
48 	MCE_ERROR_TYPE_DCACHE = 8,
49 	MCE_ERROR_TYPE_ICACHE = 9,
50 };
51 
52 enum MCE_ErrorClass {
53 	MCE_ECLASS_UNKNOWN = 0,
54 	MCE_ECLASS_HARDWARE,
55 	MCE_ECLASS_HARD_INDETERMINATE,
56 	MCE_ECLASS_SOFTWARE,
57 	MCE_ECLASS_SOFT_INDETERMINATE,
58 };
59 
60 enum MCE_UeErrorType {
61 	MCE_UE_ERROR_INDETERMINATE = 0,
62 	MCE_UE_ERROR_IFETCH = 1,
63 	MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
64 	MCE_UE_ERROR_LOAD_STORE = 3,
65 	MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
66 };
67 
68 enum MCE_SlbErrorType {
69 	MCE_SLB_ERROR_INDETERMINATE = 0,
70 	MCE_SLB_ERROR_PARITY = 1,
71 	MCE_SLB_ERROR_MULTIHIT = 2,
72 };
73 
74 enum MCE_EratErrorType {
75 	MCE_ERAT_ERROR_INDETERMINATE = 0,
76 	MCE_ERAT_ERROR_PARITY = 1,
77 	MCE_ERAT_ERROR_MULTIHIT = 2,
78 };
79 
80 enum MCE_TlbErrorType {
81 	MCE_TLB_ERROR_INDETERMINATE = 0,
82 	MCE_TLB_ERROR_PARITY = 1,
83 	MCE_TLB_ERROR_MULTIHIT = 2,
84 };
85 
86 enum MCE_UserErrorType {
87 	MCE_USER_ERROR_INDETERMINATE = 0,
88 	MCE_USER_ERROR_TLBIE = 1,
89 	MCE_USER_ERROR_SCV = 2,
90 };
91 
92 enum MCE_RaErrorType {
93 	MCE_RA_ERROR_INDETERMINATE = 0,
94 	MCE_RA_ERROR_IFETCH = 1,
95 	MCE_RA_ERROR_IFETCH_FOREIGN = 2,
96 	MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH = 3,
97 	MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN = 4,
98 	MCE_RA_ERROR_LOAD = 5,
99 	MCE_RA_ERROR_STORE = 6,
100 	MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 7,
101 	MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN = 8,
102 	MCE_RA_ERROR_LOAD_STORE_FOREIGN = 9,
103 };
104 
105 enum MCE_LinkErrorType {
106 	MCE_LINK_ERROR_INDETERMINATE = 0,
107 	MCE_LINK_ERROR_IFETCH_TIMEOUT = 1,
108 	MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT = 2,
109 	MCE_LINK_ERROR_LOAD_TIMEOUT = 3,
110 	MCE_LINK_ERROR_STORE_TIMEOUT = 4,
111 	MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT = 5,
112 };
113 
114 struct machine_check_event {
115 	enum MCE_Version	version:8;
116 	u8			in_use;
117 	enum MCE_Severity	severity:8;
118 	enum MCE_Initiator	initiator:8;
119 	enum MCE_ErrorType	error_type:8;
120 	enum MCE_ErrorClass	error_class:8;
121 	enum MCE_Disposition	disposition:8;
122 	bool			sync_error;
123 	u16			cpu;
124 	u64			gpr3;
125 	u64			srr0;
126 	u64			srr1;
127 	union {
128 		struct {
129 			enum MCE_UeErrorType ue_error_type:8;
130 			u8		effective_address_provided;
131 			u8		physical_address_provided;
132 			u8		ignore_event;
133 			u8		reserved_1[4];
134 			u64		effective_address;
135 			u64		physical_address;
136 			u8		reserved_2[8];
137 		} ue_error;
138 
139 		struct {
140 			enum MCE_SlbErrorType slb_error_type:8;
141 			u8		effective_address_provided;
142 			u8		reserved_1[6];
143 			u64		effective_address;
144 			u8		reserved_2[16];
145 		} slb_error;
146 
147 		struct {
148 			enum MCE_EratErrorType erat_error_type:8;
149 			u8		effective_address_provided;
150 			u8		reserved_1[6];
151 			u64		effective_address;
152 			u8		reserved_2[16];
153 		} erat_error;
154 
155 		struct {
156 			enum MCE_TlbErrorType tlb_error_type:8;
157 			u8		effective_address_provided;
158 			u8		reserved_1[6];
159 			u64		effective_address;
160 			u8		reserved_2[16];
161 		} tlb_error;
162 
163 		struct {
164 			enum MCE_UserErrorType user_error_type:8;
165 			u8		effective_address_provided;
166 			u8		reserved_1[6];
167 			u64		effective_address;
168 			u8		reserved_2[16];
169 		} user_error;
170 
171 		struct {
172 			enum MCE_RaErrorType ra_error_type:8;
173 			u8		effective_address_provided;
174 			u8		reserved_1[6];
175 			u64		effective_address;
176 			u8		reserved_2[16];
177 		} ra_error;
178 
179 		struct {
180 			enum MCE_LinkErrorType link_error_type:8;
181 			u8		effective_address_provided;
182 			u8		reserved_1[6];
183 			u64		effective_address;
184 			u8		reserved_2[16];
185 		} link_error;
186 	} u;
187 };
188 
189 struct mce_error_info {
190 	enum MCE_ErrorType error_type:8;
191 	union {
192 		enum MCE_UeErrorType ue_error_type:8;
193 		enum MCE_SlbErrorType slb_error_type:8;
194 		enum MCE_EratErrorType erat_error_type:8;
195 		enum MCE_TlbErrorType tlb_error_type:8;
196 		enum MCE_UserErrorType user_error_type:8;
197 		enum MCE_RaErrorType ra_error_type:8;
198 		enum MCE_LinkErrorType link_error_type:8;
199 	} u;
200 	enum MCE_Severity	severity:8;
201 	enum MCE_Initiator	initiator:8;
202 	enum MCE_ErrorClass	error_class:8;
203 	bool			sync_error;
204 	bool			ignore_event;
205 };
206 
207 #define MAX_MC_EVT	10
208 
209 struct mce_info {
210 	int mce_nest_count;
211 	struct machine_check_event mce_event[MAX_MC_EVT];
212 	/* Queue for delayed MCE events. */
213 	int mce_queue_count;
214 	struct machine_check_event mce_event_queue[MAX_MC_EVT];
215 	/* Queue for delayed MCE UE events. */
216 	int mce_ue_count;
217 	struct machine_check_event  mce_ue_event_queue[MAX_MC_EVT];
218 };
219 
220 /* Release flags for get_mce_event() */
221 #define MCE_EVENT_RELEASE	true
222 #define MCE_EVENT_DONTRELEASE	false
223 
224 struct pt_regs;
225 struct notifier_block;
226 
227 extern void save_mce_event(struct pt_regs *regs, long handled,
228 			   struct mce_error_info *mce_err, uint64_t nip,
229 			   uint64_t addr, uint64_t phys_addr);
230 extern int get_mce_event(struct machine_check_event *mce, bool release);
231 extern void release_mce_event(void);
232 extern void machine_check_queue_event(void);
233 extern void machine_check_print_event_info(struct machine_check_event *evt,
234 					   bool user_mode, bool in_guest);
235 unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr);
236 extern void mce_common_process_ue(struct pt_regs *regs,
237 				  struct mce_error_info *mce_err);
238 void mce_irq_work_queue(void);
239 int mce_register_notifier(struct notifier_block *nb);
240 int mce_unregister_notifier(struct notifier_block *nb);
241 
242 #ifdef CONFIG_PPC_BOOK3S_64
243 void mce_run_irq_context_handlers(void);
244 #else
mce_run_irq_context_handlers(void)245 static inline void mce_run_irq_context_handlers(void) { };
246 #endif /* CONFIG_PPC_BOOK3S_64 */
247 
248 #ifdef CONFIG_PPC_BOOK3S_64
249 void set_mce_pending_irq_work(void);
250 void clear_mce_pending_irq_work(void);
251 #endif /* CONFIG_PPC_BOOK3S_64 */
252 
253 #ifdef CONFIG_PPC_BOOK3S_64
254 void flush_and_reload_slb(void);
255 void flush_erat(void);
256 long __machine_check_early_realmode_p7(struct pt_regs *regs);
257 long __machine_check_early_realmode_p8(struct pt_regs *regs);
258 long __machine_check_early_realmode_p9(struct pt_regs *regs);
259 long __machine_check_early_realmode_p10(struct pt_regs *regs);
260 #endif /* CONFIG_PPC_BOOK3S_64 */
261 
262 #ifdef CONFIG_PPC_BOOK3S_64
263 void mce_init(void);
264 #else
mce_init(void)265 static inline void mce_init(void) { };
266 #endif /* CONFIG_PPC_BOOK3S_64 */
267 
268 #endif /* __ASM_PPC64_MCE_H__ */
269