KVM: PPC: Book3S PR: Expose TAR facility to guest
authorAlexander Graf <agraf@suse.de>
Tue, 22 Apr 2014 10:26:58 +0000 (12:26 +0200)
committerAlexander Graf <agraf@suse.de>
Fri, 30 May 2014 12:26:23 +0000 (14:26 +0200)
POWER8 implements a new register called TAR. This register has to be
enabled in FSCR and then from KVM's point of view is mere storage.

This patch enables the guest to use TAR.

Signed-off-by: Alexander Graf <agraf@suse.de>
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_pr.c

index 232ec5f0b886cce88f8a8dc798d27ebb33749ed9..29fbb554af5c8fed9ee9a76053e1fdcf17496f55 100644 (file)
@@ -449,7 +449,9 @@ struct kvm_vcpu_arch {
        ulong pc;
        ulong ctr;
        ulong lr;
+#ifdef CONFIG_PPC_BOOK3S
        ulong tar;
+#endif
 
        ulong xer;
        u32 cr;
index e2b86b5c02b330bafe3af4d1331c5a540db82919..93e1465c849681729b0b158097562246cf8cd685 100644 (file)
@@ -446,7 +446,9 @@ int main(void)
        DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
        DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
        DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
+#ifdef CONFIG_PPC_BOOK3S
        DEFINE(VCPU_TAR, offsetof(struct kvm_vcpu, arch.tar));
+#endif
        DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
        DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
index 79cfa2d10238b15c5c0599282c807e504b778e1b..4046a1a91a75f7b0457f7bf660ef1748b0f3a021 100644 (file)
@@ -634,6 +634,9 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
                case KVM_REG_PPC_FSCR:
                        val = get_reg_val(reg->id, vcpu->arch.fscr);
                        break;
+               case KVM_REG_PPC_TAR:
+                       val = get_reg_val(reg->id, vcpu->arch.tar);
+                       break;
                default:
                        r = -EINVAL;
                        break;
@@ -726,6 +729,9 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
                case KVM_REG_PPC_FSCR:
                        vcpu->arch.fscr = set_reg_val(reg->id, val);
                        break;
+               case KVM_REG_PPC_TAR:
+                       vcpu->arch.tar = set_reg_val(reg->id, val);
+                       break;
                default:
                        r = -EINVAL;
                        break;
index 0092e12b3e46c216b3b2aa8a0ba8ca0e22e0e533..ee1d8ee5f1a78a6a4eececa2bb438cd96439014f 100644 (file)
@@ -891,9 +891,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
        case KVM_REG_PPC_BESCR:
                *val = get_reg_val(id, vcpu->arch.bescr);
                break;
-       case KVM_REG_PPC_TAR:
-               *val = get_reg_val(id, vcpu->arch.tar);
-               break;
        case KVM_REG_PPC_DPDES:
                *val = get_reg_val(id, vcpu->arch.vcore->dpdes);
                break;
@@ -1100,9 +1097,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
        case KVM_REG_PPC_BESCR:
                vcpu->arch.bescr = set_reg_val(id, *val);
                break;
-       case KVM_REG_PPC_TAR:
-               vcpu->arch.tar = set_reg_val(id, *val);
-               break;
        case KVM_REG_PPC_DPDES:
                vcpu->arch.vcore->dpdes = set_reg_val(id, *val);
                break;
index ddc626eea2dacada291e4489b1803be5fc8b46ab..7d27a9518f07b3225f53584a1b23325eca5df5f1 100644 (file)
@@ -90,6 +90,7 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
 #endif
 
        kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
+       kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
        vcpu->cpu = -1;
 }
 
@@ -625,6 +626,14 @@ static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac)
                /* Facility not available to the guest, ignore giveup request*/
                return;
        }
+
+       switch (fac) {
+       case FSCR_TAR_LG:
+               vcpu->arch.tar = mfspr(SPRN_TAR);
+               mtspr(SPRN_TAR, current->thread.tar);
+               vcpu->arch.shadow_fscr &= ~FSCR_TAR;
+               break;
+       }
 #endif
 }
 
@@ -794,6 +803,12 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)
        }
 
        switch (fac) {
+       case FSCR_TAR_LG:
+               /* TAR switching isn't lazy in Linux yet */
+               current->thread.tar = mfspr(SPRN_TAR);
+               mtspr(SPRN_TAR, vcpu->arch.tar);
+               vcpu->arch.shadow_fscr |= FSCR_TAR;
+               break;
        default:
                kvmppc_emulate_fac(vcpu, fac);
                break;
@@ -1393,6 +1408,9 @@ static int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        /* Make sure we save the guest FPU/Altivec/VSX state */
        kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
 
+       /* Make sure we save the guest TAR/EBB/DSCR state */
+       kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+
 out:
        vcpu->mode = OUTSIDE_GUEST_MODE;
        return ret;