Commit 1bc3fe81 authored by Paul Mackerras's avatar Paul Mackerras

KVM: PPC: Book3S HV: Enable guests to use large decrementer mode on POWER9

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: default avatarPaul Mackerras <paulus@ozlabs.org>
parent 3d3efb68
...@@ -579,7 +579,7 @@ struct kvm_vcpu_arch { ...@@ -579,7 +579,7 @@ struct kvm_vcpu_arch {
ulong mcsrr0; ulong mcsrr0;
ulong mcsrr1; ulong mcsrr1;
ulong mcsr; ulong mcsr;
u32 dec; ulong dec;
#ifdef CONFIG_BOOKE #ifdef CONFIG_BOOKE
u32 decar; u32 decar;
#endif #endif
......
...@@ -1143,6 +1143,12 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, ...@@ -1143,6 +1143,12 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr,
mask = LPCR_DPFD | LPCR_ILE | LPCR_TC; mask = LPCR_DPFD | LPCR_ILE | LPCR_TC;
if (cpu_has_feature(CPU_FTR_ARCH_207S)) if (cpu_has_feature(CPU_FTR_ARCH_207S))
mask |= LPCR_AIL; 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 */ /* Broken 32-bit version of LPCR must not clear top bits */
if (preserve_top32) if (preserve_top32)
......
...@@ -936,7 +936,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300) ...@@ -936,7 +936,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
mftb r7 mftb r7
subf r3,r7,r8 subf r3,r7,r8
mtspr SPRN_DEC,r3 mtspr SPRN_DEC,r3
stw r3,VCPU_DEC(r4) std r3,VCPU_DEC(r4)
ld r5, VCPU_SPRG0(r4) ld r5, VCPU_SPRG0(r4)
ld r6, VCPU_SPRG1(r4) ld r6, VCPU_SPRG1(r4)
...@@ -1048,7 +1048,13 @@ kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */ ...@@ -1048,7 +1048,13 @@ kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */
li r0, BOOK3S_INTERRUPT_EXTERNAL li r0, BOOK3S_INTERRUPT_EXTERNAL
bne cr1, 12f bne cr1, 12f
mfspr r0, SPRN_DEC 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 li r0, BOOK3S_INTERRUPT_DECREMENTER
bge 5f bge 5f
...@@ -1475,12 +1481,18 @@ mc_cont: ...@@ -1475,12 +1481,18 @@ mc_cont:
mtspr SPRN_SPURR,r4 mtspr SPRN_SPURR,r4
/* Save DEC */ /* Save DEC */
ld r3, HSTATE_KVM_VCORE(r13)
mfspr r5,SPRN_DEC mfspr r5,SPRN_DEC
mftb r6 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 extsw r5,r5
add r5,r5,r6 16: add r5,r5,r6
/* r5 is a guest timebase value here, convert to host TB */ /* r5 is a guest timebase value here, convert to host TB */
ld r3,HSTATE_KVM_VCORE(r13)
ld r4,VCORE_TB_OFFSET(r3) ld r4,VCORE_TB_OFFSET(r3)
subf r5,r4,r5 subf r5,r4,r5
std r5,VCPU_DEC_EXPIRES(r9) std r5,VCPU_DEC_EXPIRES(r9)
...@@ -2402,8 +2414,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) ...@@ -2402,8 +2414,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
mfspr r3, SPRN_DEC mfspr r3, SPRN_DEC
mfspr r4, SPRN_HDEC mfspr r4, SPRN_HDEC
mftb r5 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 extsw r3, r3
EXTEND_HDEC(r4) 68: EXTEND_HDEC(r4)
cmpd r3, r4 cmpd r3, r4
ble 67f ble 67f
mtspr SPRN_DEC, r4 mtspr SPRN_DEC, r4
......
...@@ -39,7 +39,7 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) ...@@ -39,7 +39,7 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
unsigned long dec_nsec; unsigned long dec_nsec;
unsigned long long dec_time; 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); hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
#ifdef CONFIG_PPC_BOOK3S #ifdef CONFIG_PPC_BOOK3S
...@@ -109,7 +109,7 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) ...@@ -109,7 +109,7 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
case SPRN_TBWU: break; case SPRN_TBWU: break;
case SPRN_DEC: case SPRN_DEC:
vcpu->arch.dec = spr_val; vcpu->arch.dec = (u32) spr_val;
kvmppc_emulate_dec(vcpu); kvmppc_emulate_dec(vcpu);
break; break;
......
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