diff options
Diffstat (limited to 'arch/sparc64/kernel/traps.c')
-rw-r--r-- | arch/sparc64/kernel/traps.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index fe1796c939c3..ad67784292db 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c | |||
@@ -10,7 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/sched.h> /* for jiffies */ | 13 | #include <linux/sched.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/kallsyms.h> | 15 | #include <linux/kallsyms.h> |
16 | #include <linux/signal.h> | 16 | #include <linux/signal.h> |
@@ -1873,6 +1873,16 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset) | |||
1873 | 1873 | ||
1874 | put_cpu(); | 1874 | put_cpu(); |
1875 | 1875 | ||
1876 | if (ent->err_type == SUN4V_ERR_TYPE_WARNING_RES) { | ||
1877 | /* If err_type is 0x4, it's a powerdown request. Do | ||
1878 | * not do the usual resumable error log because that | ||
1879 | * makes it look like some abnormal error. | ||
1880 | */ | ||
1881 | printk(KERN_INFO "Power down request...\n"); | ||
1882 | kill_cad_pid(SIGINT, 1); | ||
1883 | return; | ||
1884 | } | ||
1885 | |||
1876 | sun4v_log_error(regs, &local_copy, cpu, | 1886 | sun4v_log_error(regs, &local_copy, cpu, |
1877 | KERN_ERR "RESUMABLE ERROR", | 1887 | KERN_ERR "RESUMABLE ERROR", |
1878 | &sun4v_resum_oflow_cnt); | 1888 | &sun4v_resum_oflow_cnt); |
@@ -2261,8 +2271,12 @@ void die_if_kernel(char *str, struct pt_regs *regs) | |||
2261 | do_exit(SIGSEGV); | 2271 | do_exit(SIGSEGV); |
2262 | } | 2272 | } |
2263 | 2273 | ||
2274 | #define VIS_OPCODE_MASK ((0x3 << 30) | (0x3f << 19)) | ||
2275 | #define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19)) | ||
2276 | |||
2264 | extern int handle_popc(u32 insn, struct pt_regs *regs); | 2277 | extern int handle_popc(u32 insn, struct pt_regs *regs); |
2265 | extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); | 2278 | extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); |
2279 | extern int vis_emul(struct pt_regs *, unsigned int); | ||
2266 | 2280 | ||
2267 | void do_illegal_instruction(struct pt_regs *regs) | 2281 | void do_illegal_instruction(struct pt_regs *regs) |
2268 | { | 2282 | { |
@@ -2287,10 +2301,18 @@ void do_illegal_instruction(struct pt_regs *regs) | |||
2287 | if (handle_ldf_stq(insn, regs)) | 2301 | if (handle_ldf_stq(insn, regs)) |
2288 | return; | 2302 | return; |
2289 | } else if (tlb_type == hypervisor) { | 2303 | } else if (tlb_type == hypervisor) { |
2290 | extern int vis_emul(struct pt_regs *, unsigned int); | 2304 | if ((insn & VIS_OPCODE_MASK) == VIS_OPCODE_VAL) { |
2305 | if (!vis_emul(regs, insn)) | ||
2306 | return; | ||
2307 | } else { | ||
2308 | struct fpustate *f = FPUSTATE; | ||
2291 | 2309 | ||
2292 | if (!vis_emul(regs, insn)) | 2310 | /* XXX maybe verify XFSR bits like |
2293 | return; | 2311 | * XXX do_fpother() does? |
2312 | */ | ||
2313 | if (do_mathemu(regs, f)) | ||
2314 | return; | ||
2315 | } | ||
2294 | } | 2316 | } |
2295 | } | 2317 | } |
2296 | info.si_signo = SIGILL; | 2318 | info.si_signo = SIGILL; |