|
@@ -1636,6 +1636,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
|
|
if (index < 0) {
|
|
if (index < 0) {
|
|
vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
|
|
vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
|
|
vcpu->arch.host_cp0_badvaddr = va;
|
|
vcpu->arch.host_cp0_badvaddr = va;
|
|
|
|
+ vcpu->arch.pc = curr_pc;
|
|
er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,
|
|
er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,
|
|
vcpu);
|
|
vcpu);
|
|
preempt_enable();
|
|
preempt_enable();
|
|
@@ -1647,6 +1648,8 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
|
|
* invalid exception to the guest
|
|
* invalid exception to the guest
|
|
*/
|
|
*/
|
|
if (!TLB_IS_VALID(*tlb, va)) {
|
|
if (!TLB_IS_VALID(*tlb, va)) {
|
|
|
|
+ vcpu->arch.host_cp0_badvaddr = va;
|
|
|
|
+ vcpu->arch.pc = curr_pc;
|
|
er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
|
|
er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
|
|
run, vcpu);
|
|
run, vcpu);
|
|
preempt_enable();
|
|
preempt_enable();
|
|
@@ -1666,7 +1669,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
|
|
cache, op, base, arch->gprs[base], offset);
|
|
cache, op, base, arch->gprs[base], offset);
|
|
er = EMULATE_FAIL;
|
|
er = EMULATE_FAIL;
|
|
preempt_enable();
|
|
preempt_enable();
|
|
- goto dont_update_pc;
|
|
|
|
|
|
+ goto done;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1694,16 +1697,20 @@ skip_fault:
|
|
kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
|
|
kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
|
|
cache, op, base, arch->gprs[base], offset);
|
|
cache, op, base, arch->gprs[base], offset);
|
|
er = EMULATE_FAIL;
|
|
er = EMULATE_FAIL;
|
|
- preempt_enable();
|
|
|
|
- goto dont_update_pc;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
preempt_enable();
|
|
preempt_enable();
|
|
|
|
+done:
|
|
|
|
+ /* Rollback PC only if emulation was unsuccessful */
|
|
|
|
+ if (er == EMULATE_FAIL)
|
|
|
|
+ vcpu->arch.pc = curr_pc;
|
|
|
|
|
|
dont_update_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;
|
|
return er;
|
|
}
|
|
}
|
|
|
|
|