return err;
 }
 
-static void kvmppc_update_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *vpap)
+static void kvmppc_update_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *vpap,
+                              struct kvmppc_vpa *old_vpap)
 {
        struct kvm *kvm = vcpu->kvm;
        void *va;
                kvmppc_unpin_guest_page(kvm, va, gpa, false);
                va = NULL;
        }
-       if (vpap->pinned_addr)
-               kvmppc_unpin_guest_page(kvm, vpap->pinned_addr, vpap->gpa,
-                                       vpap->dirty);
+       *old_vpap = *vpap;
+
        vpap->gpa = gpa;
        vpap->pinned_addr = va;
        vpap->dirty = false;
 
 static void kvmppc_update_vpas(struct kvm_vcpu *vcpu)
 {
+       struct kvm *kvm = vcpu->kvm;
+       struct kvmppc_vpa old_vpa = { 0 };
+
        if (!(vcpu->arch.vpa.update_pending ||
              vcpu->arch.slb_shadow.update_pending ||
              vcpu->arch.dtl.update_pending))
 
        spin_lock(&vcpu->arch.vpa_update_lock);
        if (vcpu->arch.vpa.update_pending) {
-               kvmppc_update_vpa(vcpu, &vcpu->arch.vpa);
-               if (vcpu->arch.vpa.pinned_addr)
+               kvmppc_update_vpa(vcpu, &vcpu->arch.vpa, &old_vpa);
+               if (old_vpa.pinned_addr) {
+                       if (kvmhv_is_nestedv2())
+                               kvmhv_nestedv2_set_vpa(vcpu, ~0ull);
+                       kvmppc_unpin_guest_page(kvm, old_vpa.pinned_addr, old_vpa.gpa,
+                                               old_vpa.dirty);
+               }
+               if (vcpu->arch.vpa.pinned_addr) {
                        init_vpa(vcpu, vcpu->arch.vpa.pinned_addr);
+                       if (kvmhv_is_nestedv2())
+                               kvmhv_nestedv2_set_vpa(vcpu, __pa(vcpu->arch.vpa.pinned_addr));
+               }
        }
        if (vcpu->arch.dtl.update_pending) {
-               kvmppc_update_vpa(vcpu, &vcpu->arch.dtl);
+               kvmppc_update_vpa(vcpu, &vcpu->arch.dtl, &old_vpa);
+               if (old_vpa.pinned_addr)
+                       kvmppc_unpin_guest_page(kvm, old_vpa.pinned_addr, old_vpa.gpa,
+                                               old_vpa.dirty);
                vcpu->arch.dtl_ptr = vcpu->arch.dtl.pinned_addr;
                vcpu->arch.dtl_index = 0;
        }
-       if (vcpu->arch.slb_shadow.update_pending)
-               kvmppc_update_vpa(vcpu, &vcpu->arch.slb_shadow);
+       if (vcpu->arch.slb_shadow.update_pending) {
+               kvmppc_update_vpa(vcpu, &vcpu->arch.slb_shadow, &old_vpa);
+               if (old_vpa.pinned_addr)
+                       kvmppc_unpin_guest_page(kvm, old_vpa.pinned_addr, old_vpa.gpa,
+                                               old_vpa.dirty);
+       }
+
        spin_unlock(&vcpu->arch.vpa_update_lock);
 }
 
 
 }
 EXPORT_SYMBOL_GPL(kvmhv_nestedv2_set_ptbl_entry);
 
+/**
+ * kvmhv_nestedv2_set_vpa() - register L2 VPA with L0
+ * @vcpu: vcpu
+ * @vpa: L1 logical real address
+ */
+int kvmhv_nestedv2_set_vpa(struct kvm_vcpu *vcpu, unsigned long vpa)
+{
+       struct kvmhv_nestedv2_io *io;
+       struct kvmppc_gs_buff *gsb;
+       int rc = 0;
+
+       io = &vcpu->arch.nestedv2_io;
+       gsb = io->vcpu_run_input;
+
+       kvmppc_gsb_reset(gsb);
+       rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_VPA, vpa);
+       if (rc < 0)
+               goto out;
+
+       rc = kvmppc_gsb_send(gsb, 0);
+       if (rc < 0)
+               pr_err("KVM-NESTEDv2: couldn't register the L2 VPA (rc=%d)\n", rc);
+
+out:
+       kvmppc_gsb_reset(gsb);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(kvmhv_nestedv2_set_vpa);
+
 /**
  * kvmhv_nestedv2_parse_output() - receive values from H_GUEST_RUN_VCPU output
  * @vcpu: vcpu