Commit 72e91cae authored by James Hogan's avatar James Hogan Committed by Ben Hutchings

MIPS: KVM: Propagate kseg0/mapped tlb fault errors

commit 9b731bcf upstream.

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: 858dd5d4 ("KVM/MIPS32: MMU/TLB operations for the Guest.")
Fixes: e685c689 ("KVM/MIPS32: Privileged instruction/target branch emulation.")
Signed-off-by: default avatarJames 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
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
[bwh: Backported to 3.16: adjust filename, context]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 01be3799
...@@ -1481,9 +1481,13 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause, ...@@ -1481,9 +1481,13 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
preempt_disable(); preempt_disable();
if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) { if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) {
if (kvm_mips_host_tlb_lookup(vcpu, va) < 0 &&
if (kvm_mips_host_tlb_lookup(vcpu, va) < 0) { kvm_mips_handle_kseg0_tlb_fault(va, vcpu)) {
kvm_mips_handle_kseg0_tlb_fault(va, vcpu); kvm_err("%s: handling mapped kseg0 tlb fault for %lx, vcpu: %p, ASID: %#lx\n",
__func__, va, vcpu, read_c0_entryhi());
er = EMULATE_FAIL;
preempt_enable();
goto done;
} }
} else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) || } else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) ||
KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) { KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) {
...@@ -1516,11 +1520,19 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause, ...@@ -1516,11 +1520,19 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
run, vcpu); run, vcpu);
preempt_enable(); preempt_enable();
goto dont_update_pc; goto dont_update_pc;
} else { }
/* We fault an entry from the guest tlb to the shadow host TLB */ /*
kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, * We fault an entry from the guest tlb to the
NULL, * shadow host TLB
NULL); */
if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
NULL, NULL)) {
kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n",
__func__, va, index, vcpu,
read_c0_entryhi());
er = EMULATE_FAIL;
preempt_enable();
goto done;
} }
} }
} else { } else {
...@@ -2335,8 +2347,13 @@ kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc, ...@@ -2335,8 +2347,13 @@ kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n", ("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n",
tlb->tlb_hi, tlb->tlb_lo0, tlb->tlb_lo1); tlb->tlb_hi, tlb->tlb_lo0, tlb->tlb_lo1);
/* OK we have a Guest TLB entry, now inject it into the shadow host TLB */ /* OK we have a Guest TLB entry, now inject it into the shadow host TLB */
kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL, if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
NULL); NULL, NULL)) {
kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n",
__func__, va, index, vcpu,
read_c0_entryhi());
er = EMULATE_FAIL;
}
} }
} }
......
...@@ -801,10 +801,16 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu) ...@@ -801,10 +801,16 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
local_irq_restore(flags); local_irq_restore(flags);
return KVM_INVALID_INST; return KVM_INVALID_INST;
} }
kvm_mips_handle_mapped_seg_tlb_fault(vcpu, if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
&vcpu->arch. &vcpu->arch.guest_tlb[index],
guest_tlb[index], NULL, NULL)) {
NULL, NULL); kvm_err("%s: handling mapped seg tlb fault failed for %p, index: %u, vcpu: %p, ASID: %#lx\n",
__func__, opc, index, vcpu,
read_c0_entryhi());
kvm_mips_dump_guest_tlbs(vcpu);
local_irq_restore(flags);
return KVM_INVALID_INST;
}
inst = *(opc); inst = *(opc);
} }
local_irq_restore(flags); local_irq_restore(flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment