* [RFC PATCH 03/32] KVM: PPC: Book3S HV: Move interrupt delivery on guest entry to C code
@ 2018-09-21 10:01 Paul Mackerras
2018-09-24 4:10 ` David Gibson
0 siblings, 1 reply; 2+ messages in thread
From: Paul Mackerras @ 2018-09-21 10:01 UTC (permalink / raw)
To: kvm-ppc
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@ozlabs.org>
---
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:
--
2.7.4
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [RFC PATCH 03/32] KVM: PPC: Book3S HV: Move interrupt delivery on guest entry to C code
2018-09-21 10:01 [RFC PATCH 03/32] KVM: PPC: Book3S HV: Move interrupt delivery on guest entry to C code Paul Mackerras
@ 2018-09-24 4:10 ` David Gibson
0 siblings, 0 replies; 2+ messages in thread
From: David Gibson @ 2018-09-24 4:10 UTC (permalink / raw)
To: kvm-ppc
[-- Attachment #1: Type: text/plain, Size: 6712 bytes --]
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@ozlabs.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> 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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2018-09-24 4:10 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-21 10:01 [RFC PATCH 03/32] KVM: PPC: Book3S HV: Move interrupt delivery on guest entry to C code Paul Mackerras
2018-09-24 4:10 ` David Gibson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.