diff options
author | Paul Mackerras <paulus@samba.org> | 2014-04-14 19:52:27 +1000 |
---|---|---|
committer | Wang Sen <wangsen@linux.vnet.ibm.com> | 2014-04-16 11:15:21 +0800 |
commit | 846274db638806ae00a048339f345c4779e92b1e (patch) | |
tree | a8351a1108ef772ccfd9ac04cd52b1aeb066bbc6 | |
parent | a758d7ee38f23bfb828f7e0abf470ca68191fe5c (diff) | |
download | powerkvm-846274db638806ae00a048339f345c4779e92b1e.tar.gz |
KVM: PPC: Book3S PR: Implement ARCH_COMPAT register
This provides basic support for the KVM_REG_PPC_ARCH_COMPAT register
in PR KVM. At present the value is sanity-checked when set, but
doesn't actually affect anything yet.
Implementing this makes it possible to use a qemu command-line
argument such as "-cpu host,compat=power7" on a POWER8 machine,
just as we would with HV KVM.
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 40 |
2 files changed, 42 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 160faad31e8cf..19144ebb28d83 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -576,6 +576,8 @@ struct kvm_vcpu_arch { u32 ivor[64]; ulong ivpr; u32 pvr; + u32 pvr_arch; + u32 compat_arch; u32 shadow_pid; u32 shadow_pid1; diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index dc61cbafd6b71..955c75ade84bb 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -298,6 +298,28 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr) kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); } +/* + * Evaluate the architecture level of a PVR value. + * The result is in terms of PVR_ARCH_* values. + */ +static u32 pvr_to_arch(u32 pvr) +{ + switch (PVR_VER(pvr)) { + case PVR_POWER5p: + return PVR_ARCH_204; + case PVR_POWER6: + return PVR_ARCH_205; + case PVR_POWER7: + case PVR_POWER7p: + return PVR_ARCH_206; + case PVR_POWER8: + case PVR_POWER8E: + return PVR_ARCH_207; + default: + return 0; + } +} + void kvmppc_set_pvr_pr(struct kvm_vcpu *vcpu, u32 pvr) { u32 host_pvr; @@ -373,6 +395,18 @@ void kvmppc_set_pvr_pr(struct kvm_vcpu *vcpu, u32 pvr) /* Enable HID2.PSE - in case we need it later */ mtspr(SPRN_HID2_GEKKO, mfspr(SPRN_HID2_GEKKO) | (1 << 29)); } + + vcpu->arch.pvr_arch = pvr_to_arch(pvr); + if (vcpu->arch.pvr_arch < vcpu->arch.compat_arch) + vcpu->arch.compat_arch = 0; +} + +static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 compat_arch) +{ + if (compat_arch > vcpu->arch.pvr_arch) + return -EINVAL; + vcpu->arch.compat_arch = vcpu->arch.pvr_arch; + return 0; } /* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To @@ -1087,6 +1121,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_ARCH_COMPAT: + *val = get_reg_val(id, vcpu->arch.compat_arch); + break; default: r = -EINVAL; break; @@ -1105,6 +1142,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_ARCH_COMPAT: + r = kvmppc_set_arch_compat(vcpu, set_reg_val(id, *val)); + break; default: r = -EINVAL; break; |