On Mon, Jan 13, 2003 at 07:04:36PM +0100, Geert Uytterhoeven wrote: > The following patch (against linux-mips-2.4.x CVS) cures my crash. > > I don't know on which CPUs this may happen (need #ifdef CONFIG_CPU_VR41XX?), > nor whether all branch and jump instructions are affected (I included > everything that starts with a `b' or `j'). I'm suggesting this alternative patch below. Comments? Ralf diff -u -r1.4.2.1 branch.h --- include/asm-mips/branch.h 7 May 2002 03:48:08 -0000 +++ include/asm-mips/branch.h 28 Jan 2003 02:34:12 -0000 @@ -8,11 +8,52 @@ #ifndef _ASM_BRANCH_H #define _ASM_BRANCH_H +#include <asm/inst.h> #include <asm/ptrace.h> +#include <asm/uaccess.h> +#include <asm/war.h> static inline int delay_slot(struct pt_regs *regs) { - return regs->cp0_cause & CAUSEF_BD; +#ifdef BDSLOT_WAR + union mips_instruction insn; + mm_segment_t seg; +#endif + int ds; + + ds = regs->cp0_cause & CAUSEF_BD; + if (ds) + return ds; + +#ifdef BDSLOT_WAR + if (!user_mode(regs)) + set_fs(KERNEL_DS); + __get_user(insn.word, (unsigned int *)regs->cp0_epc); + set_fs(seg); + + switch (insn.i_format.opcode) { + /* + * On some CPUs, if an unaligned access happens in a branch delay slot + * and the branch is not taken, EPC points at the branch instruction, + * but the BD bit in the cause register is not set. + */ + case bcond_op: + case j_op: + case jal_op: + case beq_op: + case bne_op: + case blez_op: + case bgtz_op: + case beql_op: + case bnel_op: + case blezl_op: + case bgtzl_op: + case jalx_op: + return 1; + } +#endif + + return 0; } static inline unsigned long exception_epc(struct pt_regs *regs) diff -u -r1.1.2.4 war.h --- include/asm-mips/war.h 2 Oct 2002 19:42:04 -0000 +++ include/asm-mips/war.h 28 Jan 2003 02:34:13 -0000 @@ -84,4 +84,17 @@ #endif +#if !defined(CONFIG_CPU_MIPS32) && !defined(CONFIG_CPU_MIPS64) + +/* + * A bunch of CPUs predating the MIPS32 and MIPS64 specs do not always set + * the BD bit in c0_cause on an exception. For those we need to look at + * the faulting instruction to deciede if we were faulting in a delay slot. + * There might be further CPUs where BD works as expected but for now we're + * paranoid. + */ +#define BDSLOT_WAR + +#endif + #endif /* _ASM_WAR_H */