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