Re: [PATCH 06/11] KVM: PPC: Book3S HV: Support POWER6 compatibility mode on POWER7

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 05.09.2013, at 22:22, Paul Mackerras wrote:

> This enables us to use the Processor Compatibility Register (PCR) on
> POWER7 to put the processor into architecture 2.05 compatibility mode
> when running a guest.  In this mode the new instructions and registers
> that were introduced on POWER7 are disabled in user mode.  This
> includes all the VSX facilities plus several other instructions such
> as ldbrx, stdbrx, popcntw, popcntd, etc.
> 
> To select this mode, we have a new register accessible through the
> set/get_one_reg interface, called KVM_REG_PPC_ARCH_COMPAT.  Setting
> this to zero gives the full set of capabilities of the processor.
> Setting it to one of the "logical" PVR values defined in PAPR puts
> the vcpu into the compatibility mode for the corresponding
> architecture level.  The supported values are:
> 
> 0x0f000002	Architecture 2.05 (POWER6)
> 0x0f000003	Architecture 2.06 (POWER7)
> 0x0f100003	Architecture 2.06+ (POWER7+)
> 
> Since the PCR is per-core, the architecture compatibility level and
> the corresponding PCR value are stored in the struct kvmppc_vcore, and
> are therefore shared between all vcpus in a virtual core.
> 
> Signed-off-by: Paul Mackerras <paulus@xxxxxxxxx>
> ---
> Documentation/virtual/kvm/api.txt       |  1 +
> arch/powerpc/include/asm/kvm_host.h     |  2 ++
> arch/powerpc/include/asm/reg.h          | 11 +++++++++++
> arch/powerpc/include/uapi/asm/kvm.h     |  3 +++
> arch/powerpc/kernel/asm-offsets.c       |  1 +
> arch/powerpc/kvm/book3s_hv.c            | 35 +++++++++++++++++++++++++++++++++
> arch/powerpc/kvm/book3s_hv_rmhandlers.S | 11 +++++++++--
> 7 files changed, 62 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 34a32b6..f1f300f 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -1837,6 +1837,7 @@ registers, find a list below:
>   PPC   | KVM_REG_PPC_VRSAVE	| 32
>   PPC   | KVM_REG_PPC_LPCR	| 64
>   PPC   | KVM_REG_PPC_PPR	| 64
> +  PPC   | KVM_REG_PPC_ARCH_COMPAT | 32
>   PPC   | KVM_REG_PPC_TM_GPR0	| 64
>           ...
>   PPC   | KVM_REG_PPC_TM_GPR31	| 64
> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> index b0dcd18..5a40270 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -295,6 +295,8 @@ struct kvmppc_vcore {
> 	u64 preempt_tb;
> 	struct kvm_vcpu *runner;
> 	u64 tb_offset;		/* guest timebase - host timebase */
> +	u32 arch_compat;
> +	ulong pcr;
> };
> 
> #define VCORE_ENTRY_COUNT(vc)	((vc)->entry_exit_count & 0xff)
> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
> index 3fc0d06..52ff962 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -305,6 +305,10 @@
> #define   LPID_RSVD	0x3ff		/* Reserved LPID for partn switching */
> #define	SPRN_HMER	0x150	/* Hardware m? error recovery */
> #define	SPRN_HMEER	0x151	/* Hardware m? enable error recovery */
> +#define SPRN_PCR	0x152	/* Processor compatibility register */
> +#define   PCR_VEC_DIS	(1ul << (63-0))	/* Vec. disable (pre POWER8) */
> +#define   PCR_VSX_DIS	(1ul << (63-1))	/* VSX disable (pre POWER8) */
> +#define   PCR_ARCH_205	0x2		/* Architecture 2.05 */
> #define	SPRN_HEIR	0x153	/* Hypervisor Emulated Instruction Register */
> #define SPRN_TLBINDEXR	0x154	/* P7 TLB control register */
> #define SPRN_TLBVPNR	0x155	/* P7 TLB control register */
> @@ -1095,6 +1099,13 @@
> #define PVR_BE		0x0070
> #define PVR_PA6T	0x0090
> 
> +/* "Logical" PVR values defined in PAPR, representing architecture levels */
> +#define PVR_ARCH_204	0x0f000001
> +#define PVR_ARCH_205	0x0f000002
> +#define PVR_ARCH_206	0x0f000003
> +#define PVR_ARCH_206p	0x0f100003
> +#define PVR_ARCH_207	0x0f000004
> +
> /* Macros for setting and retrieving special purpose registers */
> #ifndef __ASSEMBLY__
> #define mfmsr()		({unsigned long rval; \
> diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
> index fab6bc1..e420d46 100644
> --- a/arch/powerpc/include/uapi/asm/kvm.h
> +++ b/arch/powerpc/include/uapi/asm/kvm.h
> @@ -536,6 +536,9 @@ struct kvm_get_htab_header {
> #define KVM_REG_PPC_LPCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
> #define KVM_REG_PPC_PPR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6)
> 
> +/* Architecture compatibility level */
> +#define KVM_REG_PPC_ARCH_COMPAT	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7)
> +
> /* Transactional Memory checkpointed state:
>  * This is all GPRs, all VSX regs and a subset of SPRs
>  */
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index 5c6ea96..115dd64 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -522,6 +522,7 @@ int main(void)
> 	DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
> 	DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
> 	DEFINE(VCORE_TB_OFFSET, offsetof(struct kvmppc_vcore, tb_offset));
> +	DEFINE(VCORE_PCR, offsetof(struct kvmppc_vcore, pcr));
> 	DEFINE(VCPU_SVCPU, offsetof(struct kvmppc_vcpu_book3s, shadow_vcpu) -
> 			   offsetof(struct kvmppc_vcpu_book3s, vcpu));
> 	DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index eceff7e..1a10afa 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -166,6 +166,35 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
> 	vcpu->arch.pvr = pvr;
> }
> 
> +int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
> +{
> +	unsigned long pcr = 0;
> +	struct kvmppc_vcore *vc = vcpu->arch.vcore;
> +
> +	if (arch_compat) {
> +		if (!cpu_has_feature(CPU_FTR_ARCH_206))
> +			return -EINVAL;	/* 970 has no compat mode support */
> +
> +		switch (arch_compat) {
> +		case PVR_ARCH_205:
> +			pcr = PCR_ARCH_205;
> +			break;
> +		case PVR_ARCH_206:
> +		case PVR_ARCH_206p:
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +	}
> +
> +	spin_lock(&vc->lock);
> +	vc->arch_compat = arch_compat;
> +	vc->pcr = pcr;
> +	spin_unlock(&vc->lock);
> +
> +	return 0;
> +}
> +
> void kvmppc_dump_regs(struct kvm_vcpu *vcpu)
> {
> 	int r;
> @@ -817,6 +846,9 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
> 	case KVM_REG_PPC_PPR:
> 		*val = get_reg_val(id, vcpu->arch.ppr);
> 		break;
> +	case KVM_REG_PPC_ARCH_COMPAT:
> +		*val = get_reg_val(id, vcpu->arch.vcore->arch_compat);
> +		break;
> 	default:
> 		r = -EINVAL;
> 		break;
> @@ -927,6 +959,9 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
> 	case KVM_REG_PPC_PPR:
> 		vcpu->arch.ppr = set_reg_val(id, *val);
> 		break;
> +	case KVM_REG_PPC_ARCH_COMPAT:
> +		r = kvmppc_set_arch_compat(vcpu, set_reg_val(id, *val));
> +		break;
> 	default:
> 		r = -EINVAL;
> 		break;
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index 88e7068..023d8600 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -358,7 +358,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
> 	addis	r8,r8,0x100	/* if so, increment upper 40 bits */
> 	mtspr	SPRN_TBU40,r8
> 
> -37:	li	r0,1
> +	/* Load guest PCR value to select appropriate compat mode */
> +37:	ld	r7, VCORE_PCR(r5)
> +	mtspr	SPRN_PCR, r7
> +
> +	li	r0,1
> 	stb	r0,VCORE_IN_GUEST(r5)	/* signal secondaries to continue */
> 	b	10f
> 
> @@ -984,8 +988,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
> 	addis	r8,r8,0x100		/* if so, increment upper 40 bits */
> 	mtspr	SPRN_TBU40,r8
> 
> -	/* Signal secondary CPUs to continue */
> +	/* Reset PCR */
> 17:	li	r0,0
> +	mtspr	SPRN_PCR,r0

How long does writing to PCR take? Is it faster than a load+branch to see whether we actually need it? I would assume the normal fast path is going to be guest cpu == host.


Alex

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux