From 6e7726e16fb5e8f1169dbfcb75e321ac871af827 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 19 Nov 2006 14:38:25 -0800 Subject: [PATCH] [SPARC64]: Call do_mathemu on illegal instruction traps too. To add this logic, put the VIS instruction check at the vis_emul() call site instead of inside of vis_emul(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/traps.c | 18 +++++++++++++++--- arch/sparc64/kernel/visemul.c | 6 ------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index fe1796c939c3..ec7a60142bec 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -2261,8 +2261,12 @@ void die_if_kernel(char *str, struct pt_regs *regs) do_exit(SIGSEGV); } +#define VIS_OPCODE_MASK ((0x3 << 30) | (0x3f << 19)) +#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19)) + extern int handle_popc(u32 insn, struct pt_regs *regs); extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); +extern int vis_emul(struct pt_regs *, unsigned int); void do_illegal_instruction(struct pt_regs *regs) { @@ -2287,10 +2291,18 @@ void do_illegal_instruction(struct pt_regs *regs) if (handle_ldf_stq(insn, regs)) return; } else if (tlb_type == hypervisor) { - extern int vis_emul(struct pt_regs *, unsigned int); + if ((insn & VIS_OPCODE_MASK) == VIS_OPCODE_VAL) { + if (!vis_emul(regs, insn)) + return; + } else { + struct fpustate *f = FPUSTATE; - if (!vis_emul(regs, insn)) - return; + /* XXX maybe verify XFSR bits like + * XXX do_fpother() does? + */ + if (do_mathemu(regs, f)) + return; + } } } info.si_signo = SIGILL; diff --git a/arch/sparc64/kernel/visemul.c b/arch/sparc64/kernel/visemul.c index 84fedaa38aae..c3fd64706b53 100644 --- a/arch/sparc64/kernel/visemul.c +++ b/arch/sparc64/kernel/visemul.c @@ -128,9 +128,6 @@ /* 001001100 - Permute bytes as specified by GSR.MASK */ #define BSHUFFLE_OPF 0x04c -#define VIS_OPCODE_MASK ((0x3 << 30) | (0x3f << 19)) -#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19)) - #define VIS_OPF_SHIFT 5 #define VIS_OPF_MASK (0x1ff << VIS_OPF_SHIFT) @@ -810,9 +807,6 @@ int vis_emul(struct pt_regs *regs, unsigned int insn) if (get_user(insn, (u32 __user *) pc)) return -EFAULT; - if ((insn & VIS_OPCODE_MASK) != VIS_OPCODE_VAL) - return -EINVAL; - opf = (insn & VIS_OPF_MASK) >> VIS_OPF_SHIFT; switch (opf) { default: