KVM: PPC: Book3S HV: Handle hypervisor instruction faults better
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 8 Oct 2018 05:30:56 +0000 (16:30 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 9 Oct 2018 05:04:27 +0000 (16:04 +1100)
Currently the code for handling hypervisor instruction page faults
passes 0 for the flags indicating the type of fault, which is OK in
the usual case that the page is not mapped in the partition-scoped
page tables.  However, there are other causes for hypervisor
instruction page faults, such as not being to update a reference
(R) or change (C) bit.  The cause is indicated in bits in HSRR1,
including a bit which indicates that the fault is due to not being
able to write to a page (for example to update an R or C bit).
Not handling these other kinds of faults correctly can lead to a
loop of continual faults without forward progress in the guest.

In order to handle these faults better, this patch constructs a
"DSISR-like" value from the bits which DSISR and SRR1 (for a HISI)
have in common, and passes it to kvmppc_book3s_hv_page_fault() so
that it knows what caused the fault.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/reg.h
arch/powerpc/kvm/book3s_hv.c

index e5b314ed054e027d69782c9fd7261eaaefe85eb8..6fda746ba32874999db3fcf68450bcd73a248b48 100644 (file)
 #define SPRN_HSRR0     0x13A   /* Save/Restore Register 0 */
 #define SPRN_HSRR1     0x13B   /* Save/Restore Register 1 */
 #define   HSRR1_DENORM         0x00100000 /* Denorm exception */
+#define   HSRR1_HISI_WRITE     0x00010000 /* HISI bcs couldn't update mem */
 
 #define SPRN_TBCTL     0x35f   /* PA6T Timebase control register */
 #define   TBCTL_FREEZE         0x0000000000000000ull /* Freeze all tbs */
index 4befa5a812feded0fc2636467f9bc22051da567b..3334ed9e17e8c94c43dbb78d72859e185da9e3a2 100644 (file)
@@ -1188,7 +1188,10 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu,
                break;
        case BOOK3S_INTERRUPT_H_INST_STORAGE:
                vcpu->arch.fault_dar = kvmppc_get_pc(vcpu);
-               vcpu->arch.fault_dsisr = 0;
+               vcpu->arch.fault_dsisr = vcpu->arch.shregs.msr &
+                       DSISR_SRR1_MATCH_64S;
+               if (vcpu->arch.shregs.msr & HSRR1_HISI_WRITE)
+                       vcpu->arch.fault_dsisr |= DSISR_ISSTORE;
                r = RESUME_PAGE_FAULT;
                break;
        /*