diff options
author | 2023-06-04 14:26:52 +0200 | |
---|---|---|
committer | 2023-06-09 09:54:17 +0200 | |
commit | 6673c2763f6f999fc32cff1833c7d4d6d35f787b (patch) | |
tree | 4aa5c4647d327aa6dbbba9be82080a78daca5118 /arch/mips/kernel | |
parent | Revert "MIPS: unhide PATA_PLATFORM" (diff) | |
download | linux-6673c2763f6f999fc32cff1833c7d4d6d35f787b.tar.gz linux-6673c2763f6f999fc32cff1833c7d4d6d35f787b.tar.bz2 linux-6673c2763f6f999fc32cff1833c7d4d6d35f787b.zip |
MIPS: uaccess: emulate Ingenic LXW/LXH/LXHU uaccess
The LXW, LXH, LXHU opcodes are part of the MXU ASE found in Ingenic
XBurst based SoCs.
While technically part of the MXU ASE, they do not touch any of the SIMD
registers, and can be used even when the MXU ASE is disabled.
This patch makes it possible to emulate unaligned access for those
instructions.
Signed-off-by: Siarhei Volkau <lis8215@gmail.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/unaligned.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 7b5aba5df02e..f4cf94e92ec3 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -160,6 +160,47 @@ static void emulate_load_store_insn(struct pt_regs *regs, * The remaining opcodes are the ones that are really of * interest. */ +#ifdef CONFIG_MACH_INGENIC + case spec2_op: + if (insn.mxu_lx_format.func != mxu_lx_op) + goto sigbus; /* other MXU instructions we don't care */ + + switch (insn.mxu_lx_format.op) { + case mxu_lxw_op: + if (user && !access_ok(addr, 4)) + goto sigbus; + LoadW(addr, value, res); + if (res) + goto fault; + compute_return_epc(regs); + regs->regs[insn.mxu_lx_format.rd] = value; + break; + case mxu_lxh_op: + if (user && !access_ok(addr, 2)) + goto sigbus; + LoadHW(addr, value, res); + if (res) + goto fault; + compute_return_epc(regs); + regs->regs[insn.dsp_format.rd] = value; + break; + case mxu_lxhu_op: + if (user && !access_ok(addr, 2)) + goto sigbus; + LoadHWU(addr, value, res); + if (res) + goto fault; + compute_return_epc(regs); + regs->regs[insn.dsp_format.rd] = value; + break; + case mxu_lxb_op: + case mxu_lxbu_op: + goto sigbus; + default: + goto sigill; + } + break; +#endif case spec3_op: if (insn.dsp_format.func == lx_op) { switch (insn.dsp_format.op) { |