On Fri, Sep 21, 2018 at 08:01:34PM +1000, Paul Mackerras wrote: > This is based on a patch by Suraj Jitindar Singh. > > This moves the code in book3s_hv_rmhandlers.S that generates an > external, decrementer or privileged doorbell interrupt just before > entering the guest to C code in book3s_hv_builtin.c. This is to > make future maintenance and modification easier. The algorithm > expressed in the C code is almost identical to the previous > algorithm. > > Signed-off-by: Paul Mackerras <paulus@xxxxxxxxxx> Reviewed-by: David Gibson <david@xxxxxxxxxxxxxxxxxxxxx> > --- > arch/powerpc/include/asm/kvm_ppc.h | 1 + > arch/powerpc/kvm/book3s_hv.c | 3 +- > arch/powerpc/kvm/book3s_hv_builtin.c | 48 ++++++++++++++++++++++ > arch/powerpc/kvm/book3s_hv_rmhandlers.S | 70 ++++++++------------------------- > 4 files changed, 67 insertions(+), 55 deletions(-) > > diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h > index e991821..83d61b8 100644 > --- a/arch/powerpc/include/asm/kvm_ppc.h > +++ b/arch/powerpc/include/asm/kvm_ppc.h > @@ -652,6 +652,7 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, > unsigned long mfrr); > int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr); > int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr); > +void kvmppc_guest_entry_inject_int(struct kvm_vcpu *vcpu); > > /* > * Host-side operations we want to set up while running in real > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index 3e3a715..49a686c 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -730,8 +730,7 @@ static bool kvmppc_doorbell_pending(struct kvm_vcpu *vcpu) > /* > * Ensure that the read of vcore->dpdes comes after the read > * of vcpu->doorbell_request. This barrier matches the > - * lwsync in book3s_hv_rmhandlers.S just before the > - * fast_guest_return label. > + * smb_wmb() in kvmppc_guest_entry_inject(). > */ > smp_rmb(); > vc = vcpu->arch.vcore; > diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c > index fc6bb96..ccfea5b 100644 > --- a/arch/powerpc/kvm/book3s_hv_builtin.c > +++ b/arch/powerpc/kvm/book3s_hv_builtin.c > @@ -729,3 +729,51 @@ void kvmhv_p9_restore_lpcr(struct kvm_split_mode *sip) > smp_mb(); > local_paca->kvm_hstate.kvm_split_mode = NULL; > } > + > +/* > + * Is there a PRIV_DOORBELL pending for the guest (on POWER9)? > + * Can we inject a Decrementer or a External interrupt? > + */ > +void kvmppc_guest_entry_inject_int(struct kvm_vcpu *vcpu) > +{ > + int ext; > + unsigned long vec = 0; > + unsigned long lpcr; > + > + /* Insert EXTERNAL bit into LPCR at the MER bit position */ > + ext = (vcpu->arch.pending_exceptions >> BOOK3S_IRQPRIO_EXTERNAL) & 1; > + lpcr = mfspr(SPRN_LPCR); > + lpcr |= ext << LPCR_MER_SH; > + mtspr(SPRN_LPCR, lpcr); > + isync(); > + > + if (vcpu->arch.shregs.msr & MSR_EE) { > + if (ext) { > + vec = BOOK3S_INTERRUPT_EXTERNAL; > + } else { > + long int dec = mfspr(SPRN_DEC); > + if (!(lpcr & LPCR_LD)) > + dec = (int) dec; > + if (dec < 0) > + vec = BOOK3S_INTERRUPT_DECREMENTER; > + } > + } > + if (vec) { > + unsigned long msr, old_msr = vcpu->arch.shregs.msr; > + > + kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu)); > + kvmppc_set_srr1(vcpu, old_msr); > + kvmppc_set_pc(vcpu, vec); > + msr = vcpu->arch.intr_msr; > + if (MSR_TM_ACTIVE(old_msr)) > + msr |= MSR_TS_S; > + vcpu->arch.shregs.msr = msr; > + } > + > + if (vcpu->arch.doorbell_request) { > + mtspr(SPRN_DPDES, 1); > + vcpu->arch.vcore->dpdes = 1; > + smp_wmb(); > + vcpu->arch.doorbell_request = 0; > + } > +} > diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S > index 77960e6..6752da1 100644 > --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S > +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S > @@ -1101,13 +1101,20 @@ no_xive: > #endif /* CONFIG_KVM_XICS */ > > deliver_guest_interrupt: > - ld r6, VCPU_CTR(r4) > - ld r7, VCPU_XER(r4) > - > - mtctr r6 > - mtxer r7 > - > kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */ > + /* Check if we can deliver an external or decrementer interrupt now */ > + ld r0, VCPU_PENDING_EXC(r4) > +BEGIN_FTR_SECTION > + /* On POWER9, also check for emulated doorbell interrupt */ > + lbz r3, VCPU_DBELL_REQ(r4) > + or r0, r0, r3 > +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) > + cmpdi r0, 0 > + beq 71f > + mr r3, r4 > + bl kvmppc_guest_entry_inject_int > + ld r4, HSTATE_KVM_VCPU(r13) > +71: > ld r10, VCPU_PC(r4) > ld r11, VCPU_MSR(r4) > ld r6, VCPU_SRR0(r4) > @@ -1120,53 +1127,10 @@ kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */ > rotldi r11, r11, 1 + MSR_HV_LG > ori r11, r11, MSR_ME > > - /* Check if we can deliver an external or decrementer interrupt now */ > - ld r0, VCPU_PENDING_EXC(r4) > - rldicl r0, r0, 64 - BOOK3S_IRQPRIO_EXTERNAL, 63 > - cmpdi cr1, r0, 0 > - andi. r8, r11, MSR_EE > - mfspr r8, SPRN_LPCR > - /* Insert EXTERNAL bit into LPCR at the MER bit position */ > - rldimi r8, r0, LPCR_MER_SH, 63 - LPCR_MER_SH > - mtspr SPRN_LPCR, r8 > - isync > - beq 5f > - li r0, BOOK3S_INTERRUPT_EXTERNAL > - bne cr1, 12f > - mfspr r0, SPRN_DEC > -BEGIN_FTR_SECTION > - /* On POWER9 check whether the guest has large decrementer enabled */ > - andis. r8, r8, LPCR_LD@h > - bne 15f > -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) > - extsw r0, r0 > -15: cmpdi r0, 0 > - li r0, BOOK3S_INTERRUPT_DECREMENTER > - bge 5f > - > -12: mtspr SPRN_SRR0, r10 > - mr r10,r0 > - mtspr SPRN_SRR1, r11 > - mr r9, r4 > - bl kvmppc_msr_interrupt > -5: > -BEGIN_FTR_SECTION > - b fast_guest_return > -END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) > - /* On POWER9, check for pending doorbell requests */ > - lbz r0, VCPU_DBELL_REQ(r4) > - cmpwi r0, 0 > - beq fast_guest_return > - ld r5, HSTATE_KVM_VCORE(r13) > - /* Set DPDES register so the CPU will take a doorbell interrupt */ > - li r0, 1 > - mtspr SPRN_DPDES, r0 > - std r0, VCORE_DPDES(r5) > - /* Make sure other cpus see vcore->dpdes set before dbell req clear */ > - lwsync > - /* Clear the pending doorbell request */ > - li r0, 0 > - stb r0, VCPU_DBELL_REQ(r4) > + ld r6, VCPU_CTR(r4) > + ld r7, VCPU_XER(r4) > + mtctr r6 > + mtxer r7 > > /* > * Required state: -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Attachment:
signature.asc
Description: PGP signature