|
@@ -1666,7 +1666,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
|
|
|
cache, op, base, arch->gprs[base], offset);
|
|
|
er = EMULATE_FAIL;
|
|
|
preempt_enable();
|
|
|
- goto dont_update_pc;
|
|
|
+ goto done;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1694,16 +1694,20 @@ skip_fault:
|
|
|
kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
|
|
|
cache, op, base, arch->gprs[base], offset);
|
|
|
er = EMULATE_FAIL;
|
|
|
- preempt_enable();
|
|
|
- goto dont_update_pc;
|
|
|
}
|
|
|
|
|
|
preempt_enable();
|
|
|
+done:
|
|
|
+ /* Rollback PC only if emulation was unsuccessful */
|
|
|
+ if (er == EMULATE_FAIL)
|
|
|
+ vcpu->arch.pc = curr_pc;
|
|
|
|
|
|
dont_update_pc:
|
|
|
- /* Rollback PC */
|
|
|
- vcpu->arch.pc = curr_pc;
|
|
|
-done:
|
|
|
+ /*
|
|
|
+ * This is for exceptions whose emulation updates the PC, so do not
|
|
|
+ * overwrite the PC under any circumstances
|
|
|
+ */
|
|
|
+
|
|
|
return er;
|
|
|
}
|
|
|
|