diff options
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r-- | arch/mips/kernel/traps.c | 111 |
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 | ||
81 | static void show_raw_backtrace(unsigned long reg29) | 82 | static 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); | |||
192 | static void show_code(unsigned int __user *pc) | 196 | static 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 | ||
312 | void show_registers(const struct pt_regs *regs) | 319 | void 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 | ||
1006 | static int __initdata l1parity = 1; | ||
1007 | static int __init nol1parity(char *s) | ||
1008 | { | ||
1009 | l1parity = 0; | ||
1010 | return 1; | ||
1011 | } | ||
1012 | __setup("nol1par", nol1parity); | ||
1013 | static int __initdata l2parity = 1; | ||
1014 | static 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) { |