aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2014-07-19 03:59:34 -0400
committerAlexander Graf <agraf@suse.de>2014-07-28 09:23:16 -0400
commita0840240c0c6bcbac8f0f5db11f95c19aaf9b52f (patch)
tree3b4a2c128db2ff01c5d646780f0e63fc78d84229 /arch/powerpc
parentb2677b8dd8de0dc1496ede4da09b9dfd59f15cea (diff)
KVM: PPC: Book3S: Fix LPCR one_reg interface
Unfortunately, the LPCR got defined as a 32-bit register in the one_reg interface. This is unfortunate because KVM allows userspace to control the DPFD (default prefetch depth) field, which is in the upper 32 bits. The result is that DPFD always get set to 0, which reduces performance in the guest. We can't just change KVM_REG_PPC_LPCR to be a 64-bit register ID, since that would break existing userspace binaries. Instead we define a new KVM_REG_PPC_LPCR_64 id which is 64-bit. Userspace can still use the old KVM_REG_PPC_LPCR id, but it now only modifies those fields in the bottom 32 bits that userspace can modify (ILE, TC and AIL). If userspace uses the new KVM_REG_PPC_LPCR_64 id, it can modify DPFD as well. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Paul Mackerras <paulus@samba.org> Cc: stable@vger.kernel.org Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/uapi/asm/kvm.h1
-rw-r--r--arch/powerpc/kvm/book3s_hv.c13
-rw-r--r--arch/powerpc/kvm/book3s_pr.c2
3 files changed, 14 insertions, 2 deletions
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 0e56d9e7b2d6..e0e49dbb145d 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -548,6 +548,7 @@ struct kvm_get_htab_header {
548 548
549#define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4) 549#define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
550#define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5) 550#define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
551#define KVM_REG_PPC_LPCR_64 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb5)
551#define KVM_REG_PPC_PPR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6) 552#define KVM_REG_PPC_PPR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6)
552 553
553/* Architecture compatibility level */ 554/* Architecture compatibility level */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index f1281c4c381c..0c5266e75a2e 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -863,7 +863,8 @@ static int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu,
863 return 0; 863 return 0;
864} 864}
865 865
866static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr) 866static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr,
867 bool preserve_top32)
867{ 868{
868 struct kvmppc_vcore *vc = vcpu->arch.vcore; 869 struct kvmppc_vcore *vc = vcpu->arch.vcore;
869 u64 mask; 870 u64 mask;
@@ -898,6 +899,10 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr)
898 mask = LPCR_DPFD | LPCR_ILE | LPCR_TC; 899 mask = LPCR_DPFD | LPCR_ILE | LPCR_TC;
899 if (cpu_has_feature(CPU_FTR_ARCH_207S)) 900 if (cpu_has_feature(CPU_FTR_ARCH_207S))
900 mask |= LPCR_AIL; 901 mask |= LPCR_AIL;
902
903 /* Broken 32-bit version of LPCR must not clear top bits */
904 if (preserve_top32)
905 mask &= 0xFFFFFFFF;
901 vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask); 906 vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask);
902 spin_unlock(&vc->lock); 907 spin_unlock(&vc->lock);
903} 908}
@@ -1011,6 +1016,7 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
1011 *val = get_reg_val(id, vcpu->arch.vcore->tb_offset); 1016 *val = get_reg_val(id, vcpu->arch.vcore->tb_offset);
1012 break; 1017 break;
1013 case KVM_REG_PPC_LPCR: 1018 case KVM_REG_PPC_LPCR:
1019 case KVM_REG_PPC_LPCR_64:
1014 *val = get_reg_val(id, vcpu->arch.vcore->lpcr); 1020 *val = get_reg_val(id, vcpu->arch.vcore->lpcr);
1015 break; 1021 break;
1016 case KVM_REG_PPC_PPR: 1022 case KVM_REG_PPC_PPR:
@@ -1216,7 +1222,10 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
1216 ALIGN(set_reg_val(id, *val), 1UL << 24); 1222 ALIGN(set_reg_val(id, *val), 1UL << 24);
1217 break; 1223 break;
1218 case KVM_REG_PPC_LPCR: 1224 case KVM_REG_PPC_LPCR:
1219 kvmppc_set_lpcr(vcpu, set_reg_val(id, *val)); 1225 kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), true);
1226 break;
1227 case KVM_REG_PPC_LPCR_64:
1228 kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), false);
1220 break; 1229 break;
1221 case KVM_REG_PPC_PPR: 1230 case KVM_REG_PPC_PPR:
1222 vcpu->arch.ppr = set_reg_val(id, *val); 1231 vcpu->arch.ppr = set_reg_val(id, *val);
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index b18f2d4fac59..e7a1fa2517b1 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -1314,6 +1314,7 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
1314 *val = get_reg_val(id, to_book3s(vcpu)->hior); 1314 *val = get_reg_val(id, to_book3s(vcpu)->hior);
1315 break; 1315 break;
1316 case KVM_REG_PPC_LPCR: 1316 case KVM_REG_PPC_LPCR:
1317 case KVM_REG_PPC_LPCR_64:
1317 /* 1318 /*
1318 * We are only interested in the LPCR_ILE bit 1319 * We are only interested in the LPCR_ILE bit
1319 */ 1320 */
@@ -1349,6 +1350,7 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
1349 to_book3s(vcpu)->hior_explicit = true; 1350 to_book3s(vcpu)->hior_explicit = true;
1350 break; 1351 break;
1351 case KVM_REG_PPC_LPCR: 1352 case KVM_REG_PPC_LPCR:
1353 case KVM_REG_PPC_LPCR_64:
1352 kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val)); 1354 kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val));
1353 break; 1355 break;
1354 default: 1356 default: