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 <[email protected]>
> ---
> 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to