Commit 6eae3548 authored by Markos Chandras's avatar Markos Chandras Committed by Ralf Baechle
Browse files

MIPS: unaligned: Fix regular load/store instruction emulation for EVA



When emulating a regular lh/lw/lhu/sh/sw we need to use the appropriate
instruction if we are in EVA mode. This is necessary for userspace
applications which trigger alignment exceptions. In such case, the
userspace load/store instruction needs to be emulated with the correct
eva/non-eva instruction by the kernel emulator.

Signed-off-by: default avatarMarkos Chandras <markos.chandras@imgtec.com>
Fixes: c1771216 ("MIPS: kernel: unaligned: Handle unaligned accesses for EVA")
Cc: <stable@vger.kernel.org> # v3.15+
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9503/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 3563c32d
Loading
Loading
Loading
Loading
+47 −5
Original line number Diff line number Diff line
@@ -1023,7 +1023,15 @@ static void emulate_load_store_insn(struct pt_regs *regs,
		if (!access_ok(VERIFY_READ, addr, 2))
			goto sigbus;

		if (config_enabled(CONFIG_EVA)) {
			if (segment_eq(get_fs(), get_ds()))
				LoadHW(addr, value, res);
			else
				LoadHWE(addr, value, res);
		} else {
			LoadHW(addr, value, res);
		}

		if (res)
			goto fault;
		compute_return_epc(regs);
@@ -1034,7 +1042,15 @@ static void emulate_load_store_insn(struct pt_regs *regs,
		if (!access_ok(VERIFY_READ, addr, 4))
			goto sigbus;

		if (config_enabled(CONFIG_EVA)) {
			if (segment_eq(get_fs(), get_ds()))
				LoadW(addr, value, res);
			else
				LoadWE(addr, value, res);
		} else {
			LoadW(addr, value, res);
		}

		if (res)
			goto fault;
		compute_return_epc(regs);
@@ -1045,7 +1061,15 @@ static void emulate_load_store_insn(struct pt_regs *regs,
		if (!access_ok(VERIFY_READ, addr, 2))
			goto sigbus;

		if (config_enabled(CONFIG_EVA)) {
			if (segment_eq(get_fs(), get_ds()))
				LoadHWU(addr, value, res);
			else
				LoadHWUE(addr, value, res);
		} else {
			LoadHWU(addr, value, res);
		}

		if (res)
			goto fault;
		compute_return_epc(regs);
@@ -1104,7 +1128,16 @@ static void emulate_load_store_insn(struct pt_regs *regs,

		compute_return_epc(regs);
		value = regs->regs[insn.i_format.rt];

		if (config_enabled(CONFIG_EVA)) {
			if (segment_eq(get_fs(), get_ds()))
				StoreHW(addr, value, res);
			else
				StoreHWE(addr, value, res);
		} else {
			StoreHW(addr, value, res);
		}

		if (res)
			goto fault;
		break;
@@ -1115,7 +1148,16 @@ static void emulate_load_store_insn(struct pt_regs *regs,

		compute_return_epc(regs);
		value = regs->regs[insn.i_format.rt];

		if (config_enabled(CONFIG_EVA)) {
			if (segment_eq(get_fs(), get_ds()))
				StoreW(addr, value, res);
			else
				StoreWE(addr, value, res);
		} else {
			StoreW(addr, value, res);
		}

		if (res)
			goto fault;
		break;