Message ID | d02b1f29fc0cffad794defef2270cff08b8569ad.1509386181.git.joseph.salisbury@canonical.com |
---|---|
State | New |
Headers | show |
Series | [SRU,Xenial,1/1] KVM: PPC: Book3S: Treat VTB as a per-subcore register, not per-thread | expand |
On Fri, Nov 03, 2017 at 01:05:44PM -0400, Joseph Salisbury wrote: > From: Paul Mackerras <paulus@ozlabs.org> > > BugLink: http://bugs.launchpad.net/bugs/1727331 > > POWER8 has one virtual timebase (VTB) register per subcore, not one > per CPU thread. The HV KVM code currently treats VTB as a per-thread > register, which can lead to spurious soft lockup messages from guests > which use the VTB as the time source for the soft lockup detector. > (CPUs before POWER8 did not have the VTB register.) > > For HV KVM, this fixes the problem by making only the primary thread > in each virtual core save and restore the VTB value. With this, > the VTB state becomes part of the kvmppc_vcore structure. This > also means that "piggybacking" of multiple virtual cores onto one > subcore is not possible on POWER8, because then the virtual cores > would share a single VTB register. > > PR KVM emulates a VTB register, which is per-vcpu because PR KVM > has no notion of CPU threads or SMT. For PR KVM we move the VTB > state into the kvmppc_vcpu_book3s struct. > > Cc: stable@vger.kernel.org # v3.14+ > Reported-by: Thomas Huth <thuth@redhat.com> > Tested-by: Thomas Huth <thuth@redhat.com> > (backported from commit 88b02cf97bb7e742db3e31671d54177e3e19fd89) > Signed-off-by: Paul Mackerras <paulus@ozlabs.org> > Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com> > --- > arch/powerpc/include/asm/kvm_book3s.h | 1 + > arch/powerpc/include/asm/kvm_host.h | 2 +- > arch/powerpc/kernel/asm-offsets.c | 2 +- > arch/powerpc/kvm/book3s.c | 6 ------ > arch/powerpc/kvm/book3s_emulate.c | 2 +- > arch/powerpc/kvm/book3s_hv.c | 14 +++++++++++--- > arch/powerpc/kvm/book3s_hv_rmhandlers.S | 14 +++++++------- > arch/powerpc/kvm/book3s_pr.c | 8 +++++++- > 8 files changed, 29 insertions(+), 20 deletions(-) > > diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h > index 9fac01c..299737b 100644 > --- a/arch/powerpc/include/asm/kvm_book3s.h > +++ b/arch/powerpc/include/asm/kvm_book3s.h > @@ -83,6 +83,7 @@ struct kvmppc_vcpu_book3s { > u64 sdr1; > u64 hior; > u64 msr_mask; > + u64 vtb; > #ifdef CONFIG_PPC_BOOK3S_32 > u32 vsid_pool[VSID_POOL_SIZE]; > u32 vsid_next; > diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h > index a92d95a..0d95aae 100644 > --- a/arch/powerpc/include/asm/kvm_host.h > +++ b/arch/powerpc/include/asm/kvm_host.h > @@ -297,6 +297,7 @@ struct kvmppc_vcore { > u32 arch_compat; > ulong pcr; > ulong dpdes; /* doorbell state (POWER8) */ > + ulong vtb; /* virtual timebase */ > ulong conferring_threads; > }; > > @@ -473,7 +474,6 @@ struct kvm_vcpu_arch { > ulong purr; > ulong spurr; > ulong ic; > - ulong vtb; > ulong dscr; > ulong amr; > ulong uamor; > diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c > index 40da691..2692fa6 100644 > --- a/arch/powerpc/kernel/asm-offsets.c > +++ b/arch/powerpc/kernel/asm-offsets.c > @@ -519,7 +519,6 @@ int main(void) > DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr)); > DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr)); > DEFINE(VCPU_IC, offsetof(struct kvm_vcpu, arch.ic)); > - DEFINE(VCPU_VTB, offsetof(struct kvm_vcpu, arch.vtb)); > DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr)); > DEFINE(VCPU_AMR, offsetof(struct kvm_vcpu, arch.amr)); > DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor)); > @@ -572,6 +571,7 @@ int main(void) > DEFINE(VCORE_LPCR, offsetof(struct kvmppc_vcore, lpcr)); > DEFINE(VCORE_PCR, offsetof(struct kvmppc_vcore, pcr)); > DEFINE(VCORE_DPDES, offsetof(struct kvmppc_vcore, dpdes)); > + DEFINE(VCORE_VTB, offsetof(struct kvmppc_vcore, vtb)); > DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige)); > DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv)); > DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb)); > diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c > index 099c79d..a86fad3 100644 > --- a/arch/powerpc/kvm/book3s.c > +++ b/arch/powerpc/kvm/book3s.c > @@ -591,9 +591,6 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_BESCR: > *val = get_reg_val(id, vcpu->arch.bescr); > break; > - case KVM_REG_PPC_VTB: > - *val = get_reg_val(id, vcpu->arch.vtb); > - break; > case KVM_REG_PPC_IC: > *val = get_reg_val(id, vcpu->arch.ic); > break; > @@ -665,9 +662,6 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_BESCR: > vcpu->arch.bescr = set_reg_val(id, *val); > break; > - case KVM_REG_PPC_VTB: > - vcpu->arch.vtb = set_reg_val(id, *val); > - break; > case KVM_REG_PPC_IC: > vcpu->arch.ic = set_reg_val(id, *val); > break; > diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c > index 729f8fa..8359752 100644 > --- a/arch/powerpc/kvm/book3s_emulate.c > +++ b/arch/powerpc/kvm/book3s_emulate.c > @@ -580,7 +580,7 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val > *spr_val = vcpu->arch.spurr; > break; > case SPRN_VTB: > - *spr_val = vcpu->arch.vtb; > + *spr_val = to_book3s(vcpu)->vtb; > break; > case SPRN_IC: > *spr_val = vcpu->arch.ic; > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index d4b50a9..bb8243e 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -1101,6 +1101,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_DPDES: > *val = get_reg_val(id, vcpu->arch.vcore->dpdes); > break; > + case KVM_REG_PPC_VTB: > + *val = get_reg_val(id, vcpu->arch.vcore->vtb); > + break; > case KVM_REG_PPC_DAWR: > *val = get_reg_val(id, vcpu->arch.dawr); > break; > @@ -1296,6 +1299,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_DPDES: > vcpu->arch.vcore->dpdes = set_reg_val(id, *val); > break; > + case KVM_REG_PPC_VTB: > + vcpu->arch.vcore->vtb = set_reg_val(id, *val); > + break; > case KVM_REG_PPC_DAWR: > vcpu->arch.dawr = set_reg_val(id, *val); > break; > @@ -2122,9 +2128,11 @@ static bool can_piggyback_subcore(struct kvmppc_vcore *pvc, > pvc->lpcr != vc->lpcr) > return false; > > - /* P8 guest with > 1 thread per core would see wrong TIR value */ > - if (cpu_has_feature(CPU_FTR_ARCH_207S) && > - (vc->num_threads > 1 || pvc->num_threads > 1)) > + /* > + * P8 guests can't do piggybacking, because then the > + * VTB would be shared between the vcpus. > + */ > + if (cpu_has_feature(CPU_FTR_ARCH_207S)) > return false; > > n_thr = cip->subcore_threads[sub] + pvc->num_threads; > diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S > index 5663af2..bb8c706 100644 > --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S > +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S > @@ -622,9 +622,11 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_207S) > 38: > > BEGIN_FTR_SECTION > - /* DPDES is shared between threads */ > + /* DPDES and VTB are shared between threads */ > ld r8, VCORE_DPDES(r5) > + ld r7, VCORE_VTB(r5) > mtspr SPRN_DPDES, r8 > + mtspr SPRN_VTB, r7 > END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) > > /* Mark the subcore state as inside guest */ > @@ -794,10 +796,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) > mtspr SPRN_CIABR, r7 > mtspr SPRN_TAR, r8 > ld r5, VCPU_IC(r4) > - ld r6, VCPU_VTB(r4) > - mtspr SPRN_IC, r5 > - mtspr SPRN_VTB, r6 > ld r8, VCPU_EBBHR(r4) > + mtspr SPRN_IC, r5 > mtspr SPRN_EBBHR, r8 > ld r5, VCPU_EBBRR(r4) > ld r6, VCPU_BESCR(r4) > @@ -1278,10 +1278,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) > stw r6, VCPU_PSPB(r9) > std r7, VCPU_FSCR(r9) > mfspr r5, SPRN_IC > - mfspr r6, SPRN_VTB > mfspr r7, SPRN_TAR > std r5, VCPU_IC(r9) > - std r6, VCPU_VTB(r9) > std r7, VCPU_TAR(r9) > mfspr r8, SPRN_EBBHR > std r8, VCPU_EBBHR(r9) > @@ -1518,9 +1516,11 @@ kvmhv_switch_to_host: > isync > > BEGIN_FTR_SECTION > - /* DPDES is shared between threads */ > + /* DPDES and VTB are shared between threads */ > mfspr r7, SPRN_DPDES > + mfspr r8, SPRN_VTB > std r7, VCORE_DPDES(r5) > + std r8, VCORE_VTB(r5) > /* clear DPDES so we don't get guest doorbells in the host */ > li r8, 0 > mtspr SPRN_DPDES, r8 > diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c > index 49f5dad..28fdc7f 100644 > --- a/arch/powerpc/kvm/book3s_pr.c > +++ b/arch/powerpc/kvm/book3s_pr.c > @@ -226,7 +226,7 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, > */ > vcpu->arch.purr += get_tb() - vcpu->arch.entry_tb; > vcpu->arch.spurr += get_tb() - vcpu->arch.entry_tb; > - vcpu->arch.vtb += get_vtb() - vcpu->arch.entry_vtb; > + to_book3s(vcpu)->vtb += get_vtb() - vcpu->arch.entry_vtb; > if (cpu_has_feature(CPU_FTR_ARCH_207S)) > vcpu->arch.ic += mfspr(SPRN_IC) - vcpu->arch.entry_ic; > svcpu->in_use = false; > @@ -1325,6 +1325,9 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_HIOR: > *val = get_reg_val(id, to_book3s(vcpu)->hior); > break; > + case KVM_REG_PPC_VTB: > + *val = get_reg_val(id, to_book3s(vcpu)->vtb); > + break; > case KVM_REG_PPC_LPCR: > case KVM_REG_PPC_LPCR_64: > /* > @@ -1361,6 +1364,9 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, > to_book3s(vcpu)->hior = set_reg_val(id, *val); > to_book3s(vcpu)->hior_explicit = true; > break; > + case KVM_REG_PPC_VTB: > + to_book3s(vcpu)->vtb = set_reg_val(id, *val); > + break; > case KVM_REG_PPC_LPCR: > case KVM_REG_PPC_LPCR_64: > kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val)); Looks reasonable to me. Acked-by: Andy Whitcroft <apw@canonical.com> -apw
On 11/03/17 18:05, Joseph Salisbury wrote: > From: Paul Mackerras <paulus@ozlabs.org> > > BugLink: http://bugs.launchpad.net/bugs/1727331 > > POWER8 has one virtual timebase (VTB) register per subcore, not one > per CPU thread. The HV KVM code currently treats VTB as a per-thread > register, which can lead to spurious soft lockup messages from guests > which use the VTB as the time source for the soft lockup detector. > (CPUs before POWER8 did not have the VTB register.) > > For HV KVM, this fixes the problem by making only the primary thread > in each virtual core save and restore the VTB value. With this, > the VTB state becomes part of the kvmppc_vcore structure. This > also means that "piggybacking" of multiple virtual cores onto one > subcore is not possible on POWER8, because then the virtual cores > would share a single VTB register. > > PR KVM emulates a VTB register, which is per-vcpu because PR KVM > has no notion of CPU threads or SMT. For PR KVM we move the VTB > state into the kvmppc_vcpu_book3s struct. > > Cc: stable@vger.kernel.org # v3.14+ > Reported-by: Thomas Huth <thuth@redhat.com> > Tested-by: Thomas Huth <thuth@redhat.com> > (backported from commit 88b02cf97bb7e742db3e31671d54177e3e19fd89) > Signed-off-by: Paul Mackerras <paulus@ozlabs.org> > Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com> Scope limited to powerpc, tested by the bug reporter and the backport looks good. Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > --- > arch/powerpc/include/asm/kvm_book3s.h | 1 + > arch/powerpc/include/asm/kvm_host.h | 2 +- > arch/powerpc/kernel/asm-offsets.c | 2 +- > arch/powerpc/kvm/book3s.c | 6 ------ > arch/powerpc/kvm/book3s_emulate.c | 2 +- > arch/powerpc/kvm/book3s_hv.c | 14 +++++++++++--- > arch/powerpc/kvm/book3s_hv_rmhandlers.S | 14 +++++++------- > arch/powerpc/kvm/book3s_pr.c | 8 +++++++- > 8 files changed, 29 insertions(+), 20 deletions(-) > > diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h > index 9fac01c..299737b 100644 > --- a/arch/powerpc/include/asm/kvm_book3s.h > +++ b/arch/powerpc/include/asm/kvm_book3s.h > @@ -83,6 +83,7 @@ struct kvmppc_vcpu_book3s { > u64 sdr1; > u64 hior; > u64 msr_mask; > + u64 vtb; > #ifdef CONFIG_PPC_BOOK3S_32 > u32 vsid_pool[VSID_POOL_SIZE]; > u32 vsid_next; > diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h > index a92d95a..0d95aae 100644 > --- a/arch/powerpc/include/asm/kvm_host.h > +++ b/arch/powerpc/include/asm/kvm_host.h > @@ -297,6 +297,7 @@ struct kvmppc_vcore { > u32 arch_compat; > ulong pcr; > ulong dpdes; /* doorbell state (POWER8) */ > + ulong vtb; /* virtual timebase */ > ulong conferring_threads; > }; > > @@ -473,7 +474,6 @@ struct kvm_vcpu_arch { > ulong purr; > ulong spurr; > ulong ic; > - ulong vtb; > ulong dscr; > ulong amr; > ulong uamor; > diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c > index 40da691..2692fa6 100644 > --- a/arch/powerpc/kernel/asm-offsets.c > +++ b/arch/powerpc/kernel/asm-offsets.c > @@ -519,7 +519,6 @@ int main(void) > DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr)); > DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr)); > DEFINE(VCPU_IC, offsetof(struct kvm_vcpu, arch.ic)); > - DEFINE(VCPU_VTB, offsetof(struct kvm_vcpu, arch.vtb)); > DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr)); > DEFINE(VCPU_AMR, offsetof(struct kvm_vcpu, arch.amr)); > DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor)); > @@ -572,6 +571,7 @@ int main(void) > DEFINE(VCORE_LPCR, offsetof(struct kvmppc_vcore, lpcr)); > DEFINE(VCORE_PCR, offsetof(struct kvmppc_vcore, pcr)); > DEFINE(VCORE_DPDES, offsetof(struct kvmppc_vcore, dpdes)); > + DEFINE(VCORE_VTB, offsetof(struct kvmppc_vcore, vtb)); > DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige)); > DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv)); > DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb)); > diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c > index 099c79d..a86fad3 100644 > --- a/arch/powerpc/kvm/book3s.c > +++ b/arch/powerpc/kvm/book3s.c > @@ -591,9 +591,6 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_BESCR: > *val = get_reg_val(id, vcpu->arch.bescr); > break; > - case KVM_REG_PPC_VTB: > - *val = get_reg_val(id, vcpu->arch.vtb); > - break; > case KVM_REG_PPC_IC: > *val = get_reg_val(id, vcpu->arch.ic); > break; > @@ -665,9 +662,6 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_BESCR: > vcpu->arch.bescr = set_reg_val(id, *val); > break; > - case KVM_REG_PPC_VTB: > - vcpu->arch.vtb = set_reg_val(id, *val); > - break; > case KVM_REG_PPC_IC: > vcpu->arch.ic = set_reg_val(id, *val); > break; > diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c > index 729f8fa..8359752 100644 > --- a/arch/powerpc/kvm/book3s_emulate.c > +++ b/arch/powerpc/kvm/book3s_emulate.c > @@ -580,7 +580,7 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val > *spr_val = vcpu->arch.spurr; > break; > case SPRN_VTB: > - *spr_val = vcpu->arch.vtb; > + *spr_val = to_book3s(vcpu)->vtb; > break; > case SPRN_IC: > *spr_val = vcpu->arch.ic; > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index d4b50a9..bb8243e 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -1101,6 +1101,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_DPDES: > *val = get_reg_val(id, vcpu->arch.vcore->dpdes); > break; > + case KVM_REG_PPC_VTB: > + *val = get_reg_val(id, vcpu->arch.vcore->vtb); > + break; > case KVM_REG_PPC_DAWR: > *val = get_reg_val(id, vcpu->arch.dawr); > break; > @@ -1296,6 +1299,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_DPDES: > vcpu->arch.vcore->dpdes = set_reg_val(id, *val); > break; > + case KVM_REG_PPC_VTB: > + vcpu->arch.vcore->vtb = set_reg_val(id, *val); > + break; > case KVM_REG_PPC_DAWR: > vcpu->arch.dawr = set_reg_val(id, *val); > break; > @@ -2122,9 +2128,11 @@ static bool can_piggyback_subcore(struct kvmppc_vcore *pvc, > pvc->lpcr != vc->lpcr) > return false; > > - /* P8 guest with > 1 thread per core would see wrong TIR value */ > - if (cpu_has_feature(CPU_FTR_ARCH_207S) && > - (vc->num_threads > 1 || pvc->num_threads > 1)) > + /* > + * P8 guests can't do piggybacking, because then the > + * VTB would be shared between the vcpus. > + */ > + if (cpu_has_feature(CPU_FTR_ARCH_207S)) > return false; > > n_thr = cip->subcore_threads[sub] + pvc->num_threads; > diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S > index 5663af2..bb8c706 100644 > --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S > +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S > @@ -622,9 +622,11 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_207S) > 38: > > BEGIN_FTR_SECTION > - /* DPDES is shared between threads */ > + /* DPDES and VTB are shared between threads */ > ld r8, VCORE_DPDES(r5) > + ld r7, VCORE_VTB(r5) > mtspr SPRN_DPDES, r8 > + mtspr SPRN_VTB, r7 > END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) > > /* Mark the subcore state as inside guest */ > @@ -794,10 +796,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) > mtspr SPRN_CIABR, r7 > mtspr SPRN_TAR, r8 > ld r5, VCPU_IC(r4) > - ld r6, VCPU_VTB(r4) > - mtspr SPRN_IC, r5 > - mtspr SPRN_VTB, r6 > ld r8, VCPU_EBBHR(r4) > + mtspr SPRN_IC, r5 > mtspr SPRN_EBBHR, r8 > ld r5, VCPU_EBBRR(r4) > ld r6, VCPU_BESCR(r4) > @@ -1278,10 +1278,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) > stw r6, VCPU_PSPB(r9) > std r7, VCPU_FSCR(r9) > mfspr r5, SPRN_IC > - mfspr r6, SPRN_VTB > mfspr r7, SPRN_TAR > std r5, VCPU_IC(r9) > - std r6, VCPU_VTB(r9) > std r7, VCPU_TAR(r9) > mfspr r8, SPRN_EBBHR > std r8, VCPU_EBBHR(r9) > @@ -1518,9 +1516,11 @@ kvmhv_switch_to_host: > isync > > BEGIN_FTR_SECTION > - /* DPDES is shared between threads */ > + /* DPDES and VTB are shared between threads */ > mfspr r7, SPRN_DPDES > + mfspr r8, SPRN_VTB > std r7, VCORE_DPDES(r5) > + std r8, VCORE_VTB(r5) > /* clear DPDES so we don't get guest doorbells in the host */ > li r8, 0 > mtspr SPRN_DPDES, r8 > diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c > index 49f5dad..28fdc7f 100644 > --- a/arch/powerpc/kvm/book3s_pr.c > +++ b/arch/powerpc/kvm/book3s_pr.c > @@ -226,7 +226,7 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, > */ > vcpu->arch.purr += get_tb() - vcpu->arch.entry_tb; > vcpu->arch.spurr += get_tb() - vcpu->arch.entry_tb; > - vcpu->arch.vtb += get_vtb() - vcpu->arch.entry_vtb; > + to_book3s(vcpu)->vtb += get_vtb() - vcpu->arch.entry_vtb; > if (cpu_has_feature(CPU_FTR_ARCH_207S)) > vcpu->arch.ic += mfspr(SPRN_IC) - vcpu->arch.entry_ic; > svcpu->in_use = false; > @@ -1325,6 +1325,9 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, > case KVM_REG_PPC_HIOR: > *val = get_reg_val(id, to_book3s(vcpu)->hior); > break; > + case KVM_REG_PPC_VTB: > + *val = get_reg_val(id, to_book3s(vcpu)->vtb); > + break; > case KVM_REG_PPC_LPCR: > case KVM_REG_PPC_LPCR_64: > /* > @@ -1361,6 +1364,9 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, > to_book3s(vcpu)->hior = set_reg_val(id, *val); > to_book3s(vcpu)->hior_explicit = true; > break; > + case KVM_REG_PPC_VTB: > + to_book3s(vcpu)->vtb = set_reg_val(id, *val); > + break; > case KVM_REG_PPC_LPCR: > case KVM_REG_PPC_LPCR_64: > kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val)); >
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index 9fac01c..299737b 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h @@ -83,6 +83,7 @@ struct kvmppc_vcpu_book3s { u64 sdr1; u64 hior; u64 msr_mask; + u64 vtb; #ifdef CONFIG_PPC_BOOK3S_32 u32 vsid_pool[VSID_POOL_SIZE]; u32 vsid_next; diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index a92d95a..0d95aae 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -297,6 +297,7 @@ struct kvmppc_vcore { u32 arch_compat; ulong pcr; ulong dpdes; /* doorbell state (POWER8) */ + ulong vtb; /* virtual timebase */ ulong conferring_threads; }; @@ -473,7 +474,6 @@ struct kvm_vcpu_arch { ulong purr; ulong spurr; ulong ic; - ulong vtb; ulong dscr; ulong amr; ulong uamor; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 40da691..2692fa6 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -519,7 +519,6 @@ int main(void) DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr)); DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr)); DEFINE(VCPU_IC, offsetof(struct kvm_vcpu, arch.ic)); - DEFINE(VCPU_VTB, offsetof(struct kvm_vcpu, arch.vtb)); DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr)); DEFINE(VCPU_AMR, offsetof(struct kvm_vcpu, arch.amr)); DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor)); @@ -572,6 +571,7 @@ int main(void) DEFINE(VCORE_LPCR, offsetof(struct kvmppc_vcore, lpcr)); DEFINE(VCORE_PCR, offsetof(struct kvmppc_vcore, pcr)); DEFINE(VCORE_DPDES, offsetof(struct kvmppc_vcore, dpdes)); + DEFINE(VCORE_VTB, offsetof(struct kvmppc_vcore, vtb)); DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige)); DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv)); DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb)); diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 099c79d..a86fad3 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -591,9 +591,6 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, case KVM_REG_PPC_BESCR: *val = get_reg_val(id, vcpu->arch.bescr); break; - case KVM_REG_PPC_VTB: - *val = get_reg_val(id, vcpu->arch.vtb); - break; case KVM_REG_PPC_IC: *val = get_reg_val(id, vcpu->arch.ic); break; @@ -665,9 +662,6 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, case KVM_REG_PPC_BESCR: vcpu->arch.bescr = set_reg_val(id, *val); break; - case KVM_REG_PPC_VTB: - vcpu->arch.vtb = set_reg_val(id, *val); - break; case KVM_REG_PPC_IC: vcpu->arch.ic = set_reg_val(id, *val); break; diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c index 729f8fa..8359752 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c @@ -580,7 +580,7 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val *spr_val = vcpu->arch.spurr; break; case SPRN_VTB: - *spr_val = vcpu->arch.vtb; + *spr_val = to_book3s(vcpu)->vtb; break; case SPRN_IC: *spr_val = vcpu->arch.ic; diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index d4b50a9..bb8243e 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -1101,6 +1101,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, case KVM_REG_PPC_DPDES: *val = get_reg_val(id, vcpu->arch.vcore->dpdes); break; + case KVM_REG_PPC_VTB: + *val = get_reg_val(id, vcpu->arch.vcore->vtb); + break; case KVM_REG_PPC_DAWR: *val = get_reg_val(id, vcpu->arch.dawr); break; @@ -1296,6 +1299,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, case KVM_REG_PPC_DPDES: vcpu->arch.vcore->dpdes = set_reg_val(id, *val); break; + case KVM_REG_PPC_VTB: + vcpu->arch.vcore->vtb = set_reg_val(id, *val); + break; case KVM_REG_PPC_DAWR: vcpu->arch.dawr = set_reg_val(id, *val); break; @@ -2122,9 +2128,11 @@ static bool can_piggyback_subcore(struct kvmppc_vcore *pvc, pvc->lpcr != vc->lpcr) return false; - /* P8 guest with > 1 thread per core would see wrong TIR value */ - if (cpu_has_feature(CPU_FTR_ARCH_207S) && - (vc->num_threads > 1 || pvc->num_threads > 1)) + /* + * P8 guests can't do piggybacking, because then the + * VTB would be shared between the vcpus. + */ + if (cpu_has_feature(CPU_FTR_ARCH_207S)) return false; n_thr = cip->subcore_threads[sub] + pvc->num_threads; diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 5663af2..bb8c706 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -622,9 +622,11 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_207S) 38: BEGIN_FTR_SECTION - /* DPDES is shared between threads */ + /* DPDES and VTB are shared between threads */ ld r8, VCORE_DPDES(r5) + ld r7, VCORE_VTB(r5) mtspr SPRN_DPDES, r8 + mtspr SPRN_VTB, r7 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) /* Mark the subcore state as inside guest */ @@ -794,10 +796,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) mtspr SPRN_CIABR, r7 mtspr SPRN_TAR, r8 ld r5, VCPU_IC(r4) - ld r6, VCPU_VTB(r4) - mtspr SPRN_IC, r5 - mtspr SPRN_VTB, r6 ld r8, VCPU_EBBHR(r4) + mtspr SPRN_IC, r5 mtspr SPRN_EBBHR, r8 ld r5, VCPU_EBBRR(r4) ld r6, VCPU_BESCR(r4) @@ -1278,10 +1278,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) stw r6, VCPU_PSPB(r9) std r7, VCPU_FSCR(r9) mfspr r5, SPRN_IC - mfspr r6, SPRN_VTB mfspr r7, SPRN_TAR std r5, VCPU_IC(r9) - std r6, VCPU_VTB(r9) std r7, VCPU_TAR(r9) mfspr r8, SPRN_EBBHR std r8, VCPU_EBBHR(r9) @@ -1518,9 +1516,11 @@ kvmhv_switch_to_host: isync BEGIN_FTR_SECTION - /* DPDES is shared between threads */ + /* DPDES and VTB are shared between threads */ mfspr r7, SPRN_DPDES + mfspr r8, SPRN_VTB std r7, VCORE_DPDES(r5) + std r8, VCORE_VTB(r5) /* clear DPDES so we don't get guest doorbells in the host */ li r8, 0 mtspr SPRN_DPDES, r8 diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 49f5dad..28fdc7f 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -226,7 +226,7 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, */ vcpu->arch.purr += get_tb() - vcpu->arch.entry_tb; vcpu->arch.spurr += get_tb() - vcpu->arch.entry_tb; - vcpu->arch.vtb += get_vtb() - vcpu->arch.entry_vtb; + to_book3s(vcpu)->vtb += get_vtb() - vcpu->arch.entry_vtb; if (cpu_has_feature(CPU_FTR_ARCH_207S)) vcpu->arch.ic += mfspr(SPRN_IC) - vcpu->arch.entry_ic; svcpu->in_use = false; @@ -1325,6 +1325,9 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, case KVM_REG_PPC_HIOR: *val = get_reg_val(id, to_book3s(vcpu)->hior); break; + case KVM_REG_PPC_VTB: + *val = get_reg_val(id, to_book3s(vcpu)->vtb); + break; case KVM_REG_PPC_LPCR: case KVM_REG_PPC_LPCR_64: /* @@ -1361,6 +1364,9 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, to_book3s(vcpu)->hior = set_reg_val(id, *val); to_book3s(vcpu)->hior_explicit = true; break; + case KVM_REG_PPC_VTB: + to_book3s(vcpu)->vtb = set_reg_val(id, *val); + break; case KVM_REG_PPC_LPCR: case KVM_REG_PPC_LPCR_64: kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val));