patch-2.1.52 linux/arch/alpha/kernel/traps.c
Next file: linux/arch/i386/config.in
Previous file: linux/arch/alpha/kernel/entry.S
Back to the patch index
Back to the overall index
- Lines: 138
- Date:
Sat Aug 30 11:37:17 1997
- Orig file:
v2.1.51/linux/arch/alpha/kernel/traps.c
- Orig date:
Thu Jul 17 10:06:03 1997
diff -u --recursive --new-file v2.1.51/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
@@ -491,8 +491,22 @@
| 1L << 0x2c | 1L << 0x2d /* stl stq */ \
| 1L << 0xd ) /* stw */
+#define R(x) ((size_t) &((struct pt_regs *)0)->x)
+
+static int unauser_reg_offsets[32] = {
+ R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8),
+ /* r9 ... r15 are stored in front of regs. */
+ -56, -48, -40, -32, -24, -16, -8,
+ R(r16), R(r17), R(r18),
+ R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26),
+ R(r27), R(r28), R(gp),
+ 0, 0
+};
+
+#undef R
+
asmlinkage void do_entUnaUser(void * va, unsigned long opcode,
- unsigned long reg, unsigned long * frame)
+ unsigned long reg, struct pt_regs *regs)
{
extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
extern unsigned long alpha_read_fp_reg (unsigned long reg);
@@ -501,12 +515,10 @@
static long last_time = 0;
unsigned long tmp1, tmp2, tmp3, tmp4;
- unsigned long *reg_addr, *pc_addr, fake_reg;
+ unsigned long fake_reg, *reg_addr = &fake_reg;
unsigned long uac_bits;
long error;
- pc_addr = frame + 7 + 20 + 1; /* pc in PAL frame */
-
/* Check the UAC bits to decide what the user wants us to do
with the unaliged access. */
@@ -519,7 +531,7 @@
lock_kernel();
printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
current->comm, current->pid,
- *pc_addr - 4, va, opcode, reg);
+ regs->pc - 4, va, opcode, reg);
unlock_kernel();
}
last_time = jiffies;
@@ -540,51 +552,19 @@
++unaligned[1].count;
unaligned[1].va = (unsigned long)va;
- unaligned[1].pc = *pc_addr - 4;
+ unaligned[1].pc = regs->pc - 4;
- reg_addr = frame;
if ((1L << opcode) & OP_INT_MASK) {
/* it's an integer load/store */
- switch (reg) {
- case 0: case 1: case 2: case 3: case 4:
- case 5: case 6: case 7: case 8:
- /* v0-t7 in SAVE_ALL frame */
- reg_addr += 7 + reg;
- break;
-
- case 9: case 10: case 11: case 12:
- case 13: case 14: case 15:
- /* s0-s6 in entUna frame */
- reg_addr += (reg - 9);
- break;
-
- case 16: case 17: case 18:
- /* a0-a2 in PAL frame */
- reg_addr += 7 + 20 + 3 + (reg - 16);
- break;
-
- case 19: case 20: case 21: case 22: case 23:
- case 24: case 25: case 26: case 27: case 28:
- /* a3-at in SAVE_ALL frame */
- reg_addr += 7 + 9 + (reg - 19);
- break;
-
- case 29:
- /* gp in PAL frame */
- reg_addr += 7 + 20 + 2;
- break;
-
- case 30:
+ if (reg < 30) {
+ reg_addr = (unsigned long *)
+ ((char *)regs + unauser_reg_offsets[reg]);
+ } else if (reg == 30) {
/* usp in PAL regs */
fake_reg = rdusp();
- reg_addr = &fake_reg;
- break;
-
- case 31:
+ } else {
/* zero "register" */
fake_reg = 0;
- reg_addr = &fake_reg;
- break;
}
}
@@ -728,7 +708,6 @@
case 0x26: /* sts */
fake_reg = s_reg_to_mem(alpha_read_fp_reg(reg));
- reg_addr = &fake_reg;
/* FALLTHRU */
case 0x2c: /* stl */
@@ -763,7 +742,6 @@
case 0x27: /* stt */
fake_reg = alpha_read_fp_reg(reg);
- reg_addr = &fake_reg;
/* FALLTHRU */
case 0x2d: /* stq */
@@ -807,14 +785,14 @@
return;
give_sigsegv:
- *pc_addr -= 4; /* make pc point to faulting insn */
+ regs->pc -= 4; /* make pc point to faulting insn */
lock_kernel();
force_sig(SIGSEGV, current);
unlock_kernel();
return;
give_sigbus:
- *pc_addr -= 4;
+ regs->pc -= 4;
lock_kernel();
force_sig(SIGBUS, current);
unlock_kernel();
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov