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)) {
		/* 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_vmexit(svm);
		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_guest_switch()) 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)) {
		 
		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_vmexit(svm);
		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;
}