patch-2.3.99-pre2 linux/arch/sparc/kernel/unaligned.c
Next file: linux/arch/sparc/lib/Makefile
Previous file: linux/arch/sparc/kernel/systbls.S
Back to the patch index
Back to the overall index
- Lines: 65
- Date:
Thu Mar 16 11:20:33 2000
- Orig file:
v2.3.99-pre1/linux/arch/sparc/kernel/unaligned.c
- Orig date:
Fri Jan 28 15:09:07 2000
diff -u --recursive --new-file v2.3.99-pre1/linux/arch/sparc/kernel/unaligned.c linux/arch/sparc/kernel/unaligned.c
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.20 2000/01/21 11:38:42 jj Exp $
+/* $Id: unaligned.c,v 1.21 2000/03/15 08:50:16 anton Exp $
* unaligned.c: Unaligned load/store trap handling with special
* cases for the kernel to do them more quickly.
*
@@ -106,6 +106,26 @@
return win->locals[reg - 16]; /* yes, I know what this does... */
}
+static inline unsigned long safe_fetch_reg(unsigned int reg, struct pt_regs *regs)
+{
+ struct reg_window *win;
+ unsigned long ret;
+
+ if(reg < 16)
+ return (!reg ? 0 : regs->u_regs[reg]);
+
+ /* Ho hum, the slightly complicated case. */
+ win = (struct reg_window *) regs->u_regs[UREG_FP];
+
+ if ((unsigned long)win & 3)
+ return -1;
+
+ if (get_user(ret, &win->locals[reg - 16]))
+ return -1;
+
+ return ret;
+}
+
static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
{
struct reg_window *win;
@@ -132,6 +152,22 @@
}
}
+static inline unsigned long safe_compute_effective_address(struct pt_regs *regs,
+ unsigned int insn)
+{
+ unsigned int rs1 = (insn >> 14) & 0x1f;
+ unsigned int rs2 = insn & 0x1f;
+ unsigned int rd = (insn >> 25) & 0x1f;
+
+ if(insn & 0x2000) {
+ maybe_flush_windows(rs1, 0, rd);
+ return (safe_fetch_reg(rs1, regs) + sign_extend_imm13(insn));
+ } else {
+ maybe_flush_windows(rs1, rs2, rd);
+ return (safe_fetch_reg(rs1, regs) + safe_fetch_reg(rs2, regs));
+ }
+}
+
/* This is just to make gcc think panic does return... */
static void unaligned_panic(char *str)
{
@@ -427,7 +463,7 @@
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRALN;
- info.si_addr = (void *)compute_effective_address(regs, insn);
+ info.si_addr = (void *)safe_compute_effective_address(regs, insn);
info.si_trapno = 0;
send_sig_info(SIGBUS, &info, current);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)