blob: 404e8561e2d0cec8b6d52a38be95d360624b0be7 [file] [log] [blame]
David S. Millerd979f172007-10-27 00:13:04 -07001/* arch/sparc64/kernel/traps.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
David S. Miller4fe3ebe2008-07-17 22:11:32 -07003 * Copyright (C) 1995,1997,2008 David S. Miller (davem@davemloft.net)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
5 */
6
7/*
8 * I like traps on v9, :))))
9 */
10
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/module.h>
David S. Millera2c1e062006-11-29 21:16:21 -080012#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/signal.h>
15#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/mm.h>
17#include <linux/init.h>
Christoph Hellwig1eeb66a2007-05-08 00:27:03 -070018#include <linux/kdebug.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019
Fernando Luis Vazquez Cao2f4dfe22007-05-09 02:33:25 -070020#include <asm/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <asm/delay.h>
22#include <asm/system.h>
23#include <asm/ptrace.h>
24#include <asm/oplib.h>
25#include <asm/page.h>
26#include <asm/pgtable.h>
27#include <asm/unistd.h>
28#include <asm/uaccess.h>
29#include <asm/fpumacro.h>
30#include <asm/lsu.h>
31#include <asm/dcu.h>
32#include <asm/estate.h>
33#include <asm/chafsr.h>
David S. Miller6c52a962005-08-29 12:45:11 -070034#include <asm/sfafsr.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <asm/psrcompat.h>
36#include <asm/processor.h>
37#include <asm/timer.h>
David S. Miller92704a12006-02-26 23:27:19 -080038#include <asm/head.h>
David S. Miller07f8e5f2006-06-21 23:34:02 -070039#include <asm/prom.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
David S. Miller99cd2202008-03-26 00:19:43 -070041#include "entry.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43/* When an irrecoverable trap occurs at tl > 0, the trap entry
44 * code logs the trap state registers at every level in the trap
45 * stack. It is found at (pt_regs + sizeof(pt_regs)) and the layout
46 * is as follows:
47 */
48struct tl1_traplog {
49 struct {
50 unsigned long tstate;
51 unsigned long tpc;
52 unsigned long tnpc;
53 unsigned long tt;
54 } trapstack[4];
55 unsigned long tl;
56};
57
58static void dump_tl1_traplog(struct tl1_traplog *p)
59{
David S. Miller3d6395c2006-02-16 01:41:41 -080060 int i, limit;
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
David S. Miller04d74752006-02-18 17:06:28 -080062 printk(KERN_EMERG "TRAPLOG: Error at trap level 0x%lx, "
63 "dumping track stack.\n", p->tl);
David S. Miller3d6395c2006-02-16 01:41:41 -080064
65 limit = (tlb_type == hypervisor) ? 2 : 4;
David S. Miller39334a42006-02-20 00:54:09 -080066 for (i = 0; i < limit; i++) {
David S. Miller04d74752006-02-18 17:06:28 -080067 printk(KERN_EMERG
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 "TRAPLOG: Trap level %d TSTATE[%016lx] TPC[%016lx] "
69 "TNPC[%016lx] TT[%lx]\n",
70 i + 1,
71 p->trapstack[i].tstate, p->trapstack[i].tpc,
72 p->trapstack[i].tnpc, p->trapstack[i].tt);
David S. Miller4fe3ebe2008-07-17 22:11:32 -070073 printk("TRAPLOG: TPC<%pS>\n", (void *) p->trapstack[i].tpc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 }
75}
76
Linus Torvalds1da177e2005-04-16 15:20:36 -070077void bad_trap(struct pt_regs *regs, long lvl)
78{
79 char buffer[32];
80 siginfo_t info;
81
82 if (notify_die(DIE_TRAP, "bad trap", regs,
83 0, lvl, SIGTRAP) == NOTIFY_STOP)
84 return;
85
86 if (lvl < 0x100) {
87 sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl);
88 die_if_kernel(buffer, regs);
89 }
90
91 lvl -= 0x100;
92 if (regs->tstate & TSTATE_PRIV) {
93 sprintf(buffer, "Kernel bad sw trap %lx", lvl);
94 die_if_kernel(buffer, regs);
95 }
96 if (test_thread_flag(TIF_32BIT)) {
97 regs->tpc &= 0xffffffff;
98 regs->tnpc &= 0xffffffff;
99 }
100 info.si_signo = SIGILL;
101 info.si_errno = 0;
102 info.si_code = ILL_ILLTRP;
103 info.si_addr = (void __user *)regs->tpc;
104 info.si_trapno = lvl;
105 force_sig_info(SIGILL, &info, current);
106}
107
108void bad_trap_tl1(struct pt_regs *regs, long lvl)
109{
110 char buffer[32];
111
112 if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
113 0, lvl, SIGTRAP) == NOTIFY_STOP)
114 return;
115
116 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
117
118 sprintf (buffer, "Bad trap %lx at tl>0", lvl);
119 die_if_kernel (buffer, regs);
120}
121
122#ifdef CONFIG_DEBUG_BUGVERBOSE
123void do_BUG(const char *file, int line)
124{
125 bust_spinlocks(1);
126 printk("kernel BUG at %s:%d!\n", file, line);
127}
128#endif
129
David S. Miller6c52a962005-08-29 12:45:11 -0700130void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131{
132 siginfo_t info;
133
134 if (notify_die(DIE_TRAP, "instruction access exception", regs,
135 0, 0x8, SIGTRAP) == NOTIFY_STOP)
136 return;
137
138 if (regs->tstate & TSTATE_PRIV) {
David S. Miller6c52a962005-08-29 12:45:11 -0700139 printk("spitfire_insn_access_exception: SFSR[%016lx] "
140 "SFAR[%016lx], going.\n", sfsr, sfar);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 die_if_kernel("Iax", regs);
142 }
143 if (test_thread_flag(TIF_32BIT)) {
144 regs->tpc &= 0xffffffff;
145 regs->tnpc &= 0xffffffff;
146 }
147 info.si_signo = SIGSEGV;
148 info.si_errno = 0;
149 info.si_code = SEGV_MAPERR;
150 info.si_addr = (void __user *)regs->tpc;
151 info.si_trapno = 0;
152 force_sig_info(SIGSEGV, &info, current);
153}
154
David S. Miller6c52a962005-08-29 12:45:11 -0700155void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156{
157 if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
158 0, 0x8, SIGTRAP) == NOTIFY_STOP)
159 return;
160
161 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
David S. Miller6c52a962005-08-29 12:45:11 -0700162 spitfire_insn_access_exception(regs, sfsr, sfar);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163}
164
David S. Millered6b0b42006-02-09 20:20:34 -0800165void sun4v_insn_access_exception(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
166{
167 unsigned short type = (type_ctx >> 16);
168 unsigned short ctx = (type_ctx & 0xffff);
169 siginfo_t info;
170
171 if (notify_die(DIE_TRAP, "instruction access exception", regs,
172 0, 0x8, SIGTRAP) == NOTIFY_STOP)
173 return;
174
175 if (regs->tstate & TSTATE_PRIV) {
176 printk("sun4v_insn_access_exception: ADDR[%016lx] "
177 "CTX[%04x] TYPE[%04x], going.\n",
178 addr, ctx, type);
179 die_if_kernel("Iax", regs);
180 }
181
182 if (test_thread_flag(TIF_32BIT)) {
183 regs->tpc &= 0xffffffff;
184 regs->tnpc &= 0xffffffff;
185 }
186 info.si_signo = SIGSEGV;
187 info.si_errno = 0;
188 info.si_code = SEGV_MAPERR;
189 info.si_addr = (void __user *) addr;
190 info.si_trapno = 0;
191 force_sig_info(SIGSEGV, &info, current);
192}
193
194void sun4v_insn_access_exception_tl1(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
195{
196 if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
197 0, 0x8, SIGTRAP) == NOTIFY_STOP)
198 return;
199
200 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
201 sun4v_insn_access_exception(regs, addr, type_ctx);
202}
203
David S. Miller6c52a962005-08-29 12:45:11 -0700204void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205{
206 siginfo_t info;
207
208 if (notify_die(DIE_TRAP, "data access exception", regs,
209 0, 0x30, SIGTRAP) == NOTIFY_STOP)
210 return;
211
212 if (regs->tstate & TSTATE_PRIV) {
213 /* Test if this comes from uaccess places. */
David S. Miller8cf14af2005-09-28 20:21:11 -0700214 const struct exception_table_entry *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
David S. Miller8cf14af2005-09-28 20:21:11 -0700216 entry = search_exception_tables(regs->tpc);
217 if (entry) {
218 /* Ouch, somebody is trying VM hole tricks on us... */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219#ifdef DEBUG_EXCEPTIONS
220 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
David S. Miller8cf14af2005-09-28 20:21:11 -0700221 printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n",
222 regs->tpc, entry->fixup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223#endif
David S. Miller8cf14af2005-09-28 20:21:11 -0700224 regs->tpc = entry->fixup;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 regs->tnpc = regs->tpc + 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 return;
227 }
228 /* Shit... */
David S. Miller6c52a962005-08-29 12:45:11 -0700229 printk("spitfire_data_access_exception: SFSR[%016lx] "
230 "SFAR[%016lx], going.\n", sfsr, sfar);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 die_if_kernel("Dax", regs);
232 }
233
234 info.si_signo = SIGSEGV;
235 info.si_errno = 0;
236 info.si_code = SEGV_MAPERR;
237 info.si_addr = (void __user *)sfar;
238 info.si_trapno = 0;
239 force_sig_info(SIGSEGV, &info, current);
240}
241
David S. Miller6c52a962005-08-29 12:45:11 -0700242void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
David S. Millerbde4e4e2005-08-29 12:44:57 -0700243{
244 if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs,
245 0, 0x30, SIGTRAP) == NOTIFY_STOP)
246 return;
247
248 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
David S. Miller6c52a962005-08-29 12:45:11 -0700249 spitfire_data_access_exception(regs, sfsr, sfar);
David S. Millerbde4e4e2005-08-29 12:44:57 -0700250}
251
David S. Millered6b0b42006-02-09 20:20:34 -0800252void sun4v_data_access_exception(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
253{
254 unsigned short type = (type_ctx >> 16);
255 unsigned short ctx = (type_ctx & 0xffff);
256 siginfo_t info;
257
258 if (notify_die(DIE_TRAP, "data access exception", regs,
259 0, 0x8, SIGTRAP) == NOTIFY_STOP)
260 return;
261
262 if (regs->tstate & TSTATE_PRIV) {
263 printk("sun4v_data_access_exception: ADDR[%016lx] "
264 "CTX[%04x] TYPE[%04x], going.\n",
265 addr, ctx, type);
David S. Miller55555632006-02-20 01:50:09 -0800266 die_if_kernel("Dax", regs);
David S. Millered6b0b42006-02-09 20:20:34 -0800267 }
268
269 if (test_thread_flag(TIF_32BIT)) {
270 regs->tpc &= 0xffffffff;
271 regs->tnpc &= 0xffffffff;
272 }
273 info.si_signo = SIGSEGV;
274 info.si_errno = 0;
275 info.si_code = SEGV_MAPERR;
276 info.si_addr = (void __user *) addr;
277 info.si_trapno = 0;
278 force_sig_info(SIGSEGV, &info, current);
279}
280
281void sun4v_data_access_exception_tl1(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
282{
283 if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs,
284 0, 0x8, SIGTRAP) == NOTIFY_STOP)
285 return;
286
287 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
288 sun4v_data_access_exception(regs, addr, type_ctx);
289}
290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291#ifdef CONFIG_PCI
292/* This is really pathetic... */
293extern volatile int pci_poke_in_progress;
294extern volatile int pci_poke_cpu;
295extern volatile int pci_poke_faulted;
296#endif
297
298/* When access exceptions happen, we must do this. */
299static void spitfire_clean_and_reenable_l1_caches(void)
300{
301 unsigned long va;
302
303 if (tlb_type != spitfire)
304 BUG();
305
306 /* Clean 'em. */
307 for (va = 0; va < (PAGE_SIZE << 1); va += 32) {
308 spitfire_put_icache_tag(va, 0x0);
309 spitfire_put_dcache_tag(va, 0x0);
310 }
311
312 /* Re-enable in LSU. */
313 __asm__ __volatile__("flush %%g6\n\t"
314 "membar #Sync\n\t"
315 "stxa %0, [%%g0] %1\n\t"
316 "membar #Sync"
317 : /* no outputs */
318 : "r" (LSU_CONTROL_IC | LSU_CONTROL_DC |
319 LSU_CONTROL_IM | LSU_CONTROL_DM),
320 "i" (ASI_LSU_CONTROL)
321 : "memory");
322}
323
David S. Miller6c52a962005-08-29 12:45:11 -0700324static void spitfire_enable_estate_errors(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325{
David S. Miller6c52a962005-08-29 12:45:11 -0700326 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
327 "membar #Sync"
328 : /* no outputs */
329 : "r" (ESTATE_ERR_ALL),
330 "i" (ASI_ESTATE_ERROR_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331}
332
333static char ecc_syndrome_table[] = {
334 0x4c, 0x40, 0x41, 0x48, 0x42, 0x48, 0x48, 0x49,
335 0x43, 0x48, 0x48, 0x49, 0x48, 0x49, 0x49, 0x4a,
336 0x44, 0x48, 0x48, 0x20, 0x48, 0x39, 0x4b, 0x48,
337 0x48, 0x25, 0x31, 0x48, 0x28, 0x48, 0x48, 0x2c,
338 0x45, 0x48, 0x48, 0x21, 0x48, 0x3d, 0x04, 0x48,
339 0x48, 0x4b, 0x35, 0x48, 0x2d, 0x48, 0x48, 0x29,
340 0x48, 0x00, 0x01, 0x48, 0x0a, 0x48, 0x48, 0x4b,
341 0x0f, 0x48, 0x48, 0x4b, 0x48, 0x49, 0x49, 0x48,
342 0x46, 0x48, 0x48, 0x2a, 0x48, 0x3b, 0x27, 0x48,
343 0x48, 0x4b, 0x33, 0x48, 0x22, 0x48, 0x48, 0x2e,
344 0x48, 0x19, 0x1d, 0x48, 0x1b, 0x4a, 0x48, 0x4b,
345 0x1f, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
346 0x48, 0x4b, 0x24, 0x48, 0x07, 0x48, 0x48, 0x36,
347 0x4b, 0x48, 0x48, 0x3e, 0x48, 0x30, 0x38, 0x48,
348 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x16, 0x48,
349 0x48, 0x12, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
350 0x47, 0x48, 0x48, 0x2f, 0x48, 0x3f, 0x4b, 0x48,
351 0x48, 0x06, 0x37, 0x48, 0x23, 0x48, 0x48, 0x2b,
352 0x48, 0x05, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x32,
353 0x26, 0x48, 0x48, 0x3a, 0x48, 0x34, 0x3c, 0x48,
354 0x48, 0x11, 0x15, 0x48, 0x13, 0x4a, 0x48, 0x4b,
355 0x17, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
356 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x1e, 0x48,
357 0x48, 0x1a, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
358 0x48, 0x08, 0x0d, 0x48, 0x02, 0x48, 0x48, 0x49,
359 0x03, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x4b, 0x48,
360 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x10, 0x48,
361 0x48, 0x14, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
362 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x18, 0x48,
363 0x48, 0x1c, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
364 0x4a, 0x0c, 0x09, 0x48, 0x0e, 0x48, 0x48, 0x4b,
365 0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a
366};
367
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368static char *syndrome_unknown = "<Unknown>";
369
David S. Miller6c52a962005-08-29 12:45:11 -0700370static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371{
David S. Miller6c52a962005-08-29 12:45:11 -0700372 unsigned short scode;
373 char memmod_str[64], *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
David S. Miller6c52a962005-08-29 12:45:11 -0700375 if (udbl & bit) {
376 scode = ecc_syndrome_table[udbl & 0xff];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 if (prom_getunumber(scode, afar,
378 memmod_str, sizeof(memmod_str)) == -1)
379 p = syndrome_unknown;
380 else
381 p = memmod_str;
382 printk(KERN_WARNING "CPU[%d]: UDBL Syndrome[%x] "
383 "Memory Module \"%s\"\n",
384 smp_processor_id(), scode, p);
385 }
386
David S. Miller6c52a962005-08-29 12:45:11 -0700387 if (udbh & bit) {
388 scode = ecc_syndrome_table[udbh & 0xff];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 if (prom_getunumber(scode, afar,
390 memmod_str, sizeof(memmod_str)) == -1)
391 p = syndrome_unknown;
392 else
393 p = memmod_str;
394 printk(KERN_WARNING "CPU[%d]: UDBH Syndrome[%x] "
395 "Memory Module \"%s\"\n",
396 smp_processor_id(), scode, p);
397 }
David S. Miller6c52a962005-08-29 12:45:11 -0700398
399}
400
401static void spitfire_cee_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, int tl1, struct pt_regs *regs)
402{
403
404 printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
405 "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx] TL>1[%d]\n",
406 smp_processor_id(), afsr, afar, udbl, udbh, tl1);
407
408 spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_CE);
409
410 /* We always log it, even if someone is listening for this
411 * trap.
412 */
413 notify_die(DIE_TRAP, "Correctable ECC Error", regs,
414 0, TRAP_TYPE_CEE, SIGTRAP);
415
416 /* The Correctable ECC Error trap does not disable I/D caches. So
417 * we only have to restore the ESTATE Error Enable register.
418 */
419 spitfire_enable_estate_errors();
420}
421
422static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long tt, int tl1, struct pt_regs *regs)
423{
424 siginfo_t info;
425
426 printk(KERN_WARNING "CPU[%d]: Uncorrectable Error AFSR[%lx] "
427 "AFAR[%lx] UDBL[%lx] UDBH[%ld] TT[%lx] TL>1[%d]\n",
428 smp_processor_id(), afsr, afar, udbl, udbh, tt, tl1);
429
430 /* XXX add more human friendly logging of the error status
431 * XXX as is implemented for cheetah
432 */
433
434 spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_UE);
435
436 /* We always log it, even if someone is listening for this
437 * trap.
438 */
439 notify_die(DIE_TRAP, "Uncorrectable Error", regs,
440 0, tt, SIGTRAP);
441
442 if (regs->tstate & TSTATE_PRIV) {
443 if (tl1)
444 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
445 die_if_kernel("UE", regs);
446 }
447
448 /* XXX need more intelligent processing here, such as is implemented
449 * XXX for cheetah errors, in fact if the E-cache still holds the
450 * XXX line with bad parity this will loop
451 */
452
453 spitfire_clean_and_reenable_l1_caches();
454 spitfire_enable_estate_errors();
455
456 if (test_thread_flag(TIF_32BIT)) {
457 regs->tpc &= 0xffffffff;
458 regs->tnpc &= 0xffffffff;
459 }
460 info.si_signo = SIGBUS;
461 info.si_errno = 0;
462 info.si_code = BUS_OBJERR;
463 info.si_addr = (void *)0;
464 info.si_trapno = 0;
465 force_sig_info(SIGBUS, &info, current);
466}
467
468void spitfire_access_error(struct pt_regs *regs, unsigned long status_encoded, unsigned long afar)
469{
470 unsigned long afsr, tt, udbh, udbl;
471 int tl1;
472
473 afsr = (status_encoded & SFSTAT_AFSR_MASK) >> SFSTAT_AFSR_SHIFT;
474 tt = (status_encoded & SFSTAT_TRAP_TYPE) >> SFSTAT_TRAP_TYPE_SHIFT;
475 tl1 = (status_encoded & SFSTAT_TL_GT_ONE) ? 1 : 0;
476 udbl = (status_encoded & SFSTAT_UDBL_MASK) >> SFSTAT_UDBL_SHIFT;
477 udbh = (status_encoded & SFSTAT_UDBH_MASK) >> SFSTAT_UDBH_SHIFT;
478
479#ifdef CONFIG_PCI
480 if (tt == TRAP_TYPE_DAE &&
481 pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
482 spitfire_clean_and_reenable_l1_caches();
483 spitfire_enable_estate_errors();
484
485 pci_poke_faulted = 1;
486 regs->tnpc = regs->tpc + 4;
487 return;
488 }
489#endif
490
491 if (afsr & SFAFSR_UE)
492 spitfire_ue_log(afsr, afar, udbh, udbl, tt, tl1, regs);
493
494 if (tt == TRAP_TYPE_CEE) {
495 /* Handle the case where we took a CEE trap, but ACK'd
496 * only the UE state in the UDB error registers.
497 */
498 if (afsr & SFAFSR_UE) {
499 if (udbh & UDBE_CE) {
500 __asm__ __volatile__(
501 "stxa %0, [%1] %2\n\t"
502 "membar #Sync"
503 : /* no outputs */
504 : "r" (udbh & UDBE_CE),
505 "r" (0x0), "i" (ASI_UDB_ERROR_W));
506 }
507 if (udbl & UDBE_CE) {
508 __asm__ __volatile__(
509 "stxa %0, [%1] %2\n\t"
510 "membar #Sync"
511 : /* no outputs */
512 : "r" (udbl & UDBE_CE),
513 "r" (0x18), "i" (ASI_UDB_ERROR_W));
514 }
515 }
516
517 spitfire_cee_log(afsr, afar, udbh, udbl, tl1, regs);
518 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519}
520
David S. Miller816242d2005-05-23 15:52:08 -0700521int cheetah_pcache_forced_on;
522
523void cheetah_enable_pcache(void)
524{
525 unsigned long dcr;
526
527 printk("CHEETAH: Enabling P-Cache on cpu %d.\n",
528 smp_processor_id());
529
530 __asm__ __volatile__("ldxa [%%g0] %1, %0"
531 : "=r" (dcr)
532 : "i" (ASI_DCU_CONTROL_REG));
533 dcr |= (DCU_PE | DCU_HPE | DCU_SPE | DCU_SL);
534 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
535 "membar #Sync"
536 : /* no outputs */
537 : "r" (dcr), "i" (ASI_DCU_CONTROL_REG));
538}
539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540/* Cheetah error trap handling. */
541static unsigned long ecache_flush_physbase;
542static unsigned long ecache_flush_linesize;
543static unsigned long ecache_flush_size;
544
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545/* This table is ordered in priority of errors and matches the
546 * AFAR overwrite policy as well.
547 */
548
549struct afsr_error_table {
550 unsigned long mask;
551 const char *name;
552};
553
554static const char CHAFSR_PERR_msg[] =
555 "System interface protocol error";
556static const char CHAFSR_IERR_msg[] =
557 "Internal processor error";
558static const char CHAFSR_ISAP_msg[] =
559 "System request parity error on incoming addresss";
560static const char CHAFSR_UCU_msg[] =
561 "Uncorrectable E-cache ECC error for ifetch/data";
562static const char CHAFSR_UCC_msg[] =
563 "SW Correctable E-cache ECC error for ifetch/data";
564static const char CHAFSR_UE_msg[] =
565 "Uncorrectable system bus data ECC error for read";
566static const char CHAFSR_EDU_msg[] =
567 "Uncorrectable E-cache ECC error for stmerge/blkld";
568static const char CHAFSR_EMU_msg[] =
569 "Uncorrectable system bus MTAG error";
570static const char CHAFSR_WDU_msg[] =
571 "Uncorrectable E-cache ECC error for writeback";
572static const char CHAFSR_CPU_msg[] =
573 "Uncorrectable ECC error for copyout";
574static const char CHAFSR_CE_msg[] =
575 "HW corrected system bus data ECC error for read";
576static const char CHAFSR_EDC_msg[] =
577 "HW corrected E-cache ECC error for stmerge/blkld";
578static const char CHAFSR_EMC_msg[] =
579 "HW corrected system bus MTAG ECC error";
580static const char CHAFSR_WDC_msg[] =
581 "HW corrected E-cache ECC error for writeback";
582static const char CHAFSR_CPC_msg[] =
583 "HW corrected ECC error for copyout";
584static const char CHAFSR_TO_msg[] =
585 "Unmapped error from system bus";
586static const char CHAFSR_BERR_msg[] =
587 "Bus error response from system bus";
588static const char CHAFSR_IVC_msg[] =
589 "HW corrected system bus data ECC error for ivec read";
590static const char CHAFSR_IVU_msg[] =
591 "Uncorrectable system bus data ECC error for ivec read";
592static struct afsr_error_table __cheetah_error_table[] = {
593 { CHAFSR_PERR, CHAFSR_PERR_msg },
594 { CHAFSR_IERR, CHAFSR_IERR_msg },
595 { CHAFSR_ISAP, CHAFSR_ISAP_msg },
596 { CHAFSR_UCU, CHAFSR_UCU_msg },
597 { CHAFSR_UCC, CHAFSR_UCC_msg },
598 { CHAFSR_UE, CHAFSR_UE_msg },
599 { CHAFSR_EDU, CHAFSR_EDU_msg },
600 { CHAFSR_EMU, CHAFSR_EMU_msg },
601 { CHAFSR_WDU, CHAFSR_WDU_msg },
602 { CHAFSR_CPU, CHAFSR_CPU_msg },
603 { CHAFSR_CE, CHAFSR_CE_msg },
604 { CHAFSR_EDC, CHAFSR_EDC_msg },
605 { CHAFSR_EMC, CHAFSR_EMC_msg },
606 { CHAFSR_WDC, CHAFSR_WDC_msg },
607 { CHAFSR_CPC, CHAFSR_CPC_msg },
608 { CHAFSR_TO, CHAFSR_TO_msg },
609 { CHAFSR_BERR, CHAFSR_BERR_msg },
610 /* These two do not update the AFAR. */
611 { CHAFSR_IVC, CHAFSR_IVC_msg },
612 { CHAFSR_IVU, CHAFSR_IVU_msg },
613 { 0, NULL },
614};
615static const char CHPAFSR_DTO_msg[] =
616 "System bus unmapped error for prefetch/storequeue-read";
617static const char CHPAFSR_DBERR_msg[] =
618 "System bus error for prefetch/storequeue-read";
619static const char CHPAFSR_THCE_msg[] =
620 "Hardware corrected E-cache Tag ECC error";
621static const char CHPAFSR_TSCE_msg[] =
622 "SW handled correctable E-cache Tag ECC error";
623static const char CHPAFSR_TUE_msg[] =
624 "Uncorrectable E-cache Tag ECC error";
625static const char CHPAFSR_DUE_msg[] =
626 "System bus uncorrectable data ECC error due to prefetch/store-fill";
627static struct afsr_error_table __cheetah_plus_error_table[] = {
628 { CHAFSR_PERR, CHAFSR_PERR_msg },
629 { CHAFSR_IERR, CHAFSR_IERR_msg },
630 { CHAFSR_ISAP, CHAFSR_ISAP_msg },
631 { CHAFSR_UCU, CHAFSR_UCU_msg },
632 { CHAFSR_UCC, CHAFSR_UCC_msg },
633 { CHAFSR_UE, CHAFSR_UE_msg },
634 { CHAFSR_EDU, CHAFSR_EDU_msg },
635 { CHAFSR_EMU, CHAFSR_EMU_msg },
636 { CHAFSR_WDU, CHAFSR_WDU_msg },
637 { CHAFSR_CPU, CHAFSR_CPU_msg },
638 { CHAFSR_CE, CHAFSR_CE_msg },
639 { CHAFSR_EDC, CHAFSR_EDC_msg },
640 { CHAFSR_EMC, CHAFSR_EMC_msg },
641 { CHAFSR_WDC, CHAFSR_WDC_msg },
642 { CHAFSR_CPC, CHAFSR_CPC_msg },
643 { CHAFSR_TO, CHAFSR_TO_msg },
644 { CHAFSR_BERR, CHAFSR_BERR_msg },
645 { CHPAFSR_DTO, CHPAFSR_DTO_msg },
646 { CHPAFSR_DBERR, CHPAFSR_DBERR_msg },
647 { CHPAFSR_THCE, CHPAFSR_THCE_msg },
648 { CHPAFSR_TSCE, CHPAFSR_TSCE_msg },
649 { CHPAFSR_TUE, CHPAFSR_TUE_msg },
650 { CHPAFSR_DUE, CHPAFSR_DUE_msg },
651 /* These two do not update the AFAR. */
652 { CHAFSR_IVC, CHAFSR_IVC_msg },
653 { CHAFSR_IVU, CHAFSR_IVU_msg },
654 { 0, NULL },
655};
656static const char JPAFSR_JETO_msg[] =
657 "System interface protocol error, hw timeout caused";
658static const char JPAFSR_SCE_msg[] =
659 "Parity error on system snoop results";
660static const char JPAFSR_JEIC_msg[] =
661 "System interface protocol error, illegal command detected";
662static const char JPAFSR_JEIT_msg[] =
663 "System interface protocol error, illegal ADTYPE detected";
664static const char JPAFSR_OM_msg[] =
665 "Out of range memory error has occurred";
666static const char JPAFSR_ETP_msg[] =
667 "Parity error on L2 cache tag SRAM";
668static const char JPAFSR_UMS_msg[] =
669 "Error due to unsupported store";
670static const char JPAFSR_RUE_msg[] =
671 "Uncorrectable ECC error from remote cache/memory";
672static const char JPAFSR_RCE_msg[] =
673 "Correctable ECC error from remote cache/memory";
674static const char JPAFSR_BP_msg[] =
675 "JBUS parity error on returned read data";
676static const char JPAFSR_WBP_msg[] =
677 "JBUS parity error on data for writeback or block store";
678static const char JPAFSR_FRC_msg[] =
679 "Foreign read to DRAM incurring correctable ECC error";
680static const char JPAFSR_FRU_msg[] =
681 "Foreign read to DRAM incurring uncorrectable ECC error";
682static struct afsr_error_table __jalapeno_error_table[] = {
683 { JPAFSR_JETO, JPAFSR_JETO_msg },
684 { JPAFSR_SCE, JPAFSR_SCE_msg },
685 { JPAFSR_JEIC, JPAFSR_JEIC_msg },
686 { JPAFSR_JEIT, JPAFSR_JEIT_msg },
687 { CHAFSR_PERR, CHAFSR_PERR_msg },
688 { CHAFSR_IERR, CHAFSR_IERR_msg },
689 { CHAFSR_ISAP, CHAFSR_ISAP_msg },
690 { CHAFSR_UCU, CHAFSR_UCU_msg },
691 { CHAFSR_UCC, CHAFSR_UCC_msg },
692 { CHAFSR_UE, CHAFSR_UE_msg },
693 { CHAFSR_EDU, CHAFSR_EDU_msg },
694 { JPAFSR_OM, JPAFSR_OM_msg },
695 { CHAFSR_WDU, CHAFSR_WDU_msg },
696 { CHAFSR_CPU, CHAFSR_CPU_msg },
697 { CHAFSR_CE, CHAFSR_CE_msg },
698 { CHAFSR_EDC, CHAFSR_EDC_msg },
699 { JPAFSR_ETP, JPAFSR_ETP_msg },
700 { CHAFSR_WDC, CHAFSR_WDC_msg },
701 { CHAFSR_CPC, CHAFSR_CPC_msg },
702 { CHAFSR_TO, CHAFSR_TO_msg },
703 { CHAFSR_BERR, CHAFSR_BERR_msg },
704 { JPAFSR_UMS, JPAFSR_UMS_msg },
705 { JPAFSR_RUE, JPAFSR_RUE_msg },
706 { JPAFSR_RCE, JPAFSR_RCE_msg },
707 { JPAFSR_BP, JPAFSR_BP_msg },
708 { JPAFSR_WBP, JPAFSR_WBP_msg },
709 { JPAFSR_FRC, JPAFSR_FRC_msg },
710 { JPAFSR_FRU, JPAFSR_FRU_msg },
711 /* These two do not update the AFAR. */
712 { CHAFSR_IVU, CHAFSR_IVU_msg },
713 { 0, NULL },
714};
715static struct afsr_error_table *cheetah_error_table;
716static unsigned long cheetah_afsr_errors;
717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718struct cheetah_err_info *cheetah_error_log;
719
David S. Millerd979f172007-10-27 00:13:04 -0700720static inline struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721{
722 struct cheetah_err_info *p;
723 int cpu = smp_processor_id();
724
725 if (!cheetah_error_log)
726 return NULL;
727
728 p = cheetah_error_log + (cpu * 2);
729 if ((afsr & CHAFSR_TL1) != 0UL)
730 p++;
731
732 return p;
733}
734
735extern unsigned int tl0_icpe[], tl1_icpe[];
736extern unsigned int tl0_dcpe[], tl1_dcpe[];
737extern unsigned int tl0_fecc[], tl1_fecc[];
738extern unsigned int tl0_cee[], tl1_cee[];
739extern unsigned int tl0_iae[], tl1_iae[];
740extern unsigned int tl0_dae[], tl1_dae[];
741extern unsigned int cheetah_plus_icpe_trap_vector[], cheetah_plus_icpe_trap_vector_tl1[];
742extern unsigned int cheetah_plus_dcpe_trap_vector[], cheetah_plus_dcpe_trap_vector_tl1[];
743extern unsigned int cheetah_fecc_trap_vector[], cheetah_fecc_trap_vector_tl1[];
744extern unsigned int cheetah_cee_trap_vector[], cheetah_cee_trap_vector_tl1[];
745extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector_tl1[];
746
747void __init cheetah_ecache_flush_init(void)
748{
749 unsigned long largest_size, smallest_linesize, order, ver;
David S. Miller5cbc3072007-05-25 15:49:59 -0700750 int i, sz;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
752 /* Scan all cpu device tree nodes, note two values:
753 * 1) largest E-cache size
754 * 2) smallest E-cache line size
755 */
756 largest_size = 0UL;
757 smallest_linesize = ~0UL;
758
David S. Miller5cbc3072007-05-25 15:49:59 -0700759 for (i = 0; i < NR_CPUS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 unsigned long val;
761
David S. Miller5cbc3072007-05-25 15:49:59 -0700762 val = cpu_data(i).ecache_size;
763 if (!val)
764 continue;
765
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 if (val > largest_size)
767 largest_size = val;
David S. Miller5cbc3072007-05-25 15:49:59 -0700768
769 val = cpu_data(i).ecache_line_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 if (val < smallest_linesize)
771 smallest_linesize = val;
David S. Miller5cbc3072007-05-25 15:49:59 -0700772
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 }
774
775 if (largest_size == 0UL || smallest_linesize == ~0UL) {
776 prom_printf("cheetah_ecache_flush_init: Cannot probe cpu E-cache "
777 "parameters.\n");
778 prom_halt();
779 }
780
781 ecache_flush_size = (2 * largest_size);
782 ecache_flush_linesize = smallest_linesize;
783
David S. Miller10147572005-09-28 21:46:43 -0700784 ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
David S. Miller10147572005-09-28 21:46:43 -0700786 if (ecache_flush_physbase == ~0UL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 prom_printf("cheetah_ecache_flush_init: Cannot find %d byte "
David S. Miller10147572005-09-28 21:46:43 -0700788 "contiguous physical memory.\n",
789 ecache_flush_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 prom_halt();
791 }
792
793 /* Now allocate error trap reporting scoreboard. */
David S. Miller07f8e5f2006-06-21 23:34:02 -0700794 sz = NR_CPUS * (2 * sizeof(struct cheetah_err_info));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 for (order = 0; order < MAX_ORDER; order++) {
David S. Miller07f8e5f2006-06-21 23:34:02 -0700796 if ((PAGE_SIZE << order) >= sz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 break;
798 }
799 cheetah_error_log = (struct cheetah_err_info *)
800 __get_free_pages(GFP_KERNEL, order);
801 if (!cheetah_error_log) {
802 prom_printf("cheetah_ecache_flush_init: Failed to allocate "
David S. Miller07f8e5f2006-06-21 23:34:02 -0700803 "error logging scoreboard (%d bytes).\n", sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 prom_halt();
805 }
806 memset(cheetah_error_log, 0, PAGE_SIZE << order);
807
808 /* Mark all AFSRs as invalid so that the trap handler will
809 * log new new information there.
810 */
811 for (i = 0; i < 2 * NR_CPUS; i++)
812 cheetah_error_log[i].afsr = CHAFSR_INVALID;
813
814 __asm__ ("rdpr %%ver, %0" : "=r" (ver));
David S. Miller92704a12006-02-26 23:27:19 -0800815 if ((ver >> 32) == __JALAPENO_ID ||
816 (ver >> 32) == __SERRANO_ID) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 cheetah_error_table = &__jalapeno_error_table[0];
818 cheetah_afsr_errors = JPAFSR_ERRORS;
819 } else if ((ver >> 32) == 0x003e0015) {
820 cheetah_error_table = &__cheetah_plus_error_table[0];
821 cheetah_afsr_errors = CHPAFSR_ERRORS;
822 } else {
823 cheetah_error_table = &__cheetah_error_table[0];
824 cheetah_afsr_errors = CHAFSR_ERRORS;
825 }
826
827 /* Now patch trap tables. */
828 memcpy(tl0_fecc, cheetah_fecc_trap_vector, (8 * 4));
829 memcpy(tl1_fecc, cheetah_fecc_trap_vector_tl1, (8 * 4));
830 memcpy(tl0_cee, cheetah_cee_trap_vector, (8 * 4));
831 memcpy(tl1_cee, cheetah_cee_trap_vector_tl1, (8 * 4));
832 memcpy(tl0_iae, cheetah_deferred_trap_vector, (8 * 4));
833 memcpy(tl1_iae, cheetah_deferred_trap_vector_tl1, (8 * 4));
834 memcpy(tl0_dae, cheetah_deferred_trap_vector, (8 * 4));
835 memcpy(tl1_dae, cheetah_deferred_trap_vector_tl1, (8 * 4));
836 if (tlb_type == cheetah_plus) {
837 memcpy(tl0_dcpe, cheetah_plus_dcpe_trap_vector, (8 * 4));
838 memcpy(tl1_dcpe, cheetah_plus_dcpe_trap_vector_tl1, (8 * 4));
839 memcpy(tl0_icpe, cheetah_plus_icpe_trap_vector, (8 * 4));
840 memcpy(tl1_icpe, cheetah_plus_icpe_trap_vector_tl1, (8 * 4));
841 }
842 flushi(PAGE_OFFSET);
843}
844
845static void cheetah_flush_ecache(void)
846{
847 unsigned long flush_base = ecache_flush_physbase;
848 unsigned long flush_linesize = ecache_flush_linesize;
849 unsigned long flush_size = ecache_flush_size;
850
851 __asm__ __volatile__("1: subcc %0, %4, %0\n\t"
852 " bne,pt %%xcc, 1b\n\t"
853 " ldxa [%2 + %0] %3, %%g0\n\t"
854 : "=&r" (flush_size)
855 : "0" (flush_size), "r" (flush_base),
856 "i" (ASI_PHYS_USE_EC), "r" (flush_linesize));
857}
858
859static void cheetah_flush_ecache_line(unsigned long physaddr)
860{
861 unsigned long alias;
862
863 physaddr &= ~(8UL - 1UL);
864 physaddr = (ecache_flush_physbase +
865 (physaddr & ((ecache_flush_size>>1UL) - 1UL)));
866 alias = physaddr + (ecache_flush_size >> 1UL);
867 __asm__ __volatile__("ldxa [%0] %2, %%g0\n\t"
868 "ldxa [%1] %2, %%g0\n\t"
869 "membar #Sync"
870 : /* no outputs */
871 : "r" (physaddr), "r" (alias),
872 "i" (ASI_PHYS_USE_EC));
873}
874
875/* Unfortunately, the diagnostic access to the I-cache tags we need to
876 * use to clear the thing interferes with I-cache coherency transactions.
877 *
878 * So we must only flush the I-cache when it is disabled.
879 */
880static void __cheetah_flush_icache(void)
881{
David S. Miller80dc0d62005-09-26 00:32:17 -0700882 unsigned int icache_size, icache_line_size;
883 unsigned long addr;
884
885 icache_size = local_cpu_data().icache_size;
886 icache_line_size = local_cpu_data().icache_line_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
888 /* Clear the valid bits in all the tags. */
David S. Miller80dc0d62005-09-26 00:32:17 -0700889 for (addr = 0; addr < icache_size; addr += icache_line_size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
891 "membar #Sync"
892 : /* no outputs */
David S. Miller80dc0d62005-09-26 00:32:17 -0700893 : "r" (addr | (2 << 3)),
894 "i" (ASI_IC_TAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 }
896}
897
898static void cheetah_flush_icache(void)
899{
900 unsigned long dcu_save;
901
902 /* Save current DCU, disable I-cache. */
903 __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t"
904 "or %0, %2, %%g1\n\t"
905 "stxa %%g1, [%%g0] %1\n\t"
906 "membar #Sync"
907 : "=r" (dcu_save)
908 : "i" (ASI_DCU_CONTROL_REG), "i" (DCU_IC)
909 : "g1");
910
911 __cheetah_flush_icache();
912
913 /* Restore DCU register */
914 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
915 "membar #Sync"
916 : /* no outputs */
917 : "r" (dcu_save), "i" (ASI_DCU_CONTROL_REG));
918}
919
920static void cheetah_flush_dcache(void)
921{
David S. Miller80dc0d62005-09-26 00:32:17 -0700922 unsigned int dcache_size, dcache_line_size;
923 unsigned long addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
David S. Miller80dc0d62005-09-26 00:32:17 -0700925 dcache_size = local_cpu_data().dcache_size;
926 dcache_line_size = local_cpu_data().dcache_line_size;
927
928 for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
930 "membar #Sync"
931 : /* no outputs */
David S. Miller80dc0d62005-09-26 00:32:17 -0700932 : "r" (addr), "i" (ASI_DCACHE_TAG));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 }
934}
935
936/* In order to make the even parity correct we must do two things.
937 * First, we clear DC_data_parity and set DC_utag to an appropriate value.
938 * Next, we clear out all 32-bytes of data for that line. Data of
939 * all-zero + tag parity value of zero == correct parity.
940 */
941static void cheetah_plus_zap_dcache_parity(void)
942{
David S. Miller80dc0d62005-09-26 00:32:17 -0700943 unsigned int dcache_size, dcache_line_size;
944 unsigned long addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
David S. Miller80dc0d62005-09-26 00:32:17 -0700946 dcache_size = local_cpu_data().dcache_size;
947 dcache_line_size = local_cpu_data().dcache_line_size;
948
949 for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
950 unsigned long tag = (addr >> 14);
951 unsigned long line;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
953 __asm__ __volatile__("membar #Sync\n\t"
954 "stxa %0, [%1] %2\n\t"
955 "membar #Sync"
956 : /* no outputs */
David S. Miller80dc0d62005-09-26 00:32:17 -0700957 : "r" (tag), "r" (addr),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 "i" (ASI_DCACHE_UTAG));
David S. Miller80dc0d62005-09-26 00:32:17 -0700959 for (line = addr; line < addr + dcache_line_size; line += 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 __asm__ __volatile__("membar #Sync\n\t"
961 "stxa %%g0, [%0] %1\n\t"
962 "membar #Sync"
963 : /* no outputs */
David S. Miller80dc0d62005-09-26 00:32:17 -0700964 : "r" (line),
965 "i" (ASI_DCACHE_DATA));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 }
967}
968
969/* Conversion tables used to frob Cheetah AFSR syndrome values into
970 * something palatable to the memory controller driver get_unumber
971 * routine.
972 */
973#define MT0 137
974#define MT1 138
975#define MT2 139
976#define NONE 254
977#define MTC0 140
978#define MTC1 141
979#define MTC2 142
980#define MTC3 143
981#define C0 128
982#define C1 129
983#define C2 130
984#define C3 131
985#define C4 132
986#define C5 133
987#define C6 134
988#define C7 135
989#define C8 136
990#define M2 144
991#define M3 145
992#define M4 146
993#define M 147
994static unsigned char cheetah_ecc_syntab[] = {
995/*00*/NONE, C0, C1, M2, C2, M2, M3, 47, C3, M2, M2, 53, M2, 41, 29, M,
996/*01*/C4, M, M, 50, M2, 38, 25, M2, M2, 33, 24, M2, 11, M, M2, 16,
997/*02*/C5, M, M, 46, M2, 37, 19, M2, M, 31, 32, M, 7, M2, M2, 10,
998/*03*/M2, 40, 13, M2, 59, M, M2, 66, M, M2, M2, 0, M2, 67, 71, M,
999/*04*/C6, M, M, 43, M, 36, 18, M, M2, 49, 15, M, 63, M2, M2, 6,
1000/*05*/M2, 44, 28, M2, M, M2, M2, 52, 68, M2, M2, 62, M2, M3, M3, M4,
1001/*06*/M2, 26, 106, M2, 64, M, M2, 2, 120, M, M2, M3, M, M3, M3, M4,
1002/*07*/116, M2, M2, M3, M2, M3, M, M4, M2, 58, 54, M2, M, M4, M4, M3,
1003/*08*/C7, M2, M, 42, M, 35, 17, M2, M, 45, 14, M2, 21, M2, M2, 5,
1004/*09*/M, 27, M, M, 99, M, M, 3, 114, M2, M2, 20, M2, M3, M3, M,
1005/*0a*/M2, 23, 113, M2, 112, M2, M, 51, 95, M, M2, M3, M2, M3, M3, M2,
1006/*0b*/103, M, M2, M3, M2, M3, M3, M4, M2, 48, M, M, 73, M2, M, M3,
1007/*0c*/M2, 22, 110, M2, 109, M2, M, 9, 108, M2, M, M3, M2, M3, M3, M,
1008/*0d*/102, M2, M, M, M2, M3, M3, M, M2, M3, M3, M2, M, M4, M, M3,
1009/*0e*/98, M, M2, M3, M2, M, M3, M4, M2, M3, M3, M4, M3, M, M, M,
1010/*0f*/M2, M3, M3, M, M3, M, M, M, 56, M4, M, M3, M4, M, M, M,
1011/*10*/C8, M, M2, 39, M, 34, 105, M2, M, 30, 104, M, 101, M, M, 4,
1012/*11*/M, M, 100, M, 83, M, M2, 12, 87, M, M, 57, M2, M, M3, M,
1013/*12*/M2, 97, 82, M2, 78, M2, M2, 1, 96, M, M, M, M, M, M3, M2,
1014/*13*/94, M, M2, M3, M2, M, M3, M, M2, M, 79, M, 69, M, M4, M,
1015/*14*/M2, 93, 92, M, 91, M, M2, 8, 90, M2, M2, M, M, M, M, M4,
1016/*15*/89, M, M, M3, M2, M3, M3, M, M, M, M3, M2, M3, M2, M, M3,
1017/*16*/86, M, M2, M3, M2, M, M3, M, M2, M, M3, M, M3, M, M, M3,
1018/*17*/M, M, M3, M2, M3, M2, M4, M, 60, M, M2, M3, M4, M, M, M2,
1019/*18*/M2, 88, 85, M2, 84, M, M2, 55, 81, M2, M2, M3, M2, M3, M3, M4,
1020/*19*/77, M, M, M, M2, M3, M, M, M2, M3, M3, M4, M3, M2, M, M,
1021/*1a*/74, M, M2, M3, M, M, M3, M, M, M, M3, M, M3, M, M4, M3,
1022/*1b*/M2, 70, 107, M4, 65, M2, M2, M, 127, M, M, M, M2, M3, M3, M,
1023/*1c*/80, M2, M2, 72, M, 119, 118, M, M2, 126, 76, M, 125, M, M4, M3,
1024/*1d*/M2, 115, 124, M, 75, M, M, M3, 61, M, M4, M, M4, M, M, M,
1025/*1e*/M, 123, 122, M4, 121, M4, M, M3, 117, M2, M2, M3, M4, M3, M, M,
1026/*1f*/111, M, M, M, M4, M3, M3, M, M, M, M3, M, M3, M2, M, M
1027};
1028static unsigned char cheetah_mtag_syntab[] = {
1029 NONE, MTC0,
1030 MTC1, NONE,
1031 MTC2, NONE,
1032 NONE, MT0,
1033 MTC3, NONE,
1034 NONE, MT1,
1035 NONE, MT2,
1036 NONE, NONE
1037};
1038
1039/* Return the highest priority error conditon mentioned. */
David S. Millerd979f172007-10-27 00:13:04 -07001040static inline unsigned long cheetah_get_hipri(unsigned long afsr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041{
1042 unsigned long tmp = 0;
1043 int i;
1044
1045 for (i = 0; cheetah_error_table[i].mask; i++) {
1046 if ((tmp = (afsr & cheetah_error_table[i].mask)) != 0UL)
1047 return tmp;
1048 }
1049 return tmp;
1050}
1051
1052static const char *cheetah_get_string(unsigned long bit)
1053{
1054 int i;
1055
1056 for (i = 0; cheetah_error_table[i].mask; i++) {
1057 if ((bit & cheetah_error_table[i].mask) != 0UL)
1058 return cheetah_error_table[i].name;
1059 }
1060 return "???";
1061}
1062
1063extern int chmc_getunumber(int, unsigned long, char *, int);
1064
1065static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info,
1066 unsigned long afsr, unsigned long afar, int recoverable)
1067{
1068 unsigned long hipri;
1069 char unum[256];
1070
1071 printk("%s" "ERROR(%d): Cheetah error trap taken afsr[%016lx] afar[%016lx] TL1(%d)\n",
1072 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1073 afsr, afar,
1074 (afsr & CHAFSR_TL1) ? 1 : 0);
David S. Miller955c0542006-04-01 23:29:56 -08001075 printk("%s" "ERROR(%d): TPC[%lx] TNPC[%lx] O7[%lx] TSTATE[%lx]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
David S. Miller955c0542006-04-01 23:29:56 -08001077 regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate);
David S. Miller5af47db2006-10-30 01:10:20 -08001078 printk("%s" "ERROR(%d): ",
1079 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id());
David S. Miller4fe3ebe2008-07-17 22:11:32 -07001080 printk("TPC<%pS>\n", (void *) regs->tpc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n",
1082 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1083 (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT,
1084 (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT,
1085 (afsr & CHAFSR_ME) ? ", Multiple Errors" : "",
1086 (afsr & CHAFSR_PRIV) ? ", Privileged" : "");
1087 hipri = cheetah_get_hipri(afsr);
1088 printk("%s" "ERROR(%d): Highest priority error (%016lx) \"%s\"\n",
1089 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1090 hipri, cheetah_get_string(hipri));
1091
1092 /* Try to get unumber if relevant. */
1093#define ESYND_ERRORS (CHAFSR_IVC | CHAFSR_IVU | \
1094 CHAFSR_CPC | CHAFSR_CPU | \
1095 CHAFSR_UE | CHAFSR_CE | \
1096 CHAFSR_EDC | CHAFSR_EDU | \
1097 CHAFSR_UCC | CHAFSR_UCU | \
1098 CHAFSR_WDU | CHAFSR_WDC)
1099#define MSYND_ERRORS (CHAFSR_EMC | CHAFSR_EMU)
1100 if (afsr & ESYND_ERRORS) {
1101 int syndrome;
1102 int ret;
1103
1104 syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT;
1105 syndrome = cheetah_ecc_syntab[syndrome];
1106 ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum));
1107 if (ret != -1)
1108 printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n",
1109 (recoverable ? KERN_WARNING : KERN_CRIT),
1110 smp_processor_id(), unum);
1111 } else if (afsr & MSYND_ERRORS) {
1112 int syndrome;
1113 int ret;
1114
1115 syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT;
1116 syndrome = cheetah_mtag_syntab[syndrome];
1117 ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum));
1118 if (ret != -1)
1119 printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n",
1120 (recoverable ? KERN_WARNING : KERN_CRIT),
1121 smp_processor_id(), unum);
1122 }
1123
1124 /* Now dump the cache snapshots. */
1125 printk("%s" "ERROR(%d): D-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx]\n",
1126 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1127 (int) info->dcache_index,
1128 info->dcache_tag,
1129 info->dcache_utag,
1130 info->dcache_stag);
1131 printk("%s" "ERROR(%d): D-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n",
1132 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1133 info->dcache_data[0],
1134 info->dcache_data[1],
1135 info->dcache_data[2],
1136 info->dcache_data[3]);
1137 printk("%s" "ERROR(%d): I-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx] "
1138 "u[%016lx] l[%016lx]\n",
1139 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1140 (int) info->icache_index,
1141 info->icache_tag,
1142 info->icache_utag,
1143 info->icache_stag,
1144 info->icache_upper,
1145 info->icache_lower);
1146 printk("%s" "ERROR(%d): I-cache INSN0[%016lx] INSN1[%016lx] INSN2[%016lx] INSN3[%016lx]\n",
1147 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1148 info->icache_data[0],
1149 info->icache_data[1],
1150 info->icache_data[2],
1151 info->icache_data[3]);
1152 printk("%s" "ERROR(%d): I-cache INSN4[%016lx] INSN5[%016lx] INSN6[%016lx] INSN7[%016lx]\n",
1153 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1154 info->icache_data[4],
1155 info->icache_data[5],
1156 info->icache_data[6],
1157 info->icache_data[7]);
1158 printk("%s" "ERROR(%d): E-cache idx[%x] tag[%016lx]\n",
1159 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1160 (int) info->ecache_index, info->ecache_tag);
1161 printk("%s" "ERROR(%d): E-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n",
1162 (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
1163 info->ecache_data[0],
1164 info->ecache_data[1],
1165 info->ecache_data[2],
1166 info->ecache_data[3]);
1167
1168 afsr = (afsr & ~hipri) & cheetah_afsr_errors;
1169 while (afsr != 0UL) {
1170 unsigned long bit = cheetah_get_hipri(afsr);
1171
1172 printk("%s" "ERROR: Multiple-error (%016lx) \"%s\"\n",
1173 (recoverable ? KERN_WARNING : KERN_CRIT),
1174 bit, cheetah_get_string(bit));
1175
1176 afsr &= ~bit;
1177 }
1178
1179 if (!recoverable)
1180 printk(KERN_CRIT "ERROR: This condition is not recoverable.\n");
1181}
1182
1183static int cheetah_recheck_errors(struct cheetah_err_info *logp)
1184{
1185 unsigned long afsr, afar;
1186 int ret = 0;
1187
1188 __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t"
1189 : "=r" (afsr)
1190 : "i" (ASI_AFSR));
1191 if ((afsr & cheetah_afsr_errors) != 0) {
1192 if (logp != NULL) {
1193 __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t"
1194 : "=r" (afar)
1195 : "i" (ASI_AFAR));
1196 logp->afsr = afsr;
1197 logp->afar = afar;
1198 }
1199 ret = 1;
1200 }
1201 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
1202 "membar #Sync\n\t"
1203 : : "r" (afsr), "i" (ASI_AFSR));
1204
1205 return ret;
1206}
1207
1208void cheetah_fecc_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
1209{
1210 struct cheetah_err_info local_snapshot, *p;
1211 int recoverable;
1212
1213 /* Flush E-cache */
1214 cheetah_flush_ecache();
1215
1216 p = cheetah_get_error_log(afsr);
1217 if (!p) {
1218 prom_printf("ERROR: Early Fast-ECC error afsr[%016lx] afar[%016lx]\n",
1219 afsr, afar);
1220 prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
1221 smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate);
1222 prom_halt();
1223 }
1224
1225 /* Grab snapshot of logged error. */
1226 memcpy(&local_snapshot, p, sizeof(local_snapshot));
1227
1228 /* If the current trap snapshot does not match what the
1229 * trap handler passed along into our args, big trouble.
1230 * In such a case, mark the local copy as invalid.
1231 *
1232 * Else, it matches and we mark the afsr in the non-local
1233 * copy as invalid so we may log new error traps there.
1234 */
1235 if (p->afsr != afsr || p->afar != afar)
1236 local_snapshot.afsr = CHAFSR_INVALID;
1237 else
1238 p->afsr = CHAFSR_INVALID;
1239
1240 cheetah_flush_icache();
1241 cheetah_flush_dcache();
1242
1243 /* Re-enable I-cache/D-cache */
1244 __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
1245 "or %%g1, %1, %%g1\n\t"
1246 "stxa %%g1, [%%g0] %0\n\t"
1247 "membar #Sync"
1248 : /* no outputs */
1249 : "i" (ASI_DCU_CONTROL_REG),
1250 "i" (DCU_DC | DCU_IC)
1251 : "g1");
1252
1253 /* Re-enable error reporting */
1254 __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
1255 "or %%g1, %1, %%g1\n\t"
1256 "stxa %%g1, [%%g0] %0\n\t"
1257 "membar #Sync"
1258 : /* no outputs */
1259 : "i" (ASI_ESTATE_ERROR_EN),
1260 "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN)
1261 : "g1");
1262
1263 /* Decide if we can continue after handling this trap and
1264 * logging the error.
1265 */
1266 recoverable = 1;
1267 if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP))
1268 recoverable = 0;
1269
1270 /* Re-check AFSR/AFAR. What we are looking for here is whether a new
1271 * error was logged while we had error reporting traps disabled.
1272 */
1273 if (cheetah_recheck_errors(&local_snapshot)) {
1274 unsigned long new_afsr = local_snapshot.afsr;
1275
1276 /* If we got a new asynchronous error, die... */
1277 if (new_afsr & (CHAFSR_EMU | CHAFSR_EDU |
1278 CHAFSR_WDU | CHAFSR_CPU |
1279 CHAFSR_IVU | CHAFSR_UE |
1280 CHAFSR_BERR | CHAFSR_TO))
1281 recoverable = 0;
1282 }
1283
1284 /* Log errors. */
1285 cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable);
1286
1287 if (!recoverable)
1288 panic("Irrecoverable Fast-ECC error trap.\n");
1289
1290 /* Flush E-cache to kick the error trap handlers out. */
1291 cheetah_flush_ecache();
1292}
1293
1294/* Try to fix a correctable error by pushing the line out from
1295 * the E-cache. Recheck error reporting registers to see if the
1296 * problem is intermittent.
1297 */
1298static int cheetah_fix_ce(unsigned long physaddr)
1299{
1300 unsigned long orig_estate;
1301 unsigned long alias1, alias2;
1302 int ret;
1303
1304 /* Make sure correctable error traps are disabled. */
1305 __asm__ __volatile__("ldxa [%%g0] %2, %0\n\t"
1306 "andn %0, %1, %%g1\n\t"
1307 "stxa %%g1, [%%g0] %2\n\t"
1308 "membar #Sync"
1309 : "=&r" (orig_estate)
1310 : "i" (ESTATE_ERROR_CEEN),
1311 "i" (ASI_ESTATE_ERROR_EN)
1312 : "g1");
1313
1314 /* We calculate alias addresses that will force the
1315 * cache line in question out of the E-cache. Then
1316 * we bring it back in with an atomic instruction so
1317 * that we get it in some modified/exclusive state,
1318 * then we displace it again to try and get proper ECC
1319 * pushed back into the system.
1320 */
1321 physaddr &= ~(8UL - 1UL);
1322 alias1 = (ecache_flush_physbase +
1323 (physaddr & ((ecache_flush_size >> 1) - 1)));
1324 alias2 = alias1 + (ecache_flush_size >> 1);
1325 __asm__ __volatile__("ldxa [%0] %3, %%g0\n\t"
1326 "ldxa [%1] %3, %%g0\n\t"
1327 "casxa [%2] %3, %%g0, %%g0\n\t"
1328 "membar #StoreLoad | #StoreStore\n\t"
1329 "ldxa [%0] %3, %%g0\n\t"
1330 "ldxa [%1] %3, %%g0\n\t"
1331 "membar #Sync"
1332 : /* no outputs */
1333 : "r" (alias1), "r" (alias2),
1334 "r" (physaddr), "i" (ASI_PHYS_USE_EC));
1335
1336 /* Did that trigger another error? */
1337 if (cheetah_recheck_errors(NULL)) {
1338 /* Try one more time. */
1339 __asm__ __volatile__("ldxa [%0] %1, %%g0\n\t"
1340 "membar #Sync"
1341 : : "r" (physaddr), "i" (ASI_PHYS_USE_EC));
1342 if (cheetah_recheck_errors(NULL))
1343 ret = 2;
1344 else
1345 ret = 1;
1346 } else {
1347 /* No new error, intermittent problem. */
1348 ret = 0;
1349 }
1350
1351 /* Restore error enables. */
1352 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
1353 "membar #Sync"
1354 : : "r" (orig_estate), "i" (ASI_ESTATE_ERROR_EN));
1355
1356 return ret;
1357}
1358
1359/* Return non-zero if PADDR is a valid physical memory address. */
1360static int cheetah_check_main_memory(unsigned long paddr)
1361{
David S. Miller10147572005-09-28 21:46:43 -07001362 unsigned long vaddr = PAGE_OFFSET + paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
David S. Miller13edad72005-09-29 17:58:26 -07001364 if (vaddr > (unsigned long) high_memory)
David S. Millered3ffaf2005-09-28 21:48:25 -07001365 return 0;
1366
David S. Miller10147572005-09-28 21:46:43 -07001367 return kern_addr_valid(vaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368}
1369
1370void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
1371{
1372 struct cheetah_err_info local_snapshot, *p;
1373 int recoverable, is_memory;
1374
1375 p = cheetah_get_error_log(afsr);
1376 if (!p) {
1377 prom_printf("ERROR: Early CEE error afsr[%016lx] afar[%016lx]\n",
1378 afsr, afar);
1379 prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
1380 smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate);
1381 prom_halt();
1382 }
1383
1384 /* Grab snapshot of logged error. */
1385 memcpy(&local_snapshot, p, sizeof(local_snapshot));
1386
1387 /* If the current trap snapshot does not match what the
1388 * trap handler passed along into our args, big trouble.
1389 * In such a case, mark the local copy as invalid.
1390 *
1391 * Else, it matches and we mark the afsr in the non-local
1392 * copy as invalid so we may log new error traps there.
1393 */
1394 if (p->afsr != afsr || p->afar != afar)
1395 local_snapshot.afsr = CHAFSR_INVALID;
1396 else
1397 p->afsr = CHAFSR_INVALID;
1398
1399 is_memory = cheetah_check_main_memory(afar);
1400
1401 if (is_memory && (afsr & CHAFSR_CE) != 0UL) {
1402 /* XXX Might want to log the results of this operation
1403 * XXX somewhere... -DaveM
1404 */
1405 cheetah_fix_ce(afar);
1406 }
1407
1408 {
1409 int flush_all, flush_line;
1410
1411 flush_all = flush_line = 0;
1412 if ((afsr & CHAFSR_EDC) != 0UL) {
1413 if ((afsr & cheetah_afsr_errors) == CHAFSR_EDC)
1414 flush_line = 1;
1415 else
1416 flush_all = 1;
1417 } else if ((afsr & CHAFSR_CPC) != 0UL) {
1418 if ((afsr & cheetah_afsr_errors) == CHAFSR_CPC)
1419 flush_line = 1;
1420 else
1421 flush_all = 1;
1422 }
1423
1424 /* Trap handler only disabled I-cache, flush it. */
1425 cheetah_flush_icache();
1426
1427 /* Re-enable I-cache */
1428 __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
1429 "or %%g1, %1, %%g1\n\t"
1430 "stxa %%g1, [%%g0] %0\n\t"
1431 "membar #Sync"
1432 : /* no outputs */
1433 : "i" (ASI_DCU_CONTROL_REG),
1434 "i" (DCU_IC)
1435 : "g1");
1436
1437 if (flush_all)
1438 cheetah_flush_ecache();
1439 else if (flush_line)
1440 cheetah_flush_ecache_line(afar);
1441 }
1442
1443 /* Re-enable error reporting */
1444 __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
1445 "or %%g1, %1, %%g1\n\t"
1446 "stxa %%g1, [%%g0] %0\n\t"
1447 "membar #Sync"
1448 : /* no outputs */
1449 : "i" (ASI_ESTATE_ERROR_EN),
1450 "i" (ESTATE_ERROR_CEEN)
1451 : "g1");
1452
1453 /* Decide if we can continue after handling this trap and
1454 * logging the error.
1455 */
1456 recoverable = 1;
1457 if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP))
1458 recoverable = 0;
1459
1460 /* Re-check AFSR/AFAR */
1461 (void) cheetah_recheck_errors(&local_snapshot);
1462
1463 /* Log errors. */
1464 cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable);
1465
1466 if (!recoverable)
1467 panic("Irrecoverable Correctable-ECC error trap.\n");
1468}
1469
1470void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
1471{
1472 struct cheetah_err_info local_snapshot, *p;
1473 int recoverable, is_memory;
1474
1475#ifdef CONFIG_PCI
1476 /* Check for the special PCI poke sequence. */
1477 if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
1478 cheetah_flush_icache();
1479 cheetah_flush_dcache();
1480
1481 /* Re-enable I-cache/D-cache */
1482 __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
1483 "or %%g1, %1, %%g1\n\t"
1484 "stxa %%g1, [%%g0] %0\n\t"
1485 "membar #Sync"
1486 : /* no outputs */
1487 : "i" (ASI_DCU_CONTROL_REG),
1488 "i" (DCU_DC | DCU_IC)
1489 : "g1");
1490
1491 /* Re-enable error reporting */
1492 __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
1493 "or %%g1, %1, %%g1\n\t"
1494 "stxa %%g1, [%%g0] %0\n\t"
1495 "membar #Sync"
1496 : /* no outputs */
1497 : "i" (ASI_ESTATE_ERROR_EN),
1498 "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN)
1499 : "g1");
1500
1501 (void) cheetah_recheck_errors(NULL);
1502
1503 pci_poke_faulted = 1;
1504 regs->tpc += 4;
1505 regs->tnpc = regs->tpc + 4;
1506 return;
1507 }
1508#endif
1509
1510 p = cheetah_get_error_log(afsr);
1511 if (!p) {
1512 prom_printf("ERROR: Early deferred error afsr[%016lx] afar[%016lx]\n",
1513 afsr, afar);
1514 prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
1515 smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate);
1516 prom_halt();
1517 }
1518
1519 /* Grab snapshot of logged error. */
1520 memcpy(&local_snapshot, p, sizeof(local_snapshot));
1521
1522 /* If the current trap snapshot does not match what the
1523 * trap handler passed along into our args, big trouble.
1524 * In such a case, mark the local copy as invalid.
1525 *
1526 * Else, it matches and we mark the afsr in the non-local
1527 * copy as invalid so we may log new error traps there.
1528 */
1529 if (p->afsr != afsr || p->afar != afar)
1530 local_snapshot.afsr = CHAFSR_INVALID;
1531 else
1532 p->afsr = CHAFSR_INVALID;
1533
1534 is_memory = cheetah_check_main_memory(afar);
1535
1536 {
1537 int flush_all, flush_line;
1538
1539 flush_all = flush_line = 0;
1540 if ((afsr & CHAFSR_EDU) != 0UL) {
1541 if ((afsr & cheetah_afsr_errors) == CHAFSR_EDU)
1542 flush_line = 1;
1543 else
1544 flush_all = 1;
1545 } else if ((afsr & CHAFSR_BERR) != 0UL) {
1546 if ((afsr & cheetah_afsr_errors) == CHAFSR_BERR)
1547 flush_line = 1;
1548 else
1549 flush_all = 1;
1550 }
1551
1552 cheetah_flush_icache();
1553 cheetah_flush_dcache();
1554
1555 /* Re-enable I/D caches */
1556 __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
1557 "or %%g1, %1, %%g1\n\t"
1558 "stxa %%g1, [%%g0] %0\n\t"
1559 "membar #Sync"
1560 : /* no outputs */
1561 : "i" (ASI_DCU_CONTROL_REG),
1562 "i" (DCU_IC | DCU_DC)
1563 : "g1");
1564
1565 if (flush_all)
1566 cheetah_flush_ecache();
1567 else if (flush_line)
1568 cheetah_flush_ecache_line(afar);
1569 }
1570
1571 /* Re-enable error reporting */
1572 __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
1573 "or %%g1, %1, %%g1\n\t"
1574 "stxa %%g1, [%%g0] %0\n\t"
1575 "membar #Sync"
1576 : /* no outputs */
1577 : "i" (ASI_ESTATE_ERROR_EN),
1578 "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN)
1579 : "g1");
1580
1581 /* Decide if we can continue after handling this trap and
1582 * logging the error.
1583 */
1584 recoverable = 1;
1585 if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP))
1586 recoverable = 0;
1587
1588 /* Re-check AFSR/AFAR. What we are looking for here is whether a new
1589 * error was logged while we had error reporting traps disabled.
1590 */
1591 if (cheetah_recheck_errors(&local_snapshot)) {
1592 unsigned long new_afsr = local_snapshot.afsr;
1593
1594 /* If we got a new asynchronous error, die... */
1595 if (new_afsr & (CHAFSR_EMU | CHAFSR_EDU |
1596 CHAFSR_WDU | CHAFSR_CPU |
1597 CHAFSR_IVU | CHAFSR_UE |
1598 CHAFSR_BERR | CHAFSR_TO))
1599 recoverable = 0;
1600 }
1601
1602 /* Log errors. */
1603 cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable);
1604
1605 /* "Recoverable" here means we try to yank the page from ever
1606 * being newly used again. This depends upon a few things:
1607 * 1) Must be main memory, and AFAR must be valid.
1608 * 2) If we trapped from user, OK.
1609 * 3) Else, if we trapped from kernel we must find exception
1610 * table entry (ie. we have to have been accessing user
1611 * space).
1612 *
1613 * If AFAR is not in main memory, or we trapped from kernel
1614 * and cannot find an exception table entry, it is unacceptable
1615 * to try and continue.
1616 */
1617 if (recoverable && is_memory) {
1618 if ((regs->tstate & TSTATE_PRIV) == 0UL) {
1619 /* OK, usermode access. */
1620 recoverable = 1;
1621 } else {
David S. Miller8cf14af2005-09-28 20:21:11 -07001622 const struct exception_table_entry *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
David S. Miller8cf14af2005-09-28 20:21:11 -07001624 entry = search_exception_tables(regs->tpc);
1625 if (entry) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 /* OK, kernel access to userspace. */
1627 recoverable = 1;
1628
1629 } else {
1630 /* BAD, privileged state is corrupted. */
1631 recoverable = 0;
1632 }
1633
1634 if (recoverable) {
1635 if (pfn_valid(afar >> PAGE_SHIFT))
1636 get_page(pfn_to_page(afar >> PAGE_SHIFT));
1637 else
1638 recoverable = 0;
1639
1640 /* Only perform fixup if we still have a
1641 * recoverable condition.
1642 */
1643 if (recoverable) {
David S. Miller8cf14af2005-09-28 20:21:11 -07001644 regs->tpc = entry->fixup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 regs->tnpc = regs->tpc + 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 }
1647 }
1648 }
1649 } else {
1650 recoverable = 0;
1651 }
1652
1653 if (!recoverable)
1654 panic("Irrecoverable deferred error trap.\n");
1655}
1656
1657/* Handle a D/I cache parity error trap. TYPE is encoded as:
1658 *
1659 * Bit0: 0=dcache,1=icache
1660 * Bit1: 0=recoverable,1=unrecoverable
1661 *
1662 * The hardware has disabled both the I-cache and D-cache in
1663 * the %dcr register.
1664 */
1665void cheetah_plus_parity_error(int type, struct pt_regs *regs)
1666{
1667 if (type & 0x1)
1668 __cheetah_flush_icache();
1669 else
1670 cheetah_plus_zap_dcache_parity();
1671 cheetah_flush_dcache();
1672
1673 /* Re-enable I-cache/D-cache */
1674 __asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
1675 "or %%g1, %1, %%g1\n\t"
1676 "stxa %%g1, [%%g0] %0\n\t"
1677 "membar #Sync"
1678 : /* no outputs */
1679 : "i" (ASI_DCU_CONTROL_REG),
1680 "i" (DCU_DC | DCU_IC)
1681 : "g1");
1682
1683 if (type & 0x2) {
1684 printk(KERN_EMERG "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n",
1685 smp_processor_id(),
1686 (type & 0x1) ? 'I' : 'D',
1687 regs->tpc);
David S. Miller4fe3ebe2008-07-17 22:11:32 -07001688 printk(KERN_EMERG "TPC<%pS>\n", (void *) regs->tpc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 panic("Irrecoverable Cheetah+ parity error.");
1690 }
1691
1692 printk(KERN_WARNING "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n",
1693 smp_processor_id(),
1694 (type & 0x1) ? 'I' : 'D',
1695 regs->tpc);
David S. Miller4fe3ebe2008-07-17 22:11:32 -07001696 printk(KERN_WARNING "TPC<%pS>\n", (void *) regs->tpc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697}
1698
David S. Miller5b0c0572006-02-08 02:53:50 -08001699struct sun4v_error_entry {
1700 u64 err_handle;
1701 u64 err_stick;
1702
1703 u32 err_type;
1704#define SUN4V_ERR_TYPE_UNDEFINED 0
1705#define SUN4V_ERR_TYPE_UNCORRECTED_RES 1
1706#define SUN4V_ERR_TYPE_PRECISE_NONRES 2
1707#define SUN4V_ERR_TYPE_DEFERRED_NONRES 3
1708#define SUN4V_ERR_TYPE_WARNING_RES 4
1709
1710 u32 err_attrs;
1711#define SUN4V_ERR_ATTRS_PROCESSOR 0x00000001
1712#define SUN4V_ERR_ATTRS_MEMORY 0x00000002
1713#define SUN4V_ERR_ATTRS_PIO 0x00000004
1714#define SUN4V_ERR_ATTRS_INT_REGISTERS 0x00000008
1715#define SUN4V_ERR_ATTRS_FPU_REGISTERS 0x00000010
1716#define SUN4V_ERR_ATTRS_USER_MODE 0x01000000
1717#define SUN4V_ERR_ATTRS_PRIV_MODE 0x02000000
1718#define SUN4V_ERR_ATTRS_RES_QUEUE_FULL 0x80000000
1719
1720 u64 err_raddr;
1721 u32 err_size;
1722 u16 err_cpu;
1723 u16 err_pad;
1724};
1725
1726static atomic_t sun4v_resum_oflow_cnt = ATOMIC_INIT(0);
1727static atomic_t sun4v_nonresum_oflow_cnt = ATOMIC_INIT(0);
1728
1729static const char *sun4v_err_type_to_str(u32 type)
1730{
1731 switch (type) {
1732 case SUN4V_ERR_TYPE_UNDEFINED:
1733 return "undefined";
1734 case SUN4V_ERR_TYPE_UNCORRECTED_RES:
1735 return "uncorrected resumable";
1736 case SUN4V_ERR_TYPE_PRECISE_NONRES:
1737 return "precise nonresumable";
1738 case SUN4V_ERR_TYPE_DEFERRED_NONRES:
1739 return "deferred nonresumable";
1740 case SUN4V_ERR_TYPE_WARNING_RES:
1741 return "warning resumable";
1742 default:
1743 return "unknown";
1744 };
1745}
1746
David S. Miller5224e6c2006-06-06 17:37:41 -07001747static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
David S. Miller5b0c0572006-02-08 02:53:50 -08001748{
1749 int cnt;
1750
1751 printk("%s: Reporting on cpu %d\n", pfx, cpu);
1752 printk("%s: err_handle[%lx] err_stick[%lx] err_type[%08x:%s]\n",
1753 pfx,
1754 ent->err_handle, ent->err_stick,
1755 ent->err_type,
1756 sun4v_err_type_to_str(ent->err_type));
1757 printk("%s: err_attrs[%08x:%s %s %s %s %s %s %s %s]\n",
1758 pfx,
1759 ent->err_attrs,
1760 ((ent->err_attrs & SUN4V_ERR_ATTRS_PROCESSOR) ?
1761 "processor" : ""),
1762 ((ent->err_attrs & SUN4V_ERR_ATTRS_MEMORY) ?
1763 "memory" : ""),
1764 ((ent->err_attrs & SUN4V_ERR_ATTRS_PIO) ?
1765 "pio" : ""),
1766 ((ent->err_attrs & SUN4V_ERR_ATTRS_INT_REGISTERS) ?
1767 "integer-regs" : ""),
1768 ((ent->err_attrs & SUN4V_ERR_ATTRS_FPU_REGISTERS) ?
1769 "fpu-regs" : ""),
1770 ((ent->err_attrs & SUN4V_ERR_ATTRS_USER_MODE) ?
1771 "user" : ""),
1772 ((ent->err_attrs & SUN4V_ERR_ATTRS_PRIV_MODE) ?
1773 "privileged" : ""),
1774 ((ent->err_attrs & SUN4V_ERR_ATTRS_RES_QUEUE_FULL) ?
1775 "queue-full" : ""));
1776 printk("%s: err_raddr[%016lx] err_size[%u] err_cpu[%u]\n",
1777 pfx,
1778 ent->err_raddr, ent->err_size, ent->err_cpu);
1779
David S. Millerdbf3e952008-07-31 20:33:43 -07001780 show_regs(regs);
David S. Miller5224e6c2006-06-06 17:37:41 -07001781
David S. Miller5b0c0572006-02-08 02:53:50 -08001782 if ((cnt = atomic_read(ocnt)) != 0) {
1783 atomic_set(ocnt, 0);
1784 wmb();
1785 printk("%s: Queue overflowed %d times.\n",
1786 pfx, cnt);
1787 }
1788}
1789
1790/* We run with %pil set to 15 and PSTATE_IE enabled in %pstate.
1791 * Log the event and clear the first word of the entry.
1792 */
1793void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
1794{
1795 struct sun4v_error_entry *ent, local_copy;
1796 struct trap_per_cpu *tb;
1797 unsigned long paddr;
1798 int cpu;
1799
1800 cpu = get_cpu();
1801
1802 tb = &trap_block[cpu];
1803 paddr = tb->resum_kernel_buf_pa + offset;
1804 ent = __va(paddr);
1805
1806 memcpy(&local_copy, ent, sizeof(struct sun4v_error_entry));
1807
1808 /* We have a local copy now, so release the entry. */
1809 ent->err_handle = 0;
1810 wmb();
1811
1812 put_cpu();
1813
David S. Millera2c1e062006-11-29 21:16:21 -08001814 if (ent->err_type == SUN4V_ERR_TYPE_WARNING_RES) {
1815 /* If err_type is 0x4, it's a powerdown request. Do
1816 * not do the usual resumable error log because that
1817 * makes it look like some abnormal error.
1818 */
1819 printk(KERN_INFO "Power down request...\n");
1820 kill_cad_pid(SIGINT, 1);
1821 return;
1822 }
1823
David S. Miller5224e6c2006-06-06 17:37:41 -07001824 sun4v_log_error(regs, &local_copy, cpu,
David S. Miller5b0c0572006-02-08 02:53:50 -08001825 KERN_ERR "RESUMABLE ERROR",
1826 &sun4v_resum_oflow_cnt);
1827}
1828
1829/* If we try to printk() we'll probably make matters worse, by trying
1830 * to retake locks this cpu already holds or causing more errors. So
1831 * just bump a counter, and we'll report these counter bumps above.
1832 */
1833void sun4v_resum_overflow(struct pt_regs *regs)
1834{
1835 atomic_inc(&sun4v_resum_oflow_cnt);
1836}
1837
1838/* We run with %pil set to 15 and PSTATE_IE enabled in %pstate.
1839 * Log the event, clear the first word of the entry, and die.
1840 */
1841void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset)
1842{
1843 struct sun4v_error_entry *ent, local_copy;
1844 struct trap_per_cpu *tb;
1845 unsigned long paddr;
1846 int cpu;
1847
1848 cpu = get_cpu();
1849
1850 tb = &trap_block[cpu];
1851 paddr = tb->nonresum_kernel_buf_pa + offset;
1852 ent = __va(paddr);
1853
1854 memcpy(&local_copy, ent, sizeof(struct sun4v_error_entry));
1855
1856 /* We have a local copy now, so release the entry. */
1857 ent->err_handle = 0;
1858 wmb();
1859
1860 put_cpu();
1861
1862#ifdef CONFIG_PCI
1863 /* Check for the special PCI poke sequence. */
1864 if (pci_poke_in_progress && pci_poke_cpu == cpu) {
1865 pci_poke_faulted = 1;
1866 regs->tpc += 4;
1867 regs->tnpc = regs->tpc + 4;
1868 return;
1869 }
1870#endif
1871
David S. Miller5224e6c2006-06-06 17:37:41 -07001872 sun4v_log_error(regs, &local_copy, cpu,
David S. Miller5b0c0572006-02-08 02:53:50 -08001873 KERN_EMERG "NON-RESUMABLE ERROR",
1874 &sun4v_nonresum_oflow_cnt);
1875
1876 panic("Non-resumable error.");
1877}
1878
1879/* If we try to printk() we'll probably make matters worse, by trying
1880 * to retake locks this cpu already holds or causing more errors. So
1881 * just bump a counter, and we'll report these counter bumps above.
1882 */
1883void sun4v_nonresum_overflow(struct pt_regs *regs)
1884{
1885 /* XXX Actually even this can make not that much sense. Perhaps
1886 * XXX we should just pull the plug and panic directly from here?
1887 */
1888 atomic_inc(&sun4v_nonresum_oflow_cnt);
1889}
1890
David S. Miller6c8927c2006-02-17 14:58:02 -08001891unsigned long sun4v_err_itlb_vaddr;
1892unsigned long sun4v_err_itlb_ctx;
1893unsigned long sun4v_err_itlb_pte;
1894unsigned long sun4v_err_itlb_error;
1895
1896void sun4v_itlb_error_report(struct pt_regs *regs, int tl)
1897{
1898 if (tl > 1)
1899 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
1900
David S. Miller04d74752006-02-18 17:06:28 -08001901 printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n",
1902 regs->tpc, tl);
David S. Miller4fe3ebe2008-07-17 22:11:32 -07001903 printk(KERN_EMERG "SUN4V-ITLB: TPC<%pS>\n", (void *) regs->tpc);
David S. Miller6320bce2008-01-17 01:32:09 -08001904 printk(KERN_EMERG "SUN4V-ITLB: O7[%lx]\n", regs->u_regs[UREG_I7]);
David S. Miller4fe3ebe2008-07-17 22:11:32 -07001905 printk(KERN_EMERG "SUN4V-ITLB: O7<%pS>\n",
1906 (void *) regs->u_regs[UREG_I7]);
David S. Miller04d74752006-02-18 17:06:28 -08001907 printk(KERN_EMERG "SUN4V-ITLB: vaddr[%lx] ctx[%lx] "
1908 "pte[%lx] error[%lx]\n",
David S. Miller6c8927c2006-02-17 14:58:02 -08001909 sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx,
1910 sun4v_err_itlb_pte, sun4v_err_itlb_error);
David S. Miller04d74752006-02-18 17:06:28 -08001911
David S. Miller6c8927c2006-02-17 14:58:02 -08001912 prom_halt();
1913}
1914
1915unsigned long sun4v_err_dtlb_vaddr;
1916unsigned long sun4v_err_dtlb_ctx;
1917unsigned long sun4v_err_dtlb_pte;
1918unsigned long sun4v_err_dtlb_error;
1919
1920void sun4v_dtlb_error_report(struct pt_regs *regs, int tl)
1921{
1922 if (tl > 1)
1923 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
1924
David S. Miller04d74752006-02-18 17:06:28 -08001925 printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n",
1926 regs->tpc, tl);
David S. Miller4fe3ebe2008-07-17 22:11:32 -07001927 printk(KERN_EMERG "SUN4V-DTLB: TPC<%pS>\n", (void *) regs->tpc);
David S. Miller6320bce2008-01-17 01:32:09 -08001928 printk(KERN_EMERG "SUN4V-DTLB: O7[%lx]\n", regs->u_regs[UREG_I7]);
David S. Miller4fe3ebe2008-07-17 22:11:32 -07001929 printk(KERN_EMERG "SUN4V-DTLB: O7<%pS>\n",
1930 (void *) regs->u_regs[UREG_I7]);
David S. Miller04d74752006-02-18 17:06:28 -08001931 printk(KERN_EMERG "SUN4V-DTLB: vaddr[%lx] ctx[%lx] "
1932 "pte[%lx] error[%lx]\n",
David S. Miller6c8927c2006-02-17 14:58:02 -08001933 sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx,
1934 sun4v_err_dtlb_pte, sun4v_err_dtlb_error);
David S. Miller04d74752006-02-18 17:06:28 -08001935
David S. Miller6c8927c2006-02-17 14:58:02 -08001936 prom_halt();
1937}
1938
David S. Miller2a3a5f52006-02-26 19:31:49 -08001939void hypervisor_tlbop_error(unsigned long err, unsigned long op)
1940{
1941 printk(KERN_CRIT "SUN4V: TLB hv call error %lu for op %lu\n",
1942 err, op);
1943}
1944
1945void hypervisor_tlbop_error_xcall(unsigned long err, unsigned long op)
1946{
1947 printk(KERN_CRIT "SUN4V: XCALL TLB hv call error %lu for op %lu\n",
1948 err, op);
1949}
1950
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951void do_fpe_common(struct pt_regs *regs)
1952{
1953 if (regs->tstate & TSTATE_PRIV) {
1954 regs->tpc = regs->tnpc;
1955 regs->tnpc += 4;
1956 } else {
1957 unsigned long fsr = current_thread_info()->xfsr[0];
1958 siginfo_t info;
1959
1960 if (test_thread_flag(TIF_32BIT)) {
1961 regs->tpc &= 0xffffffff;
1962 regs->tnpc &= 0xffffffff;
1963 }
1964 info.si_signo = SIGFPE;
1965 info.si_errno = 0;
1966 info.si_addr = (void __user *)regs->tpc;
1967 info.si_trapno = 0;
1968 info.si_code = __SI_FAULT;
1969 if ((fsr & 0x1c000) == (1 << 14)) {
1970 if (fsr & 0x10)
1971 info.si_code = FPE_FLTINV;
1972 else if (fsr & 0x08)
1973 info.si_code = FPE_FLTOVF;
1974 else if (fsr & 0x04)
1975 info.si_code = FPE_FLTUND;
1976 else if (fsr & 0x02)
1977 info.si_code = FPE_FLTDIV;
1978 else if (fsr & 0x01)
1979 info.si_code = FPE_FLTRES;
1980 }
1981 force_sig_info(SIGFPE, &info, current);
1982 }
1983}
1984
1985void do_fpieee(struct pt_regs *regs)
1986{
1987 if (notify_die(DIE_TRAP, "fpu exception ieee", regs,
1988 0, 0x24, SIGFPE) == NOTIFY_STOP)
1989 return;
1990
1991 do_fpe_common(regs);
1992}
1993
1994extern int do_mathemu(struct pt_regs *, struct fpustate *);
1995
1996void do_fpother(struct pt_regs *regs)
1997{
1998 struct fpustate *f = FPUSTATE;
1999 int ret = 0;
2000
2001 if (notify_die(DIE_TRAP, "fpu exception other", regs,
2002 0, 0x25, SIGFPE) == NOTIFY_STOP)
2003 return;
2004
2005 switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
2006 case (2 << 14): /* unfinished_FPop */
2007 case (3 << 14): /* unimplemented_FPop */
2008 ret = do_mathemu(regs, f);
2009 break;
2010 }
2011 if (ret)
2012 return;
2013 do_fpe_common(regs);
2014}
2015
2016void do_tof(struct pt_regs *regs)
2017{
2018 siginfo_t info;
2019
2020 if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs,
2021 0, 0x26, SIGEMT) == NOTIFY_STOP)
2022 return;
2023
2024 if (regs->tstate & TSTATE_PRIV)
2025 die_if_kernel("Penguin overflow trap from kernel mode", regs);
2026 if (test_thread_flag(TIF_32BIT)) {
2027 regs->tpc &= 0xffffffff;
2028 regs->tnpc &= 0xffffffff;
2029 }
2030 info.si_signo = SIGEMT;
2031 info.si_errno = 0;
2032 info.si_code = EMT_TAGOVF;
2033 info.si_addr = (void __user *)regs->tpc;
2034 info.si_trapno = 0;
2035 force_sig_info(SIGEMT, &info, current);
2036}
2037
2038void do_div0(struct pt_regs *regs)
2039{
2040 siginfo_t info;
2041
2042 if (notify_die(DIE_TRAP, "integer division by zero", regs,
2043 0, 0x28, SIGFPE) == NOTIFY_STOP)
2044 return;
2045
2046 if (regs->tstate & TSTATE_PRIV)
2047 die_if_kernel("TL0: Kernel divide by zero.", regs);
2048 if (test_thread_flag(TIF_32BIT)) {
2049 regs->tpc &= 0xffffffff;
2050 regs->tnpc &= 0xffffffff;
2051 }
2052 info.si_signo = SIGFPE;
2053 info.si_errno = 0;
2054 info.si_code = FPE_INTDIV;
2055 info.si_addr = (void __user *)regs->tpc;
2056 info.si_trapno = 0;
2057 force_sig_info(SIGFPE, &info, current);
2058}
2059
David S. Miller99cd2202008-03-26 00:19:43 -07002060static void instruction_dump(unsigned int *pc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061{
2062 int i;
2063
2064 if ((((unsigned long) pc) & 3))
2065 return;
2066
2067 printk("Instruction DUMP:");
2068 for (i = -3; i < 6; i++)
2069 printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
2070 printk("\n");
2071}
2072
David S. Miller99cd2202008-03-26 00:19:43 -07002073static void user_instruction_dump(unsigned int __user *pc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074{
2075 int i;
2076 unsigned int buf[9];
2077
2078 if ((((unsigned long) pc) & 3))
2079 return;
2080
2081 if (copy_from_user(buf, pc - 3, sizeof(buf)))
2082 return;
2083
2084 printk("Instruction DUMP:");
2085 for (i = 0; i < 9; i++)
2086 printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>');
2087 printk("\n");
2088}
2089
2090void show_stack(struct task_struct *tsk, unsigned long *_ksp)
2091{
David S. Miller77c664f2008-04-24 03:28:52 -07002092 unsigned long fp, thread_base, ksp;
David S. Millerc1f193a2007-07-30 00:17:12 -07002093 struct thread_info *tp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 int count = 0;
2095
2096 ksp = (unsigned long) _ksp;
David S. Millerc1f193a2007-07-30 00:17:12 -07002097 if (!tsk)
2098 tsk = current;
2099 tp = task_thread_info(tsk);
2100 if (ksp == 0UL) {
2101 if (tsk == current)
2102 asm("mov %%fp, %0" : "=r" (ksp));
2103 else
2104 ksp = tp->ksp;
2105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 if (tp == current_thread_info())
2107 flushw_all();
2108
2109 fp = ksp + STACK_BIAS;
2110 thread_base = (unsigned long) tp;
2111
David S. Miller4fe3ebe2008-07-17 22:11:32 -07002112 printk("Call Trace:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 do {
David S. Miller14d2c682008-05-21 18:15:53 -07002114 struct sparc_stackf *sf;
David S. Miller77c664f2008-04-24 03:28:52 -07002115 struct pt_regs *regs;
2116 unsigned long pc;
2117
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 /* Bogus frame pointer? */
2119 if (fp < (thread_base + sizeof(struct thread_info)) ||
2120 fp >= (thread_base + THREAD_SIZE))
2121 break;
David S. Miller14d2c682008-05-21 18:15:53 -07002122 sf = (struct sparc_stackf *) fp;
2123 regs = (struct pt_regs *) (sf + 1);
David S. Miller77c664f2008-04-24 03:28:52 -07002124
2125 if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
David S. Miller14d2c682008-05-21 18:15:53 -07002126 if (!(regs->tstate & TSTATE_PRIV))
2127 break;
David S. Miller77c664f2008-04-24 03:28:52 -07002128 pc = regs->tpc;
2129 fp = regs->u_regs[UREG_I6] + STACK_BIAS;
2130 } else {
David S. Miller14d2c682008-05-21 18:15:53 -07002131 pc = sf->callers_pc;
2132 fp = (unsigned long)sf->fp + STACK_BIAS;
David S. Miller77c664f2008-04-24 03:28:52 -07002133 }
2134
David S. Miller4fe3ebe2008-07-17 22:11:32 -07002135 printk(" [%016lx] %pS\n", pc, (void *) pc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 } while (++count < 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137}
2138
2139void dump_stack(void)
2140{
David S. Millerc1f193a2007-07-30 00:17:12 -07002141 show_stack(current, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142}
2143
2144EXPORT_SYMBOL(dump_stack);
2145
2146static inline int is_kernel_stack(struct task_struct *task,
2147 struct reg_window *rw)
2148{
2149 unsigned long rw_addr = (unsigned long) rw;
2150 unsigned long thread_base, thread_end;
2151
2152 if (rw_addr < PAGE_OFFSET) {
2153 if (task != &init_task)
2154 return 0;
2155 }
2156
Al Viroee3eea12006-01-12 01:05:43 -08002157 thread_base = (unsigned long) task_stack_page(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 thread_end = thread_base + sizeof(union thread_union);
2159 if (rw_addr >= thread_base &&
2160 rw_addr < thread_end &&
2161 !(rw_addr & 0x7UL))
2162 return 1;
2163
2164 return 0;
2165}
2166
2167static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
2168{
2169 unsigned long fp = rw->ins[6];
2170
2171 if (!fp)
2172 return NULL;
2173
2174 return (struct reg_window *) (fp + STACK_BIAS);
2175}
2176
2177void die_if_kernel(char *str, struct pt_regs *regs)
2178{
2179 static int die_counter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 int count = 0;
2181
2182 /* Amuse the user. */
2183 printk(
2184" \\|/ ____ \\|/\n"
2185" \"@'/ .. \\`@\"\n"
2186" /_| \\__/ |_\\\n"
2187" \\__U_/\n");
2188
Alexey Dobriyan19c58702007-10-18 23:40:41 -07002189 printk("%s(%d): %s [#%d]\n", current->comm, task_pid_nr(current), str, ++die_counter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
2191 __asm__ __volatile__("flushw");
David S. Millerdbf3e952008-07-31 20:33:43 -07002192 show_regs(regs);
Pavel Emelianovbcdcd8e2007-07-17 04:03:42 -07002193 add_taint(TAINT_DIE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 if (regs->tstate & TSTATE_PRIV) {
2195 struct reg_window *rw = (struct reg_window *)
2196 (regs->u_regs[UREG_FP] + STACK_BIAS);
2197
2198 /* Stop the back trace when we hit userland or we
2199 * find some badly aligned kernel stack.
2200 */
2201 while (rw &&
2202 count++ < 30&&
2203 is_kernel_stack(current, rw)) {
David S. Miller4fe3ebe2008-07-17 22:11:32 -07002204 printk("Caller[%016lx]: %pS\n", rw->ins[7],
2205 (void *) rw->ins[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206
2207 rw = kernel_stack_up(rw);
2208 }
2209 instruction_dump ((unsigned int *) regs->tpc);
2210 } else {
2211 if (test_thread_flag(TIF_32BIT)) {
2212 regs->tpc &= 0xffffffff;
2213 regs->tnpc &= 0xffffffff;
2214 }
2215 user_instruction_dump ((unsigned int __user *) regs->tpc);
2216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 if (regs->tstate & TSTATE_PRIV)
2218 do_exit(SIGKILL);
2219 do_exit(SIGSEGV);
2220}
2221
David S. Miller6e7726e2006-11-19 14:38:25 -08002222#define VIS_OPCODE_MASK ((0x3 << 30) | (0x3f << 19))
2223#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19))
2224
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225extern int handle_popc(u32 insn, struct pt_regs *regs);
2226extern int handle_ldf_stq(u32 insn, struct pt_regs *regs);
David S. Miller6e7726e2006-11-19 14:38:25 -08002227extern int vis_emul(struct pt_regs *, unsigned int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228
2229void do_illegal_instruction(struct pt_regs *regs)
2230{
2231 unsigned long pc = regs->tpc;
2232 unsigned long tstate = regs->tstate;
2233 u32 insn;
2234 siginfo_t info;
2235
2236 if (notify_die(DIE_TRAP, "illegal instruction", regs,
2237 0, 0x10, SIGILL) == NOTIFY_STOP)
2238 return;
2239
2240 if (tstate & TSTATE_PRIV)
2241 die_if_kernel("Kernel illegal instruction", regs);
2242 if (test_thread_flag(TIF_32BIT))
2243 pc = (u32)pc;
2244 if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
2245 if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ {
2246 if (handle_popc(insn, regs))
2247 return;
2248 } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ {
2249 if (handle_ldf_stq(insn, regs))
2250 return;
David S. Miller0c51ed92006-03-13 01:27:34 -08002251 } else if (tlb_type == hypervisor) {
David S. Miller6e7726e2006-11-19 14:38:25 -08002252 if ((insn & VIS_OPCODE_MASK) == VIS_OPCODE_VAL) {
2253 if (!vis_emul(regs, insn))
2254 return;
2255 } else {
2256 struct fpustate *f = FPUSTATE;
David S. Miller0c51ed92006-03-13 01:27:34 -08002257
David S. Miller6e7726e2006-11-19 14:38:25 -08002258 /* XXX maybe verify XFSR bits like
2259 * XXX do_fpother() does?
2260 */
2261 if (do_mathemu(regs, f))
2262 return;
2263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 }
2265 }
2266 info.si_signo = SIGILL;
2267 info.si_errno = 0;
2268 info.si_code = ILL_ILLOPC;
2269 info.si_addr = (void __user *)pc;
2270 info.si_trapno = 0;
2271 force_sig_info(SIGILL, &info, current);
2272}
2273
David S. Millered6b0b42006-02-09 20:20:34 -08002274extern void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn);
2275
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
2277{
2278 siginfo_t info;
2279
2280 if (notify_die(DIE_TRAP, "memory address unaligned", regs,
2281 0, 0x34, SIGSEGV) == NOTIFY_STOP)
2282 return;
2283
2284 if (regs->tstate & TSTATE_PRIV) {
David S. Millered6b0b42006-02-09 20:20:34 -08002285 kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 return;
2287 }
2288 info.si_signo = SIGBUS;
2289 info.si_errno = 0;
2290 info.si_code = BUS_ADRALN;
2291 info.si_addr = (void __user *)sfar;
2292 info.si_trapno = 0;
2293 force_sig_info(SIGBUS, &info, current);
2294}
2295
David S. Miller9f8a5b82006-02-14 16:39:22 -08002296void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
David S. Millered6b0b42006-02-09 20:20:34 -08002297{
2298 siginfo_t info;
2299
2300 if (notify_die(DIE_TRAP, "memory address unaligned", regs,
2301 0, 0x34, SIGSEGV) == NOTIFY_STOP)
2302 return;
2303
2304 if (regs->tstate & TSTATE_PRIV) {
2305 kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc));
2306 return;
2307 }
2308 info.si_signo = SIGBUS;
2309 info.si_errno = 0;
2310 info.si_code = BUS_ADRALN;
2311 info.si_addr = (void __user *) addr;
2312 info.si_trapno = 0;
2313 force_sig_info(SIGBUS, &info, current);
2314}
2315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316void do_privop(struct pt_regs *regs)
2317{
2318 siginfo_t info;
2319
2320 if (notify_die(DIE_TRAP, "privileged operation", regs,
2321 0, 0x11, SIGILL) == NOTIFY_STOP)
2322 return;
2323
2324 if (test_thread_flag(TIF_32BIT)) {
2325 regs->tpc &= 0xffffffff;
2326 regs->tnpc &= 0xffffffff;
2327 }
2328 info.si_signo = SIGILL;
2329 info.si_errno = 0;
2330 info.si_code = ILL_PRVOPC;
2331 info.si_addr = (void __user *)regs->tpc;
2332 info.si_trapno = 0;
2333 force_sig_info(SIGILL, &info, current);
2334}
2335
2336void do_privact(struct pt_regs *regs)
2337{
2338 do_privop(regs);
2339}
2340
2341/* Trap level 1 stuff or other traps we should never see... */
2342void do_cee(struct pt_regs *regs)
2343{
2344 die_if_kernel("TL0: Cache Error Exception", regs);
2345}
2346
2347void do_cee_tl1(struct pt_regs *regs)
2348{
2349 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2350 die_if_kernel("TL1: Cache Error Exception", regs);
2351}
2352
2353void do_dae_tl1(struct pt_regs *regs)
2354{
2355 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2356 die_if_kernel("TL1: Data Access Exception", regs);
2357}
2358
2359void do_iae_tl1(struct pt_regs *regs)
2360{
2361 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2362 die_if_kernel("TL1: Instruction Access Exception", regs);
2363}
2364
2365void do_div0_tl1(struct pt_regs *regs)
2366{
2367 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2368 die_if_kernel("TL1: DIV0 Exception", regs);
2369}
2370
2371void do_fpdis_tl1(struct pt_regs *regs)
2372{
2373 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2374 die_if_kernel("TL1: FPU Disabled", regs);
2375}
2376
2377void do_fpieee_tl1(struct pt_regs *regs)
2378{
2379 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2380 die_if_kernel("TL1: FPU IEEE Exception", regs);
2381}
2382
2383void do_fpother_tl1(struct pt_regs *regs)
2384{
2385 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2386 die_if_kernel("TL1: FPU Other Exception", regs);
2387}
2388
2389void do_ill_tl1(struct pt_regs *regs)
2390{
2391 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2392 die_if_kernel("TL1: Illegal Instruction Exception", regs);
2393}
2394
2395void do_irq_tl1(struct pt_regs *regs)
2396{
2397 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2398 die_if_kernel("TL1: IRQ Exception", regs);
2399}
2400
2401void do_lddfmna_tl1(struct pt_regs *regs)
2402{
2403 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2404 die_if_kernel("TL1: LDDF Exception", regs);
2405}
2406
2407void do_stdfmna_tl1(struct pt_regs *regs)
2408{
2409 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2410 die_if_kernel("TL1: STDF Exception", regs);
2411}
2412
2413void do_paw(struct pt_regs *regs)
2414{
2415 die_if_kernel("TL0: Phys Watchpoint Exception", regs);
2416}
2417
2418void do_paw_tl1(struct pt_regs *regs)
2419{
2420 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2421 die_if_kernel("TL1: Phys Watchpoint Exception", regs);
2422}
2423
2424void do_vaw(struct pt_regs *regs)
2425{
2426 die_if_kernel("TL0: Virt Watchpoint Exception", regs);
2427}
2428
2429void do_vaw_tl1(struct pt_regs *regs)
2430{
2431 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2432 die_if_kernel("TL1: Virt Watchpoint Exception", regs);
2433}
2434
2435void do_tof_tl1(struct pt_regs *regs)
2436{
2437 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2438 die_if_kernel("TL1: Tag Overflow Exception", regs);
2439}
2440
2441void do_getpsr(struct pt_regs *regs)
2442{
2443 regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate);
2444 regs->tpc = regs->tnpc;
2445 regs->tnpc += 4;
2446 if (test_thread_flag(TIF_32BIT)) {
2447 regs->tpc &= 0xffffffff;
2448 regs->tnpc &= 0xffffffff;
2449 }
2450}
2451
David S. Miller56fb4df2006-02-26 23:24:22 -08002452struct trap_per_cpu trap_block[NR_CPUS];
2453
2454/* This can get invoked before sched_init() so play it super safe
2455 * and use hard_smp_processor_id().
2456 */
David S. Miller72aff532006-02-17 01:29:17 -08002457void init_cur_cpu_trap(struct thread_info *t)
David S. Miller56fb4df2006-02-26 23:24:22 -08002458{
2459 int cpu = hard_smp_processor_id();
2460 struct trap_per_cpu *p = &trap_block[cpu];
2461
David S. Miller72aff532006-02-17 01:29:17 -08002462 p->thread = t;
David S. Miller56fb4df2006-02-26 23:24:22 -08002463 p->pgd_paddr = 0;
2464}
2465
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466extern void thread_info_offsets_are_bolixed_dave(void);
David S. Miller56fb4df2006-02-26 23:24:22 -08002467extern void trap_per_cpu_offsets_are_bolixed_dave(void);
David S. Millerdcc1e8d2006-03-22 00:49:59 -08002468extern void tsb_config_offsets_are_bolixed_dave(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
2470/* Only invoked on boot processor. */
2471void __init trap_init(void)
2472{
2473 /* Compile time sanity check. */
2474 if (TI_TASK != offsetof(struct thread_info, task) ||
2475 TI_FLAGS != offsetof(struct thread_info, flags) ||
2476 TI_CPU != offsetof(struct thread_info, cpu) ||
2477 TI_FPSAVED != offsetof(struct thread_info, fpsaved) ||
2478 TI_KSP != offsetof(struct thread_info, ksp) ||
2479 TI_FAULT_ADDR != offsetof(struct thread_info, fault_address) ||
2480 TI_KREGS != offsetof(struct thread_info, kregs) ||
2481 TI_UTRAPS != offsetof(struct thread_info, utraps) ||
2482 TI_EXEC_DOMAIN != offsetof(struct thread_info, exec_domain) ||
2483 TI_REG_WINDOW != offsetof(struct thread_info, reg_window) ||
2484 TI_RWIN_SPTRS != offsetof(struct thread_info, rwbuf_stkptrs) ||
2485 TI_GSR != offsetof(struct thread_info, gsr) ||
2486 TI_XFSR != offsetof(struct thread_info, xfsr) ||
2487 TI_USER_CNTD0 != offsetof(struct thread_info, user_cntd0) ||
2488 TI_USER_CNTD1 != offsetof(struct thread_info, user_cntd1) ||
2489 TI_KERN_CNTD0 != offsetof(struct thread_info, kernel_cntd0) ||
2490 TI_KERN_CNTD1 != offsetof(struct thread_info, kernel_cntd1) ||
2491 TI_PCR != offsetof(struct thread_info, pcr_reg) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) ||
David S. Millerdb7d9a42005-07-24 19:36:26 -07002493 TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
2494 TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) ||
David S. Millera3f99852005-08-19 15:55:33 -07002495 TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) ||
2496 TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) ||
2497 TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 TI_FPREGS != offsetof(struct thread_info, fpregs) ||
2499 (TI_FPREGS & (64 - 1)))
2500 thread_info_offsets_are_bolixed_dave();
2501
David S. Miller56fb4df2006-02-26 23:24:22 -08002502 if (TRAP_PER_CPU_THREAD != offsetof(struct trap_per_cpu, thread) ||
David S. Millere088ad72006-02-07 23:51:49 -08002503 (TRAP_PER_CPU_PGD_PADDR !=
2504 offsetof(struct trap_per_cpu, pgd_paddr)) ||
2505 (TRAP_PER_CPU_CPU_MONDO_PA !=
2506 offsetof(struct trap_per_cpu, cpu_mondo_pa)) ||
2507 (TRAP_PER_CPU_DEV_MONDO_PA !=
2508 offsetof(struct trap_per_cpu, dev_mondo_pa)) ||
2509 (TRAP_PER_CPU_RESUM_MONDO_PA !=
2510 offsetof(struct trap_per_cpu, resum_mondo_pa)) ||
David S. Miller5b0c0572006-02-08 02:53:50 -08002511 (TRAP_PER_CPU_RESUM_KBUF_PA !=
2512 offsetof(struct trap_per_cpu, resum_kernel_buf_pa)) ||
David S. Millere088ad72006-02-07 23:51:49 -08002513 (TRAP_PER_CPU_NONRESUM_MONDO_PA !=
2514 offsetof(struct trap_per_cpu, nonresum_mondo_pa)) ||
David S. Miller5b0c0572006-02-08 02:53:50 -08002515 (TRAP_PER_CPU_NONRESUM_KBUF_PA !=
2516 offsetof(struct trap_per_cpu, nonresum_kernel_buf_pa)) ||
David S. Millere088ad72006-02-07 23:51:49 -08002517 (TRAP_PER_CPU_FAULT_INFO !=
David S. Miller1d2f1f92006-02-08 16:41:20 -08002518 offsetof(struct trap_per_cpu, fault_info)) ||
2519 (TRAP_PER_CPU_CPU_MONDO_BLOCK_PA !=
2520 offsetof(struct trap_per_cpu, cpu_mondo_block_pa)) ||
2521 (TRAP_PER_CPU_CPU_LIST_PA !=
David S. Millerdcc1e8d2006-03-22 00:49:59 -08002522 offsetof(struct trap_per_cpu, cpu_list_pa)) ||
2523 (TRAP_PER_CPU_TSB_HUGE !=
2524 offsetof(struct trap_per_cpu, tsb_huge)) ||
2525 (TRAP_PER_CPU_TSB_HUGE_TEMP !=
David S. Millerfd0504c32006-06-20 01:20:00 -07002526 offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
David S. Millereb2d8d62007-10-13 21:42:46 -07002527 (TRAP_PER_CPU_IRQ_WORKLIST_PA !=
2528 offsetof(struct trap_per_cpu, irq_worklist_pa)) ||
David S. Miller5cbc3072007-05-25 15:49:59 -07002529 (TRAP_PER_CPU_CPU_MONDO_QMASK !=
2530 offsetof(struct trap_per_cpu, cpu_mondo_qmask)) ||
2531 (TRAP_PER_CPU_DEV_MONDO_QMASK !=
2532 offsetof(struct trap_per_cpu, dev_mondo_qmask)) ||
2533 (TRAP_PER_CPU_RESUM_QMASK !=
2534 offsetof(struct trap_per_cpu, resum_qmask)) ||
2535 (TRAP_PER_CPU_NONRESUM_QMASK !=
2536 offsetof(struct trap_per_cpu, nonresum_qmask)))
David S. Miller56fb4df2006-02-26 23:24:22 -08002537 trap_per_cpu_offsets_are_bolixed_dave();
2538
David S. Millerdcc1e8d2006-03-22 00:49:59 -08002539 if ((TSB_CONFIG_TSB !=
2540 offsetof(struct tsb_config, tsb)) ||
2541 (TSB_CONFIG_RSS_LIMIT !=
2542 offsetof(struct tsb_config, tsb_rss_limit)) ||
2543 (TSB_CONFIG_NENTRIES !=
2544 offsetof(struct tsb_config, tsb_nentries)) ||
2545 (TSB_CONFIG_REG_VAL !=
2546 offsetof(struct tsb_config, tsb_reg_val)) ||
2547 (TSB_CONFIG_MAP_VADDR !=
2548 offsetof(struct tsb_config, tsb_map_vaddr)) ||
2549 (TSB_CONFIG_MAP_PTE !=
2550 offsetof(struct tsb_config, tsb_map_pte)))
2551 tsb_config_offsets_are_bolixed_dave();
2552
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 /* Attach to the address space of init_task. On SMP we
2554 * do this in smp.c:smp_callin for other cpus.
2555 */
2556 atomic_inc(&init_mm.mm_count);
2557 current->active_mm = &init_mm;
2558}