diff options
author | James Hogan <james.hogan@imgtec.com> | 2016-08-11 06:58:15 -0400 |
---|---|---|
committer | Radim Krčmář <rkrcmar@redhat.com> | 2016-08-12 06:01:30 -0400 |
commit | 9b731bcfdec4c159ad2e4312e25d69221709b96a (patch) | |
tree | 0c52204c89a66ea2c2a2ba36f9a74216f167ce24 /arch/mips/kvm | |
parent | 0741f52d1b980dbeb290afe67d88fc2928edd8ab (diff) |
MIPS: KVM: Propagate kseg0/mapped tlb fault errors
Propagate errors from kvm_mips_handle_kseg0_tlb_fault() and
kvm_mips_handle_mapped_seg_tlb_fault(), usually triggering an internal
error since they normally indicate the guest accessed bad physical
memory or the commpage in an unexpected way.
Fixes: 858dd5d45733 ("KVM/MIPS32: MMU/TLB operations for the Guest.")
Fixes: e685c689f3a8 ("KVM/MIPS32: Privileged instruction/target branch emulation.")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Cc: <stable@vger.kernel.org> # 3.10.x-
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
Diffstat (limited to 'arch/mips/kvm')
-rw-r--r-- | arch/mips/kvm/emulate.c | 35 | ||||
-rw-r--r-- | arch/mips/kvm/mmu.c | 12 |
2 files changed, 35 insertions, 12 deletions
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index 6eb52b9c9818..e788515f766b 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c | |||
@@ -1642,8 +1642,14 @@ enum emulation_result kvm_mips_emulate_cache(union mips_instruction inst, | |||
1642 | 1642 | ||
1643 | preempt_disable(); | 1643 | preempt_disable(); |
1644 | if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) { | 1644 | if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) { |
1645 | if (kvm_mips_host_tlb_lookup(vcpu, va) < 0) | 1645 | if (kvm_mips_host_tlb_lookup(vcpu, va) < 0 && |
1646 | kvm_mips_handle_kseg0_tlb_fault(va, vcpu); | 1646 | kvm_mips_handle_kseg0_tlb_fault(va, vcpu)) { |
1647 | kvm_err("%s: handling mapped kseg0 tlb fault for %lx, vcpu: %p, ASID: %#lx\n", | ||
1648 | __func__, va, vcpu, read_c0_entryhi()); | ||
1649 | er = EMULATE_FAIL; | ||
1650 | preempt_enable(); | ||
1651 | goto done; | ||
1652 | } | ||
1647 | } else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) || | 1653 | } else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) || |
1648 | KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) { | 1654 | KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) { |
1649 | int index; | 1655 | int index; |
@@ -1680,12 +1686,18 @@ enum emulation_result kvm_mips_emulate_cache(union mips_instruction inst, | |||
1680 | run, vcpu); | 1686 | run, vcpu); |
1681 | preempt_enable(); | 1687 | preempt_enable(); |
1682 | goto dont_update_pc; | 1688 | goto dont_update_pc; |
1683 | } else { | 1689 | } |
1684 | /* | 1690 | /* |
1685 | * We fault an entry from the guest tlb to the | 1691 | * We fault an entry from the guest tlb to the |
1686 | * shadow host TLB | 1692 | * shadow host TLB |
1687 | */ | 1693 | */ |
1688 | kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb); | 1694 | if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb)) { |
1695 | kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n", | ||
1696 | __func__, va, index, vcpu, | ||
1697 | read_c0_entryhi()); | ||
1698 | er = EMULATE_FAIL; | ||
1699 | preempt_enable(); | ||
1700 | goto done; | ||
1689 | } | 1701 | } |
1690 | } | 1702 | } |
1691 | } else { | 1703 | } else { |
@@ -2659,7 +2671,12 @@ enum emulation_result kvm_mips_handle_tlbmiss(u32 cause, | |||
2659 | * OK we have a Guest TLB entry, now inject it into the | 2671 | * OK we have a Guest TLB entry, now inject it into the |
2660 | * shadow host TLB | 2672 | * shadow host TLB |
2661 | */ | 2673 | */ |
2662 | kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb); | 2674 | if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb)) { |
2675 | kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n", | ||
2676 | __func__, va, index, vcpu, | ||
2677 | read_c0_entryhi()); | ||
2678 | er = EMULATE_FAIL; | ||
2679 | } | ||
2663 | } | 2680 | } |
2664 | } | 2681 | } |
2665 | 2682 | ||
diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c index 6a8a21859502..6cfdcf55572d 100644 --- a/arch/mips/kvm/mmu.c +++ b/arch/mips/kvm/mmu.c | |||
@@ -368,9 +368,15 @@ u32 kvm_get_inst(u32 *opc, struct kvm_vcpu *vcpu) | |||
368 | local_irq_restore(flags); | 368 | local_irq_restore(flags); |
369 | return KVM_INVALID_INST; | 369 | return KVM_INVALID_INST; |
370 | } | 370 | } |
371 | kvm_mips_handle_mapped_seg_tlb_fault(vcpu, | 371 | if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, |
372 | &vcpu->arch. | 372 | &vcpu->arch.guest_tlb[index])) { |
373 | guest_tlb[index]); | 373 | kvm_err("%s: handling mapped seg tlb fault failed for %p, index: %u, vcpu: %p, ASID: %#lx\n", |
374 | __func__, opc, index, vcpu, | ||
375 | read_c0_entryhi()); | ||
376 | kvm_mips_dump_guest_tlbs(vcpu); | ||
377 | local_irq_restore(flags); | ||
378 | return KVM_INVALID_INST; | ||
379 | } | ||
374 | inst = *(opc); | 380 | inst = *(opc); |
375 | } | 381 | } |
376 | local_irq_restore(flags); | 382 | local_irq_restore(flags); |