xref: /linux/arch/alpha/kernel/err_tsunami.c (revision ea2b073b4f31f334354479b993160788610c779d)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Machine check handling for Tsunami/Typhoon systems.
4  * Author: Magnus Lindholm <linmag7@gmail.com>
5  * Based on Titan error handling by Jeff Wiedemeier (Compaq).
6  * Register definitions: 21272 Hardware Reference Manual, revision 4.0.
7  */
8 #include <linux/init.h>
9 #include <linux/pci.h>
10 #include <linux/sched.h>
11 #include <asm/io.h>
12 #include <asm/core_tsunami.h>
13 #include <asm/smp.h>
14 #include <asm/err_common.h>
15 #include <asm/irq_regs.h>
16 #include "err_impl.h"
17 #include "proto.h"
18 #include "pci_impl.h"
19 
20 #define TSUNAMI_PERROR_ERRMASK	0xdffUL
21 #define TSUNAMI_PERROR_ECCMASK	(perror_m_uecc | perror_m_cre)
22 #define TSUNAMI_PERROR_INV	(1UL << 51)
23 #define TSUNAMI_MISC_NXM		(1UL << 28)
24 
25 static int
26 tsunami_frame_valid(struct el_common *header, size_t size)
27 {
28 	return !((header->sys_offset | header->size) & 7) &&
29 	       header->sys_offset >= sizeof(*header) &&
30 	       header->sys_offset <= header->size &&
31 	       size <= header->size - header->sys_offset;
32 }
33 
34 static int
35 tsunami_parse_p_perror(int which, u64 perror, int print)
36 {
37 	static const char * const errors[] = {
38 		"Lost error", "SERR asserted", "PERR asserted",
39 		"Delayed-completion retry timeout", "Invalid scatter-gather PTE",
40 		"Address parity error", "Target abort", "Read data parity error",
41 		"No DEVSEL (master abort)", NULL,
42 		"Uncorrectable ECC error", "Correctable ECC error"
43 	};
44 	static const char * const pci_cmd[] = {
45 		"Interrupt acknowledge", "Special cycle", "I/O read", "I/O write",
46 		"Reserved", "Reserved", "Memory read", "Memory write",
47 		"Reserved", "Reserved", "Configuration read", "Configuration write",
48 		"Memory read multiple", "Dual address cycle",
49 		"Memory read line", "Memory write and invalidate"
50 	};
51 	unsigned long addr;
52 	unsigned int cmd;
53 	int i;
54 
55 	if (!(perror & TSUNAMI_PERROR_ERRMASK))
56 		return MCHK_DISPOSITION_UNKNOWN_ERROR;
57 	/* Do not import Titan's BIOS master-abort dismissal policy. */
58 	if (!print)
59 		return MCHK_DISPOSITION_REPORT;
60 
61 	printk("%s  Pchip %d PERROR: %016llx\n", err_print_prefix, which, perror);
62 	for (i = 0; i < ARRAY_SIZE(errors); i++)
63 		if ((perror & TSUNAMI_PERROR_ERRMASK & (1UL << i)) && errors[i])
64 			printk("%s    %s\n", err_print_prefix, errors[i]);
65 
66 	/*
67 	 * INV invalidates SYN, CMD and ADDR. HRM 8.8.2.6 leaves command/address
68 	 * undefined whenever SERR is set, including with other error bits.
69 	 */
70 	if (perror & (TSUNAMI_PERROR_INV | perror_m_serr)) {
71 		printk("%s    Transaction information unavailable\n", err_print_prefix);
72 		return MCHK_DISPOSITION_REPORT;
73 	}
74 	cmd = (perror & perror_m_cmd) >> 52;
75 	/*
76 	 * Table 10-42 selects the ECC fields whenever CRE or UECC is set.
77 	 * The first error freezes PERROR (10.2.5.6); mixed error bits were
78 	 * detected together. Only LOST can be set afterwards.
79 	 */
80 	if (perror & TSUNAMI_PERROR_ECCMASK) {
81 		const char *command = "Reserved";
82 
83 		if (cmd == 0)
84 			command = "DMA read";
85 		else if (cmd == 1)
86 			command = "DMA RMW";
87 		else if (cmd == 3)
88 			command = "SGTE read";
89 		addr = ((perror >> 19) & 0xffffffffUL) << 3;
90 		printk("%s    Command: %s (%x), syndrome: %02llx\n",
91 		       err_print_prefix, command, cmd, (perror & perror_m_syn) >> 56);
92 		printk("%s    System address: %lx\n", err_print_prefix, addr);
93 	} else {
94 		addr = ((perror >> 18) & 0x3fffffffUL) << 2;
95 		/* SGE captures only PCI address bits <31:13> (8KB page). */
96 		if (perror & perror_m_sge)
97 			addr &= ~0x1fffUL;
98 		printk("%s    Command: %s (%x), PCI address: %lx%s\n",
99 		       err_print_prefix, pci_cmd[cmd], cmd, addr,
100 		       (perror & perror_m_sge) ? " (8KB page)" : "");
101 		if (perror & (1UL << 17))
102 			printk("%s    Monster window\n", err_print_prefix);
103 		else if (perror & (1UL << 16))
104 			printk("%s    DAC scatter-gather window 3\n", err_print_prefix);
105 	}
106 	return MCHK_DISPOSITION_REPORT;
107 }
108 
109 /* SESF bits 0/1 identify PCI errors, bit 2 covers ECC on either Pchip/CPU. */
110 static u64
111 tsunami_pchip_error(struct el_TSUNAMI_sysdata_mcheck *frame, int which)
112 {
113 	u64 perror = which ? frame->p1_perror : frame->p0_perror;
114 
115 	if (frame->sesf & (1UL << which))
116 		return perror;
117 	if ((frame->sesf & 4) && (perror & TSUNAMI_PERROR_ECCMASK))
118 		return perror;
119 	return 0;
120 }
121 
122 static struct el_TSUNAMI_sysdata_mcheck *
123 tsunami_system_frame(struct el_common *header)
124 {
125 	if (!tsunami_frame_valid(header, sizeof(struct el_TSUNAMI_sysdata_mcheck)))
126 		return NULL;
127 	return (void *)header + header->sys_offset;
128 }
129 
130 static int
131 tsunami_process_logout_frame(struct el_common *header, int print)
132 {
133 	struct el_TSUNAMI_sysdata_mcheck *frame = tsunami_system_frame(header);
134 	int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
135 	int i;
136 
137 	if (!frame) {
138 		if (print) {
139 			printk("%s  Invalid Tsunami system frame; raw frame follows\n",
140 			       err_print_prefix);
141 			mchk_dump_logout_frame_raw(header);
142 		}
143 		return MCHK_DISPOSITION_UNKNOWN_ERROR;
144 	}
145 	if (print)
146 		printk("%s  SESF: %016llx DIR: %016llx MISC: %016llx\n",
147 		       err_print_prefix, frame->sesf, frame->dir, frame->misc);
148 	if (frame->misc & TSUNAMI_MISC_NXM) {
149 		status = MCHK_DISPOSITION_REPORT;
150 		if (print)
151 			printk("%s  Non-existent memory, NXS: %llu\n",
152 			       err_print_prefix, (frame->misc >> 29) & 7);
153 	}
154 	for (i = 0; i < 2; i++)
155 		status |= tsunami_parse_p_perror(i, tsunami_pchip_error(frame, i), print);
156 	return status;
157 }
158 
159 struct tsunami_error_state {
160 	u64 perror[2];
161 	u64 misc;
162 };
163 
164 static void
165 tsunami_ack_pchip(tsunami_pchip *pchip, u64 perror)
166 {
167 	if (!(perror & TSUNAMI_PERROR_ERRMASK))
168 		return;
169 	pchip->perror.csr = perror & TSUNAMI_PERROR_ERRMASK;
170 	/* Complete the W1C write before releasing the logout frame. */
171 	mb();
172 	pchip->perror.csr;
173 }
174 
175 static void
176 tsunami_clear_errors(struct tsunami_error_state *state)
177 {
178 	bool pchip1 = TSUNAMI_cchip->csc.csr & (1UL << 14);
179 
180 	/* Preserve each chip's transaction and the NXM source before clearing. */
181 	state->perror[0] = TSUNAMI_pchip0->perror.csr;
182 	state->perror[1] = pchip1 ? TSUNAMI_pchip1->perror.csr : 0;
183 	state->misc = TSUNAMI_cchip->misc.csr;
184 
185 	/*
186 	 * Acknowledge both present Pchips: the saved frame may predate
187 	 * live errors. This can consume another chip's pending error
188 	 * with INV set before it reaches DRIR, losing its transaction
189 	 * details and subsequent system-error notification.
190 	 */
191 	tsunami_ack_pchip(TSUNAMI_pchip0, state->perror[0]);
192 	/* Do not access the second Pchip on single-Pchip systems. */
193 	if (pchip1)
194 		tsunami_ack_pchip(TSUNAMI_pchip1, state->perror[1]);
195 	if (state->misc & TSUNAMI_MISC_NXM) {
196 		/* Zero writes leave the other MISC fields unchanged. */
197 		TSUNAMI_cchip->misc.csr = TSUNAMI_MISC_NXM;
198 		/* Complete the NXM acknowledgment before releasing the frame. */
199 		mb();
200 		TSUNAMI_cchip->misc.csr;
201 	}
202 }
203 
204 static void
205 tsunami_report_live_errors(struct tsunami_error_state *state,
206 			  struct el_TSUNAMI_sysdata_mcheck *frame)
207 {
208 	int i;
209 
210 	/* PALcode's frame may predate these errors, or describe another chip. */
211 	for (i = 0; i < 2; i++) {
212 		if (!(state->perror[i] & TSUNAMI_PERROR_ERRMASK) ||
213 		    (frame && state->perror[i] == tsunami_pchip_error(frame, i)))
214 			continue;
215 		printk("%s  Live Pchip status before acknowledgment:\n", err_print_prefix);
216 		tsunami_parse_p_perror(i, state->perror[i], 1);
217 	}
218 	if ((state->misc & TSUNAMI_MISC_NXM) &&
219 	    (!frame || ((state->misc ^ frame->misc) & (0xfUL << 28))))
220 		printk("%s  Live MISC: %016llx, non-existent memory, NXS: %llu\n",
221 		       err_print_prefix, state->misc, (state->misc >> 29) & 7);
222 }
223 
224 void
225 tsunami_machine_check(unsigned long vector, unsigned long la_ptr)
226 {
227 	struct el_common *header = (void *)la_ptr;
228 	struct el_TSUNAMI_sysdata_mcheck *frame = NULL;
229 	struct tsunami_error_state live = {};
230 	char *saved_err_prefix = err_print_prefix;
231 	bool show_regs = vector == SCB_Q_SYSMCHK;
232 
233 	/* Synchronize pending accesses before inspecting the chipset. */
234 	mb();
235 	mb();
236 	draina();
237 	/* CPU/event vectors must not consume a pending Pchip system error. */
238 	if (vector == SCB_Q_SYSMCHK || vector == SCB_Q_SYSERR) {
239 		tsunami_clear_errors(&live);
240 		frame = tsunami_system_frame(header);
241 	}
242 
243 #ifdef CONFIG_VERBOSE_MCHECK
244 	show_regs |= alpha_verbose_mcheck != 0;
245 #endif
246 	err_print_prefix = KERN_CRIT;
247 	if (vector == SCB_Q_SYSMCHK || vector == SCB_Q_SYSERR) {
248 		printk("%sSystem %s error (vector %lx, code %x) on CPU %d:\n",
249 		       err_print_prefix, vector == SCB_Q_SYSERR ? "correctable" :
250 		       "uncorrectable", vector, header->code, smp_processor_id());
251 		tsunami_process_logout_frame(header, 1);
252 		if (show_regs)
253 			dik_show_regs(get_irq_regs(), NULL);
254 		tsunami_report_live_errors(&live, frame);
255 	} else if (vector == SCB_Q_SYSEVENT) {
256 		printk("%sTsunami environmental event (code %x): layout unknown\n",
257 		       err_print_prefix, header->code);
258 		mchk_dump_logout_frame_raw(header);
259 	}
260 	err_print_prefix = saved_err_prefix;
261 
262 	if (vector != SCB_Q_SYSMCHK && vector != SCB_Q_SYSERR &&
263 	    vector != SCB_Q_SYSEVENT) {
264 		/* EV6 decoding also releases the logout frame. */
265 		ev6_machine_check(vector, la_ptr);
266 	} else {
267 		wrmces(0x7);
268 		/* Complete acknowledgment before resuming. */
269 		mb();
270 	}
271 }
272