On Tue, Apr 01, 2025 at 09:01:18AM -0400, Xiaoyao Li wrote:
> Invoke KVM_TDX_INIT_VM in kvm_arch_pre_create_vcpu() that
> KVM_TDX_INIT_VM configures global TD configurations, e.g. the canonical
> CPUID config, and must be executed prior to creating vCPUs.
>
> Use kvm_x86_arch_cpuid() to setup the CPUID settings for TDX VM.
>
> Note, this doesn't address the fact that QEMU may change the CPUID
> configuration when creating vCPUs, i.e. punts on refactoring QEMU to
> provide a stable CPUID config prior to kvm_arch_init().
>
> Signed-off-by: Xiaoyao Li <[email protected]>
> Acked-by: Gerd Hoffmann <[email protected]>
> Acked-by: Markus Armbruster <[email protected]>
> ---
> Changes in v8:
> - Drop the code that initializes cpu->kvm_state before
> kvm_arch_pre_create_vcpu() because it's not needed anymore.
>
> Changes in v7:
> - Add comments to explain why KVM_TDX_INIT_VM should retry on -EAGAIN;
> - Add retry limit of 10000 times for -EAGAIN on KVM_TDX_INIT_VM;
>
> Changes in v6:
> - setup xfam explicitly to fit with new uapi;
> - use tdx_caps->cpuid to filter the input of cpuids because now KVM only
> allows the leafs that reported via KVM_TDX_GET_CAPABILITIES;
>
> Changes in v4:
> - mark init_vm with g_autofree() and use QEMU_LOCK_GUARD() to eliminate
> the goto labels; (Daniel)
> Changes in v3:
> - Pass @errp in tdx_pre_create_vcpu() and pass error info to it. (Daniel)
> ---
> target/i386/kvm/kvm.c | 16 +++---
> target/i386/kvm/kvm_i386.h | 5 ++
> target/i386/kvm/meson.build | 2 +-
> target/i386/kvm/tdx-stub.c | 10 ++++
> target/i386/kvm/tdx.c | 105 ++++++++++++++++++++++++++++++++++++
> target/i386/kvm/tdx.h | 6 +++
> 6 files changed, 137 insertions(+), 7 deletions(-)
> create mode 100644 target/i386/kvm/tdx-stub.c
> diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c
> index 16f67e18ae78..0afaf739c09f 100644
> --- a/target/i386/kvm/tdx.c
> +++ b/target/i386/kvm/tdx.c
> +int tdx_pre_create_vcpu(CPUState *cpu, Error **errp)
> +{
> + X86CPU *x86cpu = X86_CPU(cpu);
> + CPUX86State *env = &x86cpu->env;
> + g_autofree struct kvm_tdx_init_vm *init_vm = NULL;
> + Error *local_err = NULL;
> + int retry = 10000;
> + int r = 0;
> +
> + QEMU_LOCK_GUARD(&tdx_guest->lock);
> + if (tdx_guest->initialized) {
> + return r;
> + }
> +
> + init_vm = g_malloc0(sizeof(struct kvm_tdx_init_vm) +
> + sizeof(struct kvm_cpuid_entry2) *
> KVM_MAX_CPUID_ENTRIES);
> +
> + r = setup_td_xfam(x86cpu, errp);
> + if (r) {
> + return r;
> + }
> +
> + init_vm->cpuid.nent = kvm_x86_build_cpuid(env, init_vm->cpuid.entries,
> 0);
> + tdx_filter_cpuid(&init_vm->cpuid);
> +
> + init_vm->attributes = tdx_guest->attributes;
> + init_vm->xfam = tdx_guest->xfam;
> +
> + /*
> + * KVM_TDX_INIT_VM gets -EAGAIN when KVM side SEAMCALL(TDH_MNG_CREATE)
> + * gets TDX_RND_NO_ENTROPY due to Random number generation (e.g., RDRAND
> or
> + * RDSEED) is busy.
> + *
> + * Retry for the case.
> + */
> + do {
> + error_free(local_err);
> + local_err = NULL;
> + r = tdx_vm_ioctl(KVM_TDX_INIT_VM, 0, init_vm, &local_err);
> + } while (r == -EAGAIN && --retry);
> +
> + if (r < 0) {
> + if (!retry) {
> + error_report("Hardware RNG (Random Number Generator) is busy "
> + "occupied by someone (via RDRAND/RDSEED)
> maliciously, "
> + "which leads to KVM_TDX_INIT_VM keeping failure "
> + "due to lack of entropy.");
This needs to be
error_append_hint(local_err, ....);
so that this message gets associated with the error object that
is propagated, and the top level will print it all at once.
> + }
> + error_propagate(errp, local_err);
> + return r;
> + }
> +
> + tdx_guest->initialized = true;
> +
> + return 0;
> +}
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|