Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f88ec63 authored by Miodrag Dinic's avatar Miodrag Dinic Committed by Ralf Baechle
Browse files

MIPS: unaligned: Add DSP lwx & lhx missaligned access support



Add handling of missaligned access for DSP load instructions
lwx & lhx.

Since DSP instructions share SPECIAL3 opcode with other non-DSP
instructions, necessary logic was inserted for distinguishing
between instructions with SPECIAL3 opcode. For that purpose,
the instruction format for DSP instructions is added to
arch/mips/include/uapi/asm/inst.h.

Signed-off-by: default avatarMiodrag Dinic <miodrag.dinic@imgtec.com>
Signed-off-by: default avatarAleksandar Markovic <aleksandar.markovic@imgtech.com>
Cc: James.Hogan@imgtec.com
Cc: Paul.Burton@imgtec.com
Cc: Raghu.Gandham@imgtec.com
Cc: Leonid.Yegoshin@imgtec.com
Cc: Douglas.Leung@imgtec.com
Cc: Petar.Jovanovic@imgtec.com
Cc: Goran.Ferenc@imgtec.com
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/16511/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 3daf281f
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -762,6 +762,16 @@ struct msa_mi10_format { /* MSA MI10 */
	;))))))
};

struct dsp_format {		/* SPEC3 DSP format instructions */
	__BITFIELD_FIELD(unsigned int opcode : 6,
	__BITFIELD_FIELD(unsigned int base : 5,
	__BITFIELD_FIELD(unsigned int index : 5,
	__BITFIELD_FIELD(unsigned int rd : 5,
	__BITFIELD_FIELD(unsigned int op : 5,
	__BITFIELD_FIELD(unsigned int func : 6,
	;))))))
};

struct spec3_format {   /* SPEC3 */
	__BITFIELD_FIELD(unsigned int opcode:6,
	__BITFIELD_FIELD(unsigned int rs:5,
@@ -1053,6 +1063,7 @@ union mips_instruction {
	struct b_format b_format;
	struct ps_format ps_format;
	struct v_format v_format;
	struct dsp_format dsp_format;
	struct spec3_format spec3_format;
	struct fb_format fb_format;
	struct fp0_format fp0_format;
+100 −74
Original line number Diff line number Diff line
@@ -939,12 +939,37 @@ static void emulate_load_store_insn(struct pt_regs *regs,
		 * The remaining opcodes are the ones that are really of
		 * interest.
		 */
#ifdef CONFIG_EVA
	case spec3_op:
		if (insn.dsp_format.func == lx_op) {
			switch (insn.dsp_format.op) {
			case lwx_op:
				if (!access_ok(VERIFY_READ, addr, 4))
					goto sigbus;
				LoadW(addr, value, res);
				if (res)
					goto fault;
				compute_return_epc(regs);
				regs->regs[insn.dsp_format.rd] = value;
				break;
			case lhx_op:
				if (!access_ok(VERIFY_READ, addr, 2))
					goto sigbus;
				LoadHW(addr, value, res);
				if (res)
					goto fault;
				compute_return_epc(regs);
				regs->regs[insn.dsp_format.rd] = value;
				break;
			default:
				goto sigill;
			}
		}
#ifdef CONFIG_EVA
		else {
			/*
		 * we can land here only from kernel accessing user memory,
		 * so we need to "switch" the address limit to user space, so
		 * address check can work properly.
			 * we can land here only from kernel accessing user
			 * memory, so we need to "switch" the address limit to
			 * user space, so that address check can work properly.
			 */
			seg = get_fs();
			set_fs(USER_DS);
@@ -1019,8 +1044,9 @@ static void emulate_load_store_insn(struct pt_regs *regs,
				goto sigill;
			}
			set_fs(seg);
		break;
		}
#endif
		break;
	case lh_op:
		if (!access_ok(VERIFY_READ, addr, 2))
			goto sigbus;