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: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
3d3efb68c1
commit
1bc3fe818c
|
@ -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,
|
||||||
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)
|
||||||
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 */
|
||||||
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:
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue