On Mon, 2017-05-29 at 20:12 +1000, Paul Mackerras wrote:
> This allows userspace (e.g. QEMU) to enable large decrementer mode
> for
> the guest when running on a POWER9 host, by setting the LPCR_LD bit
> in
> the guest LPCR value.  With this, the guest exit code saves 64 bits
> of
> the guest DEC value on exit.  Other places that use the guest DEC
> value check the LPCR_LD bit in the guest LPCR value, and if it is
> set,
> omit the 32-bit sign extension that would otherwise be done.
> 
> This doesn't change the DEC emulation used by PR KVM because PR KVM
> is not supported on POWER9 yet.
> 
> This is partly based on an earlier patch by Oliver O'Halloran.
> 
> Signed-off-by: Paul Mackerras <pau...@ozlabs.org>

Tested with a hacked up qemu and upstream guest/host (with these
patches).

Tested-by: Suraj Jitindar Singh <sjitindarsi...@gmail.com>

> ---
>  arch/powerpc/include/asm/kvm_host.h     |  2 +-
>  arch/powerpc/kvm/book3s_hv.c            |  6 ++++++
>  arch/powerpc/kvm/book3s_hv_rmhandlers.S | 29
> ++++++++++++++++++++++++-----
>  arch/powerpc/kvm/emulate.c              |  4 ++--
>  4 files changed, 33 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_host.h
> b/arch/powerpc/include/asm/kvm_host.h
> index 9c51ac4..3f879c8 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -579,7 +579,7 @@ struct kvm_vcpu_arch {
>       ulong mcsrr0;
>       ulong mcsrr1;
>       ulong mcsr;
> -     u32 dec;
> +     ulong dec;
>  #ifdef CONFIG_BOOKE
>       u32 decar;
>  #endif
> diff --git a/arch/powerpc/kvm/book3s_hv.c
> b/arch/powerpc/kvm/book3s_hv.c
> index 42b7a4f..9b2eb66 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -1143,6 +1143,12 @@ static void kvmppc_set_lpcr(struct kvm_vcpu
> *vcpu, u64 new_lpcr,
>       mask = LPCR_DPFD | LPCR_ILE | LPCR_TC;
>       if (cpu_has_feature(CPU_FTR_ARCH_207S))
>               mask |= LPCR_AIL;
> +     /*
> +      * On POWER9, allow userspace to enable large decrementer
> for the
> +      * guest, whether or not the host has it enabled.
> +      */
> +     if (cpu_has_feature(CPU_FTR_ARCH_300))
> +             mask |= LPCR_LD;
>  
>       /* Broken 32-bit version of LPCR must not clear top bits */
>       if (preserve_top32)
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index e390b38..3c901b5 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -920,7 +920,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
>       mftb    r7
>       subf    r3,r7,r8
>       mtspr   SPRN_DEC,r3
> -     stw     r3,VCPU_DEC(r4)
> +     std     r3,VCPU_DEC(r4)
>  
>       ld      r5, VCPU_SPRG0(r4)
>       ld      r6, VCPU_SPRG1(r4)
> @@ -1032,7 +1032,13 @@ kvmppc_cede_reentry:           /* r4 =
> vcpu, r13 = paca */
>       li      r0, BOOK3S_INTERRUPT_EXTERNAL
>       bne     cr1, 12f
>       mfspr   r0, SPRN_DEC
> -     cmpwi   r0, 0
> +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
>  
> @@ -1459,12 +1465,18 @@ mc_cont:
>       mtspr   SPRN_SPURR,r4
>  
>       /* Save DEC */
> +     ld      r3, HSTATE_KVM_VCORE(r13)
>       mfspr   r5,SPRN_DEC
>       mftb    r6
> +     /* On P9, if the guest has large decr enabled, don't sign
> extend */
> +BEGIN_FTR_SECTION
> +     ld      r4, VCORE_LPCR(r3)
> +     andis.  r4, r4, LPCR_LD@h
> +     bne     16f
> +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
>       extsw   r5,r5
> -     add     r5,r5,r6
> +16:  add     r5,r5,r6
>       /* r5 is a guest timebase value here, convert to host TB */
> -     ld      r3,HSTATE_KVM_VCORE(r13)
>       ld      r4,VCORE_TB_OFFSET(r3)
>       subf    r5,r4,r5
>       std     r5,VCPU_DEC_EXPIRES(r9)
> @@ -2376,8 +2388,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
>       mfspr   r3, SPRN_DEC
>       mfspr   r4, SPRN_HDEC
>       mftb    r5
> +BEGIN_FTR_SECTION
> +     /* On P9 check whether the guest has large decrementer mode
> enabled */
> +     ld      r6, HSTATE_KVM_VCORE(r13)
> +     ld      r6, VCORE_LPCR(r6)
> +     andis.  r6, r6, LPCR_LD@h
> +     bne     68f
> +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
>       extsw   r3, r3
> -     EXTEND_HDEC(r4)
> +68:  EXTEND_HDEC(r4)
>       cmpd    r3, r4
>       ble     67f
>       mtspr   SPRN_DEC, r4
> diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
> index c873ffe..4d8b4d6 100644
> --- a/arch/powerpc/kvm/emulate.c
> +++ b/arch/powerpc/kvm/emulate.c
> @@ -39,7 +39,7 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
>       unsigned long dec_nsec;
>       unsigned long long dec_time;
>  
> -     pr_debug("mtDEC: %x\n", vcpu->arch.dec);
> +     pr_debug("mtDEC: %lx\n", vcpu->arch.dec);
>       hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
>  
>  #ifdef CONFIG_PPC_BOOK3S
> @@ -109,7 +109,7 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu
> *vcpu, int sprn, int rs)
>       case SPRN_TBWU: break;
>  
>       case SPRN_DEC:
> -             vcpu->arch.dec = spr_val;
> +             vcpu->arch.dec = (u32) spr_val;
>               kvmppc_emulate_dec(vcpu);
>               break;
>  

Reply via email to