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

	if (!is_guest_mode(vcpu))
		return 0;

	/* FED8h - SVM Guest */
	put_smstate(u64, smstate, 0x7ed8, 1);
	/* FEE0h - SVM Guest VMCB Physical Address */
	put_smstate(u64, smstate, 0x7ee0, svm->nested.vmcb12_gpa);

	svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
	svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
	svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];

	ret = nested_svm_simple_vmexit(svm, SVM_EXIT_SW);
	if (ret)
		return ret;

	/*
	 * KVM uses VMCB01 to store L1 host state while L2 runs but
	 * VMCB01 is going to be used during SMM and thus the state will
	 * be lost. Temporary save non-VMLOAD/VMSAVE state to the host save
	 * area pointed to by MSR_VM_HSAVE_PA. APM guarantees that the
	 * format of the area is identical to guest save area offsetted
	 * by 0x400 (matches the offset of 'struct vmcb_save_area'
	 * within 'struct vmcb'). Note: HSAVE area may also be used by
	 * L1 hypervisor to save additional host context (e.g. KVM does
	 * that, see svm_prepare_switch_to_guest()) which must be
	 * preserved.
	 */
	if (kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.hsave_msr),
			 &map_save) == -EINVAL)
		return 1;

	BUILD_BUG_ON(offsetof(struct vmcb, save) != 0x400);

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

	kvm_vcpu_unmap(vcpu, &map_save, true);
	return 0;
}
static int svm_enter_smm(struct kvm_vcpu *vcpu, char *smstate)
{
	struct vcpu_svm *svm = to_svm(vcpu);
	struct kvm_host_map map_save;
	int ret;

	if (!is_guest_mode(vcpu))
		return 0;

	 
	put_smstate(u64, smstate, 0x7ed8, 1);
	 
	put_smstate(u64, smstate, 0x7ee0, svm->nested.vmcb12_gpa);

	svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
	svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
	svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];

	ret = nested_svm_simple_vmexit(svm, SVM_EXIT_SW);
	if (ret)
		return ret;

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

	BUILD_BUG_ON(offsetof(struct vmcb, save) != 0x400);

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

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