^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Handle unaligned accesses by emulation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 1996, 1998, 1999, 2002 by Ralf Baechle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 1999 Silicon Graphics, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2014 Imagination Technologies Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This file contains exception handler for address error exception with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * special capability to execute faulting instructions in software. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * handler does not try to handle the case when the program counter points
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * to an address not aligned to a word boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Putting data to unaligned addresses is a bad practice even on Intel where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * only the performance is affected. Much worse is that such code is non-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * portable. Due to several programs that die on MIPS due to alignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * problems I decided to implement this handler anyway though I originally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * didn't intend to do this at all for user code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * For now I enable fixing of address errors by default to make life easier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * I however intend to disable this somewhen in the future when the alignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * problems with user programs have been fixed. For programmers this is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * right way to go.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Fixing address errors is a per process option. The option is inherited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * across fork(2) and execve(2) calls. If you really want to use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * option in your user programs - I discourage the use of the software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * emulation strongly - use the following code in your userland stuff:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * #include <sys/sysmips.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * sysmips(MIPS_FIXADE, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * The argument x is 0 for disabling software emulation, enabled otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Below a little program to play around with this feature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * #include <sys/sysmips.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * struct foo {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * unsigned char bar[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * main(int argc, char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * struct foo x = {0, 1, 2, 3, 4, 5, 6, 7};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * unsigned int *p = (unsigned int *) (x.bar + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * if (argc > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * sysmips(MIPS_FIXADE, atoi(argv[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * printf("*p = %08lx\n", *p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * *p = 0xdeadface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * for(i = 0; i <= 7; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * printf("%02x ", x.bar[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * Coprocessor loads are not supported; I think this case is unimportant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * in the practice.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * TODO: Handle ndc (attempted store to doubleword in uncached memory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * exception for the R6000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * A store crossing a page boundary might be executed only partially.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Undo the partial store in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #include <linux/context_tracking.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #include <asm/asm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #include <asm/branch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #include <asm/cop2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #include <asm/fpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #include <asm/fpu_emulator.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #include <asm/inst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #include <asm/unaligned-emul.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #include <asm/mmu_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) UNALIGNED_ACTION_QUIET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) UNALIGNED_ACTION_SIGNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) UNALIGNED_ACTION_SHOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static u32 unaligned_instructions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static u32 unaligned_action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define unaligned_action UNALIGNED_ACTION_QUIET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) extern void show_registers(struct pt_regs *regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static void emulate_load_store_insn(struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) void __user *addr, unsigned int __user *pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) unsigned long origpc, orig31, value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) union mips_instruction insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #ifdef CONFIG_EVA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) mm_segment_t seg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) origpc = (unsigned long)pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) orig31 = regs->regs[31];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * This load never faults.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) __get_user(insn.word, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) switch (insn.i_format.opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * These are instructions that a compiler doesn't generate. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * can assume therefore that the code is MIPS-aware and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * really buggy. Emulating these instructions would break the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * semantics anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) case ll_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case lld_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case sc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) case scd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * For these instructions the only way to create an address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * error is an attempted access to kernel/supervisor address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) case ldl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) case ldr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) case lwl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) case lwr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) case sdl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) case sdr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) case swl_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) case swr_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case lb_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) case lbu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) case sb_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * The remaining opcodes are the ones that are really of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * interest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case spec3_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (insn.dsp_format.func == lx_op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) switch (insn.dsp_format.op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) case lwx_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) regs->regs[insn.dsp_format.rd] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case lhx_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) LoadHW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) regs->regs[insn.dsp_format.rd] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #ifdef CONFIG_EVA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * we can land here only from kernel accessing user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * memory, so we need to "switch" the address limit to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * user space, so that address check can work properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) seg = force_uaccess_begin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) switch (insn.spec3_format.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) case lhe_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (!access_ok(addr, 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) LoadHWE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) regs->regs[insn.spec3_format.rt] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) case lwe_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (!access_ok(addr, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) LoadWE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) regs->regs[insn.spec3_format.rt] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) case lhue_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (!access_ok(addr, 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) LoadHWUE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) regs->regs[insn.spec3_format.rt] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) case she_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!access_ok(addr, 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) value = regs->regs[insn.spec3_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) StoreHWE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case swe_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!access_ok(addr, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) value = regs->regs[insn.spec3_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) StoreWE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) force_uaccess_end(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case lh_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (IS_ENABLED(CONFIG_EVA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (uaccess_kernel())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) LoadHW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) LoadHWE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) LoadHW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) regs->regs[insn.i_format.rt] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) case lw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (IS_ENABLED(CONFIG_EVA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (uaccess_kernel())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) LoadWE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) regs->regs[insn.i_format.rt] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case lhu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (IS_ENABLED(CONFIG_EVA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (uaccess_kernel())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) LoadHWU(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) LoadHWUE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) LoadHWU(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) regs->regs[insn.i_format.rt] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) case lwu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * A 32-bit kernel might be running on a 64-bit processor. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * if we're on a 32-bit processor and an i-cache incoherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * or race makes us see a 64-bit instruction here the sdl/sdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * would blow up, so for now we don't handle unaligned 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * instructions on 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) LoadWU(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) regs->regs[insn.i_format.rt] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* Cannot handle 64-bit instructions in 32-bit kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) case ld_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * A 32-bit kernel might be running on a 64-bit processor. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * if we're on a 32-bit processor and an i-cache incoherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * or race makes us see a 64-bit instruction here the sdl/sdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * would blow up, so for now we don't handle unaligned 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * instructions on 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!access_ok(addr, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) LoadDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) regs->regs[insn.i_format.rt] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /* Cannot handle 64-bit instructions in 32-bit kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case sh_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) value = regs->regs[insn.i_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (IS_ENABLED(CONFIG_EVA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (uaccess_kernel())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) StoreHW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) StoreHWE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) StoreHW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) case sw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) value = regs->regs[insn.i_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (IS_ENABLED(CONFIG_EVA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (uaccess_kernel())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) StoreWE(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) case sd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * A 32-bit kernel might be running on a 64-bit processor. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * if we're on a 32-bit processor and an i-cache incoherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * or race makes us see a 64-bit instruction here the sdl/sdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * would blow up, so for now we don't handle unaligned 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * instructions on 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (!access_ok(addr, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) value = regs->regs[insn.i_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) StoreDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* Cannot handle 64-bit instructions in 32-bit kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) #ifdef CONFIG_MIPS_FP_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case lwc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) case ldc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) case swc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) case sdc1_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) case cop1x_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) void __user *fault_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) die_if_kernel("Unaligned FP access in kernel code", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) BUG_ON(!used_math());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) &fault_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) own_fpu(1); /* Restore FPU state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* Signal if something went wrong. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) process_fpemu_return(res, fault_addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (res == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) #endif /* CONFIG_MIPS_FP_SUPPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) #ifdef CONFIG_CPU_HAS_MSA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) case msa_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) unsigned int wd, preempted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) enum msa_2b_fmt df;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) union fpureg *fpr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (!cpu_has_msa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * If we've reached this point then userland should have taken
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * the MSA disabled exception & initialised vector context at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * some point in the past.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) BUG_ON(!thread_msa_context_live());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) df = insn.msa_mi10_format.df;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) wd = insn.msa_mi10_format.wd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) fpr = ¤t->thread.fpu.fpr[wd];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) switch (insn.msa_mi10_format.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) case msa_ld_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (!access_ok(addr, sizeof(*fpr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * If we have live MSA context keep track of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * whether we get preempted in order to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * the register context we load being clobbered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * by the live context as it's saved during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * preemption. If we don't have live context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * then it can't be saved to clobber the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * we load.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) preempted = test_thread_flag(TIF_USEDMSA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) res = __copy_from_user_inatomic(fpr, addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) sizeof(*fpr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * Update the hardware register if it is in use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * by the task in this quantum, in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * avoid having to save & restore the whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * vector context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (test_thread_flag(TIF_USEDMSA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) write_msa_wr(wd, fpr, df);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) preempted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) } while (preempted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case msa_st_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (!access_ok(addr, sizeof(*fpr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * Update from the hardware register if it is in use by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * the task in this quantum, in order to avoid having to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * save & restore the whole vector context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (test_thread_flag(TIF_USEDMSA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) read_msa_wr(wd, fpr, df);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) res = __copy_to_user_inatomic(addr, fpr, sizeof(*fpr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) compute_return_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) #endif /* CONFIG_CPU_HAS_MSA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) #ifndef CONFIG_CPU_MIPSR6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * COP2 is available to implementor for application specific use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * It's up to applications to register a notifier chain and do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * whatever they have to do, including possible sending of signals.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * This instruction has been reallocated in Release 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) case lwc2_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) cu2_notifier_call_chain(CU2_LWC2_OP, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) case ldc2_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) cu2_notifier_call_chain(CU2_LDC2_OP, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) case swc2_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) cu2_notifier_call_chain(CU2_SWC2_OP, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) case sdc2_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) cu2_notifier_call_chain(CU2_SDC2_OP, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * Pheeee... We encountered an yet unknown instruction or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * cache coherence problem. Die sucker, die ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) unaligned_instructions++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) fault:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /* roll back jump/branch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) regs->cp0_epc = origpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) regs->regs[31] = orig31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* Did we have an exception handler installed? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (fixup_exception(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) die_if_kernel("Unhandled kernel unaligned access", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) force_sig(SIGSEGV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) sigbus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) die_if_kernel("Unhandled kernel unaligned access", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) force_sig(SIGBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) sigill:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) die_if_kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) ("Unhandled kernel unaligned access or invalid instruction", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) force_sig(SIGILL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /* Recode table from 16-bit register notation to 32-bit GPR. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) const int reg16to32[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* Recode table from 16-bit STORE register notation to 32-bit GPR. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) static const int reg16to32st[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) static void emulate_load_store_microMIPS(struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) void __user *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) unsigned int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) unsigned int reg = 0, rvar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) unsigned long orig31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) u16 __user *pc16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) u16 halfword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) unsigned int word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) unsigned long origpc, contpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) union mips_instruction insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) struct mm_decoded_insn mminsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) origpc = regs->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) orig31 = regs->regs[31];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) mminsn.micro_mips_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * This load never faults.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) pc16 = (unsigned short __user *)msk_isa16_mode(regs->cp0_epc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) __get_user(halfword, pc16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) pc16++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) contpc = regs->cp0_epc + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) word = ((unsigned int)halfword << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) mminsn.pc_inc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (!mm_insn_16bit(halfword)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) __get_user(halfword, pc16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) pc16++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) contpc = regs->cp0_epc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) mminsn.pc_inc = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) word |= halfword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) mminsn.insn = word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (get_user(halfword, pc16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) mminsn.next_pc_inc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) word = ((unsigned int)halfword << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (!mm_insn_16bit(halfword)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) pc16++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (get_user(halfword, pc16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) mminsn.next_pc_inc = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) word |= halfword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) mminsn.next_insn = word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) insn = (union mips_instruction)(mminsn.insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (mm_isBranchInstr(regs, mminsn, &contpc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) insn = (union mips_instruction)(mminsn.next_insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /* Parse instruction to find what to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) switch (insn.mm_i_format.opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) case mm_pool32a_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) switch (insn.mm_x_format.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) case mm_lwxs_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) reg = insn.mm_x_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) goto loadW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) case mm_pool32b_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) switch (insn.mm_m_format.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) case mm_lwp_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) reg = insn.mm_m_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (reg == 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (!access_ok(addr, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) regs->regs[reg + 1] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) case mm_swp_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) reg = insn.mm_m_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (reg == 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (!access_ok(addr, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) value = regs->regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) value = regs->regs[reg + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) case mm_ldp_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) reg = insn.mm_m_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (reg == 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (!access_ok(addr, 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) LoadDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) addr += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) LoadDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) regs->regs[reg + 1] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) case mm_sdp_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) reg = insn.mm_m_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (reg == 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (!access_ok(addr, 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) value = regs->regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) StoreDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) addr += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) value = regs->regs[reg + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) StoreDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) case mm_lwm32_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) reg = insn.mm_m_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) rvar = reg & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if ((rvar > 9) || !reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (reg & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (!access_ok(addr, 4 * (rvar + 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (!access_ok(addr, 4 * rvar))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (rvar == 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) rvar = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) for (i = 16; rvar; rvar--, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) regs->regs[i] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if ((reg & 0xf) == 9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) regs->regs[30] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (reg & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) regs->regs[31] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) case mm_swm32_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) reg = insn.mm_m_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) rvar = reg & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if ((rvar > 9) || !reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (reg & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (!access_ok(addr, 4 * (rvar + 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (!access_ok(addr, 4 * rvar))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (rvar == 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) rvar = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) for (i = 16; rvar; rvar--, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) value = regs->regs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if ((reg & 0xf) == 9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) value = regs->regs[30];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (reg & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) value = regs->regs[31];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) case mm_ldm_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) reg = insn.mm_m_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) rvar = reg & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if ((rvar > 9) || !reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (reg & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (!access_ok(addr, 8 * (rvar + 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (!access_ok(addr, 8 * rvar))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (rvar == 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) rvar = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) for (i = 16; rvar; rvar--, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) LoadDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) regs->regs[i] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if ((reg & 0xf) == 9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) LoadDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) addr += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) regs->regs[30] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (reg & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) LoadDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) regs->regs[31] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) case mm_sdm_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) reg = insn.mm_m_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) rvar = reg & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if ((rvar > 9) || !reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (reg & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (!access_ok(addr, 8 * (rvar + 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (!access_ok(addr, 8 * rvar))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) if (rvar == 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) rvar = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) for (i = 16; rvar; rvar--, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) value = regs->regs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) StoreDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) addr += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if ((reg & 0xf) == 9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) value = regs->regs[30];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) StoreDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) addr += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (reg & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) value = regs->regs[31];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) StoreDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) /* LWC2, SWC2, LDC2, SDC2 are not serviced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) case mm_pool32c_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) switch (insn.mm_m_format.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) case mm_lwu_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) reg = insn.mm_m_format.rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) goto loadWU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) /* LL,SC,LLD,SCD are not serviced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) #ifdef CONFIG_MIPS_FP_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case mm_pool32f_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) switch (insn.mm_x_format.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) case mm_lwxc1_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) case mm_swxc1_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) case mm_ldxc1_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) case mm_sdxc1_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) goto fpu_emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) case mm_ldc132_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) case mm_sdc132_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) case mm_lwc132_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) case mm_swc132_op: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) void __user *fault_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) fpu_emul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /* roll back jump/branch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) regs->cp0_epc = origpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) regs->regs[31] = orig31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) die_if_kernel("Unaligned FP access in kernel code", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) BUG_ON(!used_math());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) BUG_ON(!is_fpu_owner());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) &fault_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) own_fpu(1); /* restore FPU state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) /* If something went wrong, signal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) process_fpemu_return(res, fault_addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (res == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) #endif /* CONFIG_MIPS_FP_SUPPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) case mm_lh32_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) reg = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) goto loadHW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) case mm_lhu32_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) reg = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) goto loadHWU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) case mm_lw32_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) reg = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) goto loadW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) case mm_sh32_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) reg = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) goto storeHW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) case mm_sw32_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) reg = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) goto storeW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) case mm_ld32_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) reg = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) goto loadDW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) case mm_sd32_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) reg = insn.mm_i_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) goto storeDW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) case mm_pool16c_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) switch (insn.mm16_m_format.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) case mm_lwm16_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) reg = insn.mm16_m_format.rlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) rvar = reg + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (!access_ok(addr, 4 * rvar))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) for (i = 16; rvar; rvar--, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) regs->regs[i] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) regs->regs[31] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) case mm_swm16_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) reg = insn.mm16_m_format.rlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) rvar = reg + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if (!access_ok(addr, 4 * rvar))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) for (i = 16; rvar; rvar--, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) value = regs->regs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) addr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) value = regs->regs[31];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) case mm_lhu16_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) reg = reg16to32[insn.mm16_rb_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) goto loadHWU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) case mm_lw16_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) reg = reg16to32[insn.mm16_rb_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) goto loadW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) case mm_sh16_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) reg = reg16to32st[insn.mm16_rb_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) goto storeHW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) case mm_sw16_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) reg = reg16to32st[insn.mm16_rb_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) goto storeW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) case mm_lwsp16_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) reg = insn.mm16_r5_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) goto loadW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) case mm_swsp16_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) reg = insn.mm16_r5_format.rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) goto storeW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) case mm_lwgp16_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) reg = reg16to32[insn.mm16_r3_format.rt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) goto loadW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) loadHW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) LoadHW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) loadHWU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) LoadHWU(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) loadW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) loadWU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * A 32-bit kernel might be running on a 64-bit processor. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * if we're on a 32-bit processor and an i-cache incoherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) * or race makes us see a 64-bit instruction here the sdl/sdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) * would blow up, so for now we don't handle unaligned 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * instructions on 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) LoadWU(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) /* Cannot handle 64-bit instructions in 32-bit kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) loadDW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) * A 32-bit kernel might be running on a 64-bit processor. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) * if we're on a 32-bit processor and an i-cache incoherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * or race makes us see a 64-bit instruction here the sdl/sdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) * would blow up, so for now we don't handle unaligned 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * instructions on 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (!access_ok(addr, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) LoadDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) /* Cannot handle 64-bit instructions in 32-bit kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) storeHW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) value = regs->regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) StoreHW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) storeW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) value = regs->regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) storeDW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) * A 32-bit kernel might be running on a 64-bit processor. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) * if we're on a 32-bit processor and an i-cache incoherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) * or race makes us see a 64-bit instruction here the sdl/sdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) * would blow up, so for now we don't handle unaligned 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * instructions on 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (!access_ok(addr, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) value = regs->regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) StoreDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) goto success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* Cannot handle 64-bit instructions in 32-bit kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) success:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) regs->cp0_epc = contpc; /* advance or branch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) unaligned_instructions++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) fault:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /* roll back jump/branch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) regs->cp0_epc = origpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) regs->regs[31] = orig31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) /* Did we have an exception handler installed? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (fixup_exception(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) die_if_kernel("Unhandled kernel unaligned access", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) force_sig(SIGSEGV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) sigbus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) die_if_kernel("Unhandled kernel unaligned access", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) force_sig(SIGBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) sigill:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) die_if_kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) ("Unhandled kernel unaligned access or invalid instruction", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) force_sig(SIGILL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) unsigned int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) unsigned long orig31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) u16 __user *pc16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) unsigned long origpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) union mips16e_instruction mips16inst, oldinst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) unsigned int opcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) int extended = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) origpc = regs->cp0_epc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) orig31 = regs->regs[31];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) pc16 = (unsigned short __user *)msk_isa16_mode(origpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) * This load never faults.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) __get_user(mips16inst.full, pc16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) oldinst = mips16inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /* skip EXTEND instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (mips16inst.ri.opcode == MIPS16e_extend_op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) extended = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) pc16++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) __get_user(mips16inst.full, pc16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) } else if (delay_slot(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) /* skip jump instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) /* JAL/JALX are 32 bits but have OPCODE in first short int */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (mips16inst.ri.opcode == MIPS16e_jal_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) pc16++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) pc16++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (get_user(mips16inst.full, pc16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) opcode = mips16inst.ri.opcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) case MIPS16e_i64_op: /* I64 or RI64 instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) switch (mips16inst.i64.func) { /* I64/RI64 func field check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) case MIPS16e_ldpc_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) case MIPS16e_ldsp_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) reg = reg16to32[mips16inst.ri64.ry];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) goto loadDW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) case MIPS16e_sdsp_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) reg = reg16to32[mips16inst.ri64.ry];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) goto writeDW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) case MIPS16e_sdrasp_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) reg = 29; /* GPRSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) goto writeDW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) case MIPS16e_swsp_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) reg = reg16to32[mips16inst.ri.rx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (extended && cpu_has_mips16e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) switch (mips16inst.ri.imm >> 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) case 0: /* SWSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) case 1: /* SWGP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) case 2: /* SHGP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) opcode = MIPS16e_sh_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) case MIPS16e_lwpc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) reg = reg16to32[mips16inst.ri.rx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) case MIPS16e_lwsp_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) reg = reg16to32[mips16inst.ri.rx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (extended && cpu_has_mips16e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) switch (mips16inst.ri.imm >> 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) case 0: /* LWSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) case 1: /* LWGP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) case 2: /* LHGP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) opcode = MIPS16e_lh_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) case 4: /* LHUGP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) opcode = MIPS16e_lhu_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) case MIPS16e_i8_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) if (mips16inst.i8.func != MIPS16e_swrasp_func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) reg = 29; /* GPRSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) reg = reg16to32[mips16inst.rri.ry];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) case MIPS16e_lb_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) case MIPS16e_lbu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) case MIPS16e_sb_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) case MIPS16e_lh_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) LoadHW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) MIPS16e_compute_return_epc(regs, &oldinst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) case MIPS16e_lhu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) LoadHWU(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) MIPS16e_compute_return_epc(regs, &oldinst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) case MIPS16e_lw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) case MIPS16e_lwpc_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) case MIPS16e_lwsp_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) LoadW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) MIPS16e_compute_return_epc(regs, &oldinst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) case MIPS16e_lwu_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) * A 32-bit kernel might be running on a 64-bit processor. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) * if we're on a 32-bit processor and an i-cache incoherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) * or race makes us see a 64-bit instruction here the sdl/sdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * would blow up, so for now we don't handle unaligned 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) * instructions on 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) LoadWU(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) MIPS16e_compute_return_epc(regs, &oldinst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) /* Cannot handle 64-bit instructions in 32-bit kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) case MIPS16e_ld_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) loadDW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) * A 32-bit kernel might be running on a 64-bit processor. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) * if we're on a 32-bit processor and an i-cache incoherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) * or race makes us see a 64-bit instruction here the sdl/sdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) * would blow up, so for now we don't handle unaligned 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) * instructions on 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) if (!access_ok(addr, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) LoadDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) MIPS16e_compute_return_epc(regs, &oldinst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) regs->regs[reg] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) /* Cannot handle 64-bit instructions in 32-bit kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) case MIPS16e_sh_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) if (!access_ok(addr, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) MIPS16e_compute_return_epc(regs, &oldinst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) value = regs->regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) StoreHW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) case MIPS16e_sw_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) case MIPS16e_swsp_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) case MIPS16e_i8_op: /* actually - MIPS16e_swrasp_func */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (!access_ok(addr, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) MIPS16e_compute_return_epc(regs, &oldinst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) value = regs->regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) StoreW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) case MIPS16e_sd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) writeDW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) * A 32-bit kernel might be running on a 64-bit processor. But
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) * if we're on a 32-bit processor and an i-cache incoherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) * or race makes us see a 64-bit instruction here the sdl/sdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) * would blow up, so for now we don't handle unaligned 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) * instructions on 32-bit kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (!access_ok(addr, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) MIPS16e_compute_return_epc(regs, &oldinst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) value = regs->regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) StoreDW(addr, value, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) /* Cannot handle 64-bit instructions in 32-bit kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) * Pheeee... We encountered an yet unknown instruction or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) * cache coherence problem. Die sucker, die ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) goto sigill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) unaligned_instructions++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) fault:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) /* roll back jump/branch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) regs->cp0_epc = origpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) regs->regs[31] = orig31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) /* Did we have an exception handler installed? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) if (fixup_exception(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) die_if_kernel("Unhandled kernel unaligned access", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) force_sig(SIGSEGV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) sigbus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) die_if_kernel("Unhandled kernel unaligned access", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) force_sig(SIGBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) sigill:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) die_if_kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) ("Unhandled kernel unaligned access or invalid instruction", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) force_sig(SIGILL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) asmlinkage void do_ade(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) enum ctx_state prev_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) unsigned int __user *pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) mm_segment_t seg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) prev_state = exception_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 1, regs, regs->cp0_badvaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) * Did we catch a fault trying to load an instruction?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) if (regs->cp0_badvaddr == regs->cp0_epc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (user_mode(regs) && !test_thread_flag(TIF_FIXADE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) if (unaligned_action == UNALIGNED_ACTION_SIGNAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) * Do branch emulation only if we didn't forward the exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) * This is all so but ugly ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) * Are we running in microMIPS mode?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) if (get_isa16_mode(regs->cp0_epc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) * Did we catch a fault trying to load an instruction in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) * 16-bit mode?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) if (regs->cp0_badvaddr == msk_isa16_mode(regs->cp0_epc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) if (unaligned_action == UNALIGNED_ACTION_SHOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) show_registers(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) if (cpu_has_mmips) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) seg = get_fs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) if (!user_mode(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) set_fs(KERNEL_DS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) emulate_load_store_microMIPS(regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) (void __user *)regs->cp0_badvaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) set_fs(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (cpu_has_mips16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) seg = get_fs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (!user_mode(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) set_fs(KERNEL_DS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) emulate_load_store_MIPS16e(regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) (void __user *)regs->cp0_badvaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) set_fs(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) goto sigbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) if (unaligned_action == UNALIGNED_ACTION_SHOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) show_registers(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) pc = (unsigned int __user *)exception_epc(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) seg = get_fs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) if (!user_mode(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) set_fs(KERNEL_DS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) set_fs(seg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) sigbus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) die_if_kernel("Kernel unaligned instruction access", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) force_sig(SIGBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) * XXX On return from the signal handler we should advance the epc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) exception_exit(prev_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) static int __init debugfs_unaligned(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) debugfs_create_u32("unaligned_instructions", S_IRUGO, mips_debugfs_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) &unaligned_instructions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) mips_debugfs_dir, &unaligned_action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) arch_initcall(debugfs_unaligned);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) #endif