1 #include <asm/branch.h>
2 #include <asm/cacheflush.h>
3 #include <asm/fpu_emulator.h>
5 #include <asm/mipsregs.h>
6 #include <asm/uaccess.h>
11 * Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when
12 * we have to emulate the instruction in a COP1 branch delay slot. Do
13 * not change cp0_epc due to the instruction
15 * According to the spec:
16 * 1) it shouldn't be a branch :-)
17 * 2) it can be a COP instruction :-(
18 * 3) if we are tring to run a protected memory space we must take
19 * special care on memory access instructions :-(
23 * "Trampoline" return routine to catch exception following
24 * execution of delay-slot instruction execution.
28 mips_instruction emul
;
29 mips_instruction badinst
;
30 mips_instruction cookie
;
35 * Set up an emulation frame for instruction IR, from a delay slot of
36 * a branch jumping to CPC. Return 0 if successful, -1 if no emulation
37 * required, otherwise a signal number causing a frame setup failure.
39 int mips_dsemul(struct pt_regs
*regs
, mips_instruction ir
, unsigned long cpc
)
41 int isa16
= get_isa16_mode(regs
->cp0_epc
);
42 mips_instruction break_math
;
43 struct emuframe __user
*fr
;
50 /* microMIPS instructions */
52 union mips_instruction insn
= { .word
= ir
};
54 /* NOP16 aka MOVE16 $0, $0 */
55 if ((ir
>> 16) == MM_NOP16
)
59 if (insn
.mm_a_format
.opcode
== mm_addiupc_op
) {
63 rs
= (((insn
.mm_a_format
.rs
+ 0x1e) & 0xf) + 2);
64 v
= regs
->cp0_epc
& ~3;
65 v
+= insn
.mm_a_format
.simmediate
<< 2;
66 regs
->regs
[rs
] = (long)v
;
71 pr_debug("dsemul %lx %lx\n", regs
->cp0_epc
, cpc
);
74 * The strategy is to push the instruction onto the user stack
75 * and put a trap after it which we can catch and jump to
76 * the required address any alternative apart from full
77 * instruction emulation!!.
79 * Algorithmics used a system call instruction, and
80 * borrowed that vector. MIPS/Linux version is a bit
81 * more heavyweight in the interests of portability and
82 * multiprocessor support. For Linux we use a BREAK 514
83 * instruction causing a breakpoint exception.
85 break_math
= BREAK_MATH(isa16
);
87 /* Ensure that the two instructions are in the same cache line */
88 fr
= (struct emuframe __user
*)
89 ((regs
->regs
[29] - sizeof(struct emuframe
)) & ~0x7);
91 /* Verify that the stack pointer is not competely insane */
92 if (unlikely(!access_ok(VERIFY_WRITE
, fr
, sizeof(struct emuframe
))))
96 err
= __put_user(ir
>> 16,
97 (u16 __user
*)(&fr
->emul
));
98 err
|= __put_user(ir
& 0xffff,
99 (u16 __user
*)((long)(&fr
->emul
) + 2));
100 err
|= __put_user(break_math
>> 16,
101 (u16 __user
*)(&fr
->badinst
));
102 err
|= __put_user(break_math
& 0xffff,
103 (u16 __user
*)((long)(&fr
->badinst
) + 2));
105 err
= __put_user(ir
, &fr
->emul
);
106 err
|= __put_user(break_math
, &fr
->badinst
);
109 err
|= __put_user((mips_instruction
)BD_COOKIE
, &fr
->cookie
);
110 err
|= __put_user(cpc
, &fr
->epc
);
113 MIPS_FPU_EMU_INC_STATS(errors
);
117 regs
->cp0_epc
= (unsigned long)&fr
->emul
| isa16
;
119 flush_cache_sigtramp((unsigned long)&fr
->emul
);
124 int do_dsemulret(struct pt_regs
*xcp
)
126 int isa16
= get_isa16_mode(xcp
->cp0_epc
);
127 struct emuframe __user
*fr
;
133 fr
= (struct emuframe __user
*)
134 (msk_isa16_mode(xcp
->cp0_epc
) - sizeof(mips_instruction
));
137 * If we can't even access the area, something is very wrong, but we'll
138 * leave that to the default handling
140 if (!access_ok(VERIFY_READ
, fr
, sizeof(struct emuframe
)))
144 * Do some sanity checking on the stackframe:
146 * - Is the instruction pointed to by the EPC an BREAK_MATH?
147 * - Is the following memory word the BD_COOKIE?
150 err
= __get_user(instr
[0],
151 (u16 __user
*)(&fr
->badinst
));
152 err
|= __get_user(instr
[1],
153 (u16 __user
*)((long)(&fr
->badinst
) + 2));
154 insn
= (instr
[0] << 16) | instr
[1];
156 err
= __get_user(insn
, &fr
->badinst
);
158 err
|= __get_user(cookie
, &fr
->cookie
);
161 insn
!= BREAK_MATH(isa16
) || cookie
!= BD_COOKIE
)) {
162 MIPS_FPU_EMU_INC_STATS(errors
);
167 * At this point, we are satisfied that it's a BD emulation trap. Yes,
168 * a user might have deliberately put two malformed and useless
169 * instructions in a row in his program, in which case he's in for a
170 * nasty surprise - the next instruction will be treated as a
171 * continuation address! Alas, this seems to be the only way that we
172 * can handle signals, recursion, and longjmps() in the context of
173 * emulating the branch delay instruction.
176 pr_debug("dsemulret\n");
178 if (__get_user(epc
, &fr
->epc
)) { /* Saved EPC */
179 /* This is not a good situation to be in */
180 force_sig(SIGBUS
, current
);
185 /* Set EPC to return to post-branch instruction */
187 MIPS_FPU_EMU_INC_STATS(ds_emul
);