aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm/emulate.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kvm/emulate.c')
-rw-r--r--arch/mips/kvm/emulate.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 8770f32c9e0b..aa0937423e28 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -790,15 +790,15 @@ enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu)
790 struct mips_coproc *cop0 = vcpu->arch.cop0; 790 struct mips_coproc *cop0 = vcpu->arch.cop0;
791 enum emulation_result er = EMULATE_DONE; 791 enum emulation_result er = EMULATE_DONE;
792 792
793 if (kvm_read_c0_guest_status(cop0) & ST0_EXL) { 793 if (kvm_read_c0_guest_status(cop0) & ST0_ERL) {
794 kvm_clear_c0_guest_status(cop0, ST0_ERL);
795 vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
796 } else if (kvm_read_c0_guest_status(cop0) & ST0_EXL) {
794 kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc, 797 kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc,
795 kvm_read_c0_guest_epc(cop0)); 798 kvm_read_c0_guest_epc(cop0));
796 kvm_clear_c0_guest_status(cop0, ST0_EXL); 799 kvm_clear_c0_guest_status(cop0, ST0_EXL);
797 vcpu->arch.pc = kvm_read_c0_guest_epc(cop0); 800 vcpu->arch.pc = kvm_read_c0_guest_epc(cop0);
798 801
799 } else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) {
800 kvm_clear_c0_guest_status(cop0, ST0_ERL);
801 vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
802 } else { 802 } else {
803 kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n", 803 kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n",
804 vcpu->arch.pc); 804 vcpu->arch.pc);
@@ -1528,13 +1528,25 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst,
1528 struct kvm_vcpu *vcpu) 1528 struct kvm_vcpu *vcpu)
1529{ 1529{
1530 enum emulation_result er = EMULATE_DO_MMIO; 1530 enum emulation_result er = EMULATE_DO_MMIO;
1531 unsigned long curr_pc;
1531 u32 op, rt; 1532 u32 op, rt;
1532 u32 bytes; 1533 u32 bytes;
1533 1534
1534 rt = inst.i_format.rt; 1535 rt = inst.i_format.rt;
1535 op = inst.i_format.opcode; 1536 op = inst.i_format.opcode;
1536 1537
1537 vcpu->arch.pending_load_cause = cause; 1538 /*
1539 * Find the resume PC now while we have safe and easy access to the
1540 * prior branch instruction, and save it for
1541 * kvm_mips_complete_mmio_load() to restore later.
1542 */
1543 curr_pc = vcpu->arch.pc;
1544 er = update_pc(vcpu, cause);
1545 if (er == EMULATE_FAIL)
1546 return er;
1547 vcpu->arch.io_pc = vcpu->arch.pc;
1548 vcpu->arch.pc = curr_pc;
1549
1538 vcpu->arch.io_gpr = rt; 1550 vcpu->arch.io_gpr = rt;
1539 1551
1540 switch (op) { 1552 switch (op) {
@@ -2494,9 +2506,8 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
2494 goto done; 2506 goto done;
2495 } 2507 }
2496 2508
2497 er = update_pc(vcpu, vcpu->arch.pending_load_cause); 2509 /* Restore saved resume PC */
2498 if (er == EMULATE_FAIL) 2510 vcpu->arch.pc = vcpu->arch.io_pc;
2499 return er;
2500 2511
2501 switch (run->mmio.len) { 2512 switch (run->mmio.len) {
2502 case 4: 2513 case 4:
@@ -2518,11 +2529,6 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
2518 break; 2529 break;
2519 } 2530 }
2520 2531
2521 if (vcpu->arch.pending_load_cause & CAUSEF_BD)
2522 kvm_debug("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
2523 vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
2524 vcpu->mmio_needed);
2525
2526done: 2532done:
2527 return er; 2533 return er;
2528} 2534}