aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2015-03-09 10:54:52 -0400
committerRalf Baechle <ralf@linux-mips.org>2015-04-10 09:41:45 -0400
commit6eae35485b26f9e51ab896eb8a936bed9908fdf6 (patch)
tree2b0d658ad890bdd012942abd736af3275dbfb72a
parent3563c32d6532ece53c9dd8905a8e41983ef9952f (diff)
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: Markos Chandras <markos.chandras@imgtec.com> Fixes: c1771216ab48 ("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: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/unaligned.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index ab475903175f..7659da224fcd 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -1023,7 +1023,15 @@ static void emulate_load_store_insn(struct pt_regs *regs,
1023 if (!access_ok(VERIFY_READ, addr, 2)) 1023 if (!access_ok(VERIFY_READ, addr, 2))
1024 goto sigbus; 1024 goto sigbus;
1025 1025
1026 LoadHW(addr, value, res); 1026 if (config_enabled(CONFIG_EVA)) {
1027 if (segment_eq(get_fs(), get_ds()))
1028 LoadHW(addr, value, res);
1029 else
1030 LoadHWE(addr, value, res);
1031 } else {
1032 LoadHW(addr, value, res);
1033 }
1034
1027 if (res) 1035 if (res)
1028 goto fault; 1036 goto fault;
1029 compute_return_epc(regs); 1037 compute_return_epc(regs);
@@ -1034,7 +1042,15 @@ static void emulate_load_store_insn(struct pt_regs *regs,
1034 if (!access_ok(VERIFY_READ, addr, 4)) 1042 if (!access_ok(VERIFY_READ, addr, 4))
1035 goto sigbus; 1043 goto sigbus;
1036 1044
1037 LoadW(addr, value, res); 1045 if (config_enabled(CONFIG_EVA)) {
1046 if (segment_eq(get_fs(), get_ds()))
1047 LoadW(addr, value, res);
1048 else
1049 LoadWE(addr, value, res);
1050 } else {
1051 LoadW(addr, value, res);
1052 }
1053
1038 if (res) 1054 if (res)
1039 goto fault; 1055 goto fault;
1040 compute_return_epc(regs); 1056 compute_return_epc(regs);
@@ -1045,7 +1061,15 @@ static void emulate_load_store_insn(struct pt_regs *regs,
1045 if (!access_ok(VERIFY_READ, addr, 2)) 1061 if (!access_ok(VERIFY_READ, addr, 2))
1046 goto sigbus; 1062 goto sigbus;
1047 1063
1048 LoadHWU(addr, value, res); 1064 if (config_enabled(CONFIG_EVA)) {
1065 if (segment_eq(get_fs(), get_ds()))
1066 LoadHWU(addr, value, res);
1067 else
1068 LoadHWUE(addr, value, res);
1069 } else {
1070 LoadHWU(addr, value, res);
1071 }
1072
1049 if (res) 1073 if (res)
1050 goto fault; 1074 goto fault;
1051 compute_return_epc(regs); 1075 compute_return_epc(regs);
@@ -1104,7 +1128,16 @@ static void emulate_load_store_insn(struct pt_regs *regs,
1104 1128
1105 compute_return_epc(regs); 1129 compute_return_epc(regs);
1106 value = regs->regs[insn.i_format.rt]; 1130 value = regs->regs[insn.i_format.rt];
1107 StoreHW(addr, value, res); 1131
1132 if (config_enabled(CONFIG_EVA)) {
1133 if (segment_eq(get_fs(), get_ds()))
1134 StoreHW(addr, value, res);
1135 else
1136 StoreHWE(addr, value, res);
1137 } else {
1138 StoreHW(addr, value, res);
1139 }
1140
1108 if (res) 1141 if (res)
1109 goto fault; 1142 goto fault;
1110 break; 1143 break;
@@ -1115,7 +1148,16 @@ static void emulate_load_store_insn(struct pt_regs *regs,
1115 1148
1116 compute_return_epc(regs); 1149 compute_return_epc(regs);
1117 value = regs->regs[insn.i_format.rt]; 1150 value = regs->regs[insn.i_format.rt];
1118 StoreW(addr, value, res); 1151
1152 if (config_enabled(CONFIG_EVA)) {
1153 if (segment_eq(get_fs(), get_ds()))
1154 StoreW(addr, value, res);
1155 else
1156 StoreWE(addr, value, res);
1157 } else {
1158 StoreW(addr, value, res);
1159 }
1160
1119 if (res) 1161 if (res)
1120 goto fault; 1162 goto fault;
1121 break; 1163 break;