diff mbox series

[SRU,Xenial,1/1] KVM: PPC: Book3S: Treat VTB as a per-subcore register, not per-thread

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

Commit Message

Joseph Salisbury Nov. 3, 2017, 5:05 p.m. UTC
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(-)

Comments

Andy Whitcroft Nov. 14, 2017, 3:16 p.m. UTC | #1
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
Kleber Sacilotto de Souza Nov. 14, 2017, 3:23 p.m. UTC | #2
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 mbox series

Patch

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));