diff options
Diffstat (limited to 'arch/mips/kvm/emulate.c')
| -rw-r--r-- | arch/mips/kvm/emulate.c | 32 |
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 | |||
| 2526 | done: | 2532 | done: |
| 2527 | return er; | 2533 | return er; |
| 2528 | } | 2534 | } |
