aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2008-04-28 12:14:26 -0400
committerRalf Baechle <ralf@linux-mips.org>2008-04-28 12:14:26 -0400
commit39b8d5254246ac56342b72f812255c8f7a74dca9 (patch)
treea9ec6bfb5d09a8367c34cc2067328d1b49bb46c1 /arch/mips/kernel/traps.c
parent308402445e005a039a72b315cd9b5ceeaea0063c (diff)
[MIPS] Add support for MIPS CMP platform.
Signed-off-by: Chris Dearman <chris@mips.com> Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c111
1 files changed, 99 insertions, 12 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index d51f4e98455f..88185cd40c3b 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -22,6 +22,7 @@
22#include <linux/kallsyms.h> 22#include <linux/kallsyms.h>
23#include <linux/bootmem.h> 23#include <linux/bootmem.h>
24#include <linux/interrupt.h> 24#include <linux/interrupt.h>
25#include <linux/ptrace.h>
25 26
26#include <asm/bootinfo.h> 27#include <asm/bootinfo.h>
27#include <asm/branch.h> 28#include <asm/branch.h>
@@ -80,19 +81,22 @@ void (*board_bind_eic_interrupt)(int irq, int regset);
80 81
81static void show_raw_backtrace(unsigned long reg29) 82static void show_raw_backtrace(unsigned long reg29)
82{ 83{
83 unsigned long *sp = (unsigned long *)reg29; 84 unsigned long *sp = (unsigned long *)(reg29 & ~3);
84 unsigned long addr; 85 unsigned long addr;
85 86
86 printk("Call Trace:"); 87 printk("Call Trace:");
87#ifdef CONFIG_KALLSYMS 88#ifdef CONFIG_KALLSYMS
88 printk("\n"); 89 printk("\n");
89#endif 90#endif
90 while (!kstack_end(sp)) { 91#define IS_KVA01(a) ((((unsigned int)a) & 0xc0000000) == 0x80000000)
91 addr = *sp++; 92 if (IS_KVA01(sp)) {
92 if (__kernel_text_address(addr)) 93 while (!kstack_end(sp)) {
93 print_ip_sym(addr); 94 addr = *sp++;
95 if (__kernel_text_address(addr))
96 print_ip_sym(addr);
97 }
98 printk("\n");
94 } 99 }
95 printk("\n");
96} 100}
97 101
98#ifdef CONFIG_KALLSYMS 102#ifdef CONFIG_KALLSYMS
@@ -192,16 +196,19 @@ EXPORT_SYMBOL(dump_stack);
192static void show_code(unsigned int __user *pc) 196static void show_code(unsigned int __user *pc)
193{ 197{
194 long i; 198 long i;
199 unsigned short __user *pc16 = NULL;
195 200
196 printk("\nCode:"); 201 printk("\nCode:");
197 202
203 if ((unsigned long)pc & 1)
204 pc16 = (unsigned short __user *)((unsigned long)pc & ~1);
198 for(i = -3 ; i < 6 ; i++) { 205 for(i = -3 ; i < 6 ; i++) {
199 unsigned int insn; 206 unsigned int insn;
200 if (__get_user(insn, pc + i)) { 207 if (pc16 ? __get_user(insn, pc16 + i) : __get_user(insn, pc + i)) {
201 printk(" (Bad address in epc)\n"); 208 printk(" (Bad address in epc)\n");
202 break; 209 break;
203 } 210 }
204 printk("%c%08x%c", (i?' ':'<'), insn, (i?' ':'>')); 211 printk("%c%0*x%c", (i?' ':'<'), pc16 ? 4 : 8, insn, (i?' ':'>'));
205 } 212 }
206} 213}
207 214
@@ -311,10 +318,21 @@ void show_regs(struct pt_regs *regs)
311 318
312void show_registers(const struct pt_regs *regs) 319void show_registers(const struct pt_regs *regs)
313{ 320{
321 const int field = 2 * sizeof(unsigned long);
322
314 __show_regs(regs); 323 __show_regs(regs);
315 print_modules(); 324 print_modules();
316 printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n", 325 printk("Process %s (pid: %d, threadinfo=%p, task=%p, tls=%0*lx)\n",
317 current->comm, task_pid_nr(current), current_thread_info(), current); 326 current->comm, current->pid, current_thread_info(), current,
327 field, current_thread_info()->tp_value);
328 if (cpu_has_userlocal) {
329 unsigned long tls;
330
331 tls = read_c0_userlocal();
332 if (tls != current_thread_info()->tp_value)
333 printk("*HwTLS: %0*lx\n", field, tls);
334 }
335
318 show_stacktrace(current, regs); 336 show_stacktrace(current, regs);
319 show_code((unsigned int __user *) regs->cp0_epc); 337 show_code((unsigned int __user *) regs->cp0_epc);
320 printk("\n"); 338 printk("\n");
@@ -985,6 +1003,21 @@ asmlinkage void do_reserved(struct pt_regs *regs)
985 (regs->cp0_cause & 0x7f) >> 2); 1003 (regs->cp0_cause & 0x7f) >> 2);
986} 1004}
987 1005
1006static int __initdata l1parity = 1;
1007static int __init nol1parity(char *s)
1008{
1009 l1parity = 0;
1010 return 1;
1011}
1012__setup("nol1par", nol1parity);
1013static int __initdata l2parity = 1;
1014static int __init nol2parity(char *s)
1015{
1016 l2parity = 0;
1017 return 1;
1018}
1019__setup("nol2par", nol2parity);
1020
988/* 1021/*
989 * Some MIPS CPUs can enable/disable for cache parity detection, but do 1022 * Some MIPS CPUs can enable/disable for cache parity detection, but do
990 * it different ways. 1023 * it different ways.
@@ -994,6 +1027,62 @@ static inline void parity_protection_init(void)
994 switch (current_cpu_type()) { 1027 switch (current_cpu_type()) {
995 case CPU_24K: 1028 case CPU_24K:
996 case CPU_34K: 1029 case CPU_34K:
1030 case CPU_74K:
1031 case CPU_1004K:
1032 {
1033#define ERRCTL_PE 0x80000000
1034#define ERRCTL_L2P 0x00800000
1035 unsigned long errctl;
1036 unsigned int l1parity_present, l2parity_present;
1037
1038 errctl = read_c0_ecc();
1039 errctl &= ~(ERRCTL_PE|ERRCTL_L2P);
1040
1041 /* probe L1 parity support */
1042 write_c0_ecc(errctl | ERRCTL_PE);
1043 back_to_back_c0_hazard();
1044 l1parity_present = (read_c0_ecc() & ERRCTL_PE);
1045
1046 /* probe L2 parity support */
1047 write_c0_ecc(errctl|ERRCTL_L2P);
1048 back_to_back_c0_hazard();
1049 l2parity_present = (read_c0_ecc() & ERRCTL_L2P);
1050
1051 if (l1parity_present && l2parity_present) {
1052 if (l1parity)
1053 errctl |= ERRCTL_PE;
1054 if (l1parity ^ l2parity)
1055 errctl |= ERRCTL_L2P;
1056 } else if (l1parity_present) {
1057 if (l1parity)
1058 errctl |= ERRCTL_PE;
1059 } else if (l2parity_present) {
1060 if (l2parity)
1061 errctl |= ERRCTL_L2P;
1062 } else {
1063 /* No parity available */
1064 }
1065
1066 printk(KERN_INFO "Writing ErrCtl register=%08lx\n", errctl);
1067
1068 write_c0_ecc(errctl);
1069 back_to_back_c0_hazard();
1070 errctl = read_c0_ecc();
1071 printk(KERN_INFO "Readback ErrCtl register=%08lx\n", errctl);
1072
1073 if (l1parity_present)
1074 printk(KERN_INFO "Cache parity protection %sabled\n",
1075 (errctl & ERRCTL_PE) ? "en" : "dis");
1076
1077 if (l2parity_present) {
1078 if (l1parity_present && l1parity)
1079 errctl ^= ERRCTL_L2P;
1080 printk(KERN_INFO "L2 cache parity protection %sabled\n",
1081 (errctl & ERRCTL_L2P) ? "en" : "dis");
1082 }
1083 }
1084 break;
1085
997 case CPU_5KC: 1086 case CPU_5KC:
998 write_c0_ecc(0x80000000); 1087 write_c0_ecc(0x80000000);
999 back_to_back_c0_hazard(); 1088 back_to_back_c0_hazard();
@@ -1353,7 +1442,6 @@ void __cpuinit per_cpu_trap_init(void)
1353 change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, 1442 change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
1354 status_set); 1443 status_set);
1355 1444
1356#ifdef CONFIG_CPU_MIPSR2
1357 if (cpu_has_mips_r2) { 1445 if (cpu_has_mips_r2) {
1358 unsigned int enable = 0x0000000f; 1446 unsigned int enable = 0x0000000f;
1359 1447
@@ -1362,7 +1450,6 @@ void __cpuinit per_cpu_trap_init(void)
1362 1450
1363 write_c0_hwrena(enable); 1451 write_c0_hwrena(enable);
1364 } 1452 }
1365#endif
1366 1453
1367#ifdef CONFIG_MIPS_MT_SMTC 1454#ifdef CONFIG_MIPS_MT_SMTC
1368 if (!secondaryTC) { 1455 if (!secondaryTC) {