KVM: PPC: Book3S: Fix LPCR one_reg interface
[pandora-kernel.git] / arch / powerpc / kvm / book3s_hv.c
index f1281c4..0c5266e 100644 (file)
@@ -863,7 +863,8 @@ static int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr)
+static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr,
+               bool preserve_top32)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
        u64 mask;
@@ -898,6 +899,10 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr)
        mask = LPCR_DPFD | LPCR_ILE | LPCR_TC;
        if (cpu_has_feature(CPU_FTR_ARCH_207S))
                mask |= LPCR_AIL;
+
+       /* Broken 32-bit version of LPCR must not clear top bits */
+       if (preserve_top32)
+               mask &= 0xFFFFFFFF;
        vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask);
        spin_unlock(&vc->lock);
 }
@@ -1011,6 +1016,7 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
                *val = get_reg_val(id, vcpu->arch.vcore->tb_offset);
                break;
        case KVM_REG_PPC_LPCR:
+       case KVM_REG_PPC_LPCR_64:
                *val = get_reg_val(id, vcpu->arch.vcore->lpcr);
                break;
        case KVM_REG_PPC_PPR:
@@ -1216,7 +1222,10 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
                        ALIGN(set_reg_val(id, *val), 1UL << 24);
                break;
        case KVM_REG_PPC_LPCR:
-               kvmppc_set_lpcr(vcpu, set_reg_val(id, *val));
+               kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), true);
+               break;
+       case KVM_REG_PPC_LPCR_64:
+               kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), false);
                break;
        case KVM_REG_PPC_PPR:
                vcpu->arch.ppr = set_reg_val(id, *val);