aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/unaligned.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/unaligned.c')
-rw-r--r--arch/mips/kernel/unaligned.c51
1 files changed, 30 insertions, 21 deletions
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 490cea569d57..5c62065cbf22 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -885,7 +885,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
885{ 885{
886 union mips_instruction insn; 886 union mips_instruction insn;
887 unsigned long value; 887 unsigned long value;
888 unsigned int res; 888 unsigned int res, preempted;
889 unsigned long origpc; 889 unsigned long origpc;
890 unsigned long orig31; 890 unsigned long orig31;
891 void __user *fault_addr = NULL; 891 void __user *fault_addr = NULL;
@@ -1226,27 +1226,36 @@ static void emulate_load_store_insn(struct pt_regs *regs,
1226 if (!access_ok(VERIFY_READ, addr, sizeof(*fpr))) 1226 if (!access_ok(VERIFY_READ, addr, sizeof(*fpr)))
1227 goto sigbus; 1227 goto sigbus;
1228 1228
1229 /* 1229 do {
1230 * Disable preemption to avoid a race between copying 1230 /*
1231 * state from userland, migrating to another CPU and 1231 * If we have live MSA context keep track of
1232 * updating the hardware vector register below. 1232 * whether we get preempted in order to avoid
1233 */ 1233 * the register context we load being clobbered
1234 preempt_disable(); 1234 * by the live context as it's saved during
1235 1235 * preemption. If we don't have live context
1236 res = __copy_from_user_inatomic(fpr, addr, 1236 * then it can't be saved to clobber the value
1237 sizeof(*fpr)); 1237 * we load.
1238 if (res) 1238 */
1239 goto fault; 1239 preempted = test_thread_flag(TIF_USEDMSA);
1240 1240
1241 /* 1241 res = __copy_from_user_inatomic(fpr, addr,
1242 * Update the hardware register if it is in use by the 1242 sizeof(*fpr));
1243 * task in this quantum, in order to avoid having to 1243 if (res)
1244 * save & restore the whole vector context. 1244 goto fault;
1245 */
1246 if (test_thread_flag(TIF_USEDMSA))
1247 write_msa_wr(wd, fpr, df);
1248 1245
1249 preempt_enable(); 1246 /*
1247 * Update the hardware register if it is in use
1248 * by the task in this quantum, in order to
1249 * avoid having to save & restore the whole
1250 * vector context.
1251 */
1252 preempt_disable();
1253 if (test_thread_flag(TIF_USEDMSA)) {
1254 write_msa_wr(wd, fpr, df);
1255 preempted = 0;
1256 }
1257 preempt_enable();
1258 } while (preempted);
1250 break; 1259 break;
1251 1260
1252 case msa_st_op: 1261 case msa_st_op: