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?

Reply via email to