static int svm_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
{
	struct vcpu_svm *svm = to_svm(vcpu);
	struct kvm_host_map map, map_save;
	int ret = 0;

	if (guest_cpuid_has(vcpu, X86_FEATURE_LM)) {
		u64 saved_efer = GET_SMSTATE(u64, smstate, 0x7ed0);
		u64 guest = GET_SMSTATE(u64, smstate, 0x7ed8);
		u64 vmcb12_gpa = GET_SMSTATE(u64, smstate, 0x7ee0);
		struct vmcb *vmcb12;

		if (guest) {
			if (!guest_cpuid_has(vcpu, X86_FEATURE_SVM))
				return 1;

			if (!(saved_efer & EFER_SVME))
				return 1;

			if (kvm_vcpu_map(vcpu,
					 gpa_to_gfn(vmcb12_gpa), &map) == -EINVAL)
				return 1;

			if (svm_allocate_nested(svm))
				return 1;

			vmcb12 = map.hva;

			nested_load_control_from_vmcb12(svm, &vmcb12->control);

			ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12);
			kvm_vcpu_unmap(vcpu, &map, true);

			/*
			 * Restore L1 host state from L1 HSAVE area as VMCB01 was
			 * used during SMM (see svm_enter_smm())
			 */
			if (kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.hsave_msr),
					 &map_save) == -EINVAL)
				return 1;

			svm_copy_vmrun_state(&svm->vmcb01.ptr->save,
					     map_save.hva + 0x400);

			kvm_vcpu_unmap(vcpu, &map_save, true);
		}
	}

	return ret;
}
static int svm_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
{
	struct vcpu_svm *svm = to_svm(vcpu);
	struct kvm_host_map map, map_save;
	int ret = 0;

	if (guest_cpuid_has(vcpu, X86_FEATURE_LM)) {
		u64 saved_efer = GET_SMSTATE(u64, smstate, 0x7ed0);
		u64 guest = GET_SMSTATE(u64, smstate, 0x7ed8);
		u64 vmcb12_gpa = GET_SMSTATE(u64, smstate, 0x7ee0);
		struct vmcb *vmcb12;

		if (guest) {
			if (!guest_cpuid_has(vcpu, X86_FEATURE_SVM))
				return 1;

			if (!(saved_efer & EFER_SVME))
				return 1;

			if (kvm_vcpu_map(vcpu,
					 gpa_to_gfn(vmcb12_gpa), &map) == -EINVAL)
				return 1;

			if (svm_allocate_nested(svm))
				return 1;

			vmcb12 = map.hva;

			nested_load_control_from_vmcb12(svm, &vmcb12->control);

			ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12);
			kvm_vcpu_unmap(vcpu, &map, true);

			 
			if (kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.hsave_msr),
					 &map_save) == -EINVAL)
				return 1;

			svm_copy_vmrun_state(&svm->vmcb01.ptr->save,
					     map_save.hva + 0x400);

			kvm_vcpu_unmap(vcpu, &map_save, true);
		}
	}

	return ret;
}