On Tue, Sep 08, 2026 at 12:33:36PM +0200, Jörg Rödel wrote: > From: Joerg Roedel <[email protected]> > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c ... > +static int snp_get_vcpu_state(struct kvm_vcpu *vcpu, > + struct kvm_sev_cmd *argp) > +{ > + struct vcpu_svm *svm = to_svm(vcpu); > + struct kvm *kvm = vcpu->kvm; > + struct kvm_sev_snp_vcpu_state state = {}; > + > + if (!is_sev_snp_guest(vcpu)) > + return -ENOTTY; > + if (!to_kvm_sev_info(kvm)->snp_context) > + return -EINVAL; > + > + guard(mutex)(&svm->sev_es.snp_vmsa_mutex); > + > + if (VALID_PAGE(svm->sev_es.snp_guest_vmsa_gpa) && > + VALID_PAGE(svm->vmcb->control.vmsa_pa)) { > + state.vmsa_gpa = svm->sev_es.snp_guest_vmsa_gpa; > + state.valid_fields |= KVM_SEV_SNP_VCPU_STATE_VMSA_VALID; > + } > + > + if (VALID_PAGE(svm->vmcb->control.ghcb_gpa)) { > + state.ghcb_gpa = svm->vmcb->control.ghcb_gpa; > + state.valid_fields |= KVM_SEV_SNP_VCPU_STATE_GHCB_VALID; > + } > + > + if (copy_to_user(u64_to_user_ptr(argp->data), &state, sizeof(state))) > + return -EFAULT; > + > + return 0; > +} > + > +static int snp_set_vcpu_state(struct kvm_vcpu *vcpu, > + struct kvm_sev_cmd *argp) > +{ > + struct vcpu_svm *svm = to_svm(vcpu); > + struct kvm *kvm = vcpu->kvm; > + struct kvm_sev_info *sev = to_kvm_sev_info(kvm); > + struct kvm_sev_snp_vcpu_state state; > + int ret; > + > + if (!is_sev_snp_guest(vcpu)) > + return -ENOTTY; > + if (!sev->snp_direct_vmsa) > + return -EINVAL; > + if (!sev->snp_context || kvm->arch.pre_fault_allowed) > + return -EINVAL; > + > + if (copy_from_user(&state, u64_to_user_ptr(argp->data), sizeof(state))) > + return -EFAULT; > + > + if (memchr_inv(state.pad, 0, sizeof(state.pad)) || > + state.valid_fields & ~(KVM_SEV_SNP_VCPU_STATE_VMSA_VALID | > + KVM_SEV_SNP_VCPU_STATE_GHCB_VALID)) > + return -EINVAL; > + > + if (state.valid_fields & KVM_SEV_SNP_VCPU_STATE_VMSA_VALID) { > + if (!PAGE_ALIGNED(state.vmsa_gpa) || > + !page_address_valid(vcpu, state.vmsa_gpa) || > + IS_ALIGNED(state.vmsa_gpa, PMD_SIZE)) > + return -EINVAL; > + } > + > + guard(mutex)(&svm->sev_es.snp_vmsa_mutex); > + > + if (state.valid_fields & KVM_SEV_SNP_VCPU_STATE_VMSA_VALID) { > + ret = sev_snp_install_guest_vmsa(svm, state.vmsa_gpa); > + if (ret) > + return ret; > + } else { > + svm->sev_es.snp_has_guest_vmsa = true; > + svm->sev_es.snp_guest_vmsa_gpa = INVALID_PAGE; > + svm->vmcb->control.vmsa_pa = INVALID_PAGE; > + } > + > + if (state.valid_fields & KVM_SEV_SNP_VCPU_STATE_GHCB_VALID) > + svm->vmcb->control.ghcb_gpa = state.ghcb_gpa; > + else > + svm->vmcb->control.ghcb_gpa = INVALID_PAGE; > + > + vmcb_mark_all_dirty(svm->vmcb); > + return 0; > +} > +
Nice, looks like snp_get/set_vcpu_state() could quite easily make use of KVM_EXPORT/IMPORT_VCPU?

