]> Pileus Git - ~andy/linux/blobdiff - arch/powerpc/kvm/book3s_pr.c
Merge branch 'kvm-ppc-next' of git://github.com/agraf/linux-2.6 into kvm-queue
[~andy/linux] / arch / powerpc / kvm / book3s_pr.c
index 6a5fc7d53de67248a5b9d79aa0385a0182cf6c63..c5c052a9729c95d14591087fe71b20168237dc5d 100644 (file)
@@ -67,6 +67,7 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
        memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb));
        svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
+       svcpu->in_use = 0;
        svcpu_put(svcpu);
 #endif
        vcpu->cpu = smp_processor_id();
@@ -79,6 +80,9 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       if (svcpu->in_use) {
+               kvmppc_copy_from_svcpu(vcpu, svcpu);
+       }
        memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
        to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
        svcpu_put(svcpu);
@@ -111,12 +115,26 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
        svcpu->ctr = vcpu->arch.ctr;
        svcpu->lr  = vcpu->arch.lr;
        svcpu->pc  = vcpu->arch.pc;
+       svcpu->in_use = true;
 }
 
 /* Copy data touched by real-mode code from shadow vcpu back to vcpu */
 void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
                            struct kvmppc_book3s_shadow_vcpu *svcpu)
 {
+       /*
+        * vcpu_put would just call us again because in_use hasn't
+        * been updated yet.
+        */
+       preempt_disable();
+
+       /*
+        * Maybe we were already preempted and synced the svcpu from
+        * our preempt notifiers. Don't bother touching this svcpu then.
+        */
+       if (!svcpu->in_use)
+               goto out;
+
        vcpu->arch.gpr[0] = svcpu->gpr[0];
        vcpu->arch.gpr[1] = svcpu->gpr[1];
        vcpu->arch.gpr[2] = svcpu->gpr[2];
@@ -140,6 +158,10 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
        vcpu->arch.fault_dar   = svcpu->fault_dar;
        vcpu->arch.fault_dsisr = svcpu->fault_dsisr;
        vcpu->arch.last_inst   = svcpu->last_inst;
+       svcpu->in_use = false;
+
+out:
+       preempt_enable();
 }
 
 static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu)