Re: [PATCH 00/10] KVM: SEV: allow customizing VMSA features

From: Sean Christopherson
Date: Mon Feb 12 2024 - 21:46:37 EST


On Fri, Feb 09, 2024, Paolo Bonzini wrote:
> On Fri, Feb 9, 2024 at 8:40 PM Sean Christopherson <seanjc@googlecom> wrote:
> > On Fri, Feb 09, 2024, Paolo Bonzini wrote:
> > > The idea that no parameter would ever be necessary when enabling SEV or
> > > SEV-ES for a VM was decidedly optimistic.
> >
> > That implies there was a conscious decision regarding the uAPI. AFAICT, all of
> > the SEV uAPIs are direct reflections of the PSP invocations. Which is why I'm
> > being so draconian about the SNP uAPIs; this time around, we need to actually
> > design something.
>
> You liked that word, heh? :) The part that I am less sure about, is
> that it's actually _possible_ to design something.
>
> If you end up with a KVM_CREATE_VM2 whose arguments are
>
> uint32_t flags;
> uint32_t vm_type;
> uint64_t arch_mishmash_0; /* Intel only */
> uint64_t arch_mishmash_1; /* AMD only */
> uint64_t arch_mishmash_2; /* Intel only */
> uint64_t arch_mishmash_3; /* AMD only */
>
> and half of the flags are Intel only, the other half are AMD only...
> do you actually gain anything over a vendor-specific ioctl?

Sane, generic names. I agree the code gains are likely negligible, but for me
at least, having KVM-friendly names for the commands would be immensely helpful.
E.g. for KVM_CREATE_VM2, I was thinking more like:

__u32 flags;
__u32 vm_type;
union {
struct tdx;
struct sev;
struct sev_es;
struct sev_snp;
__u8 pad[<big size>]
};

Rinse and repeat for APIs that have a common purpose, but different payloads.

Similar to KVM_{SET,GET}_NESTED_STATE, where the data is wildly different, and
there's very little overlap between {svm,vmx}_set_nested_state(), I find it quite
valuable to have a single set of APIs. E.g. I don't have to translate between
VMX and SVM terminology when thinking about the APIs, when discussing them, etc.

That's especially true for all this CoCo goo, where the names are ridiculously
divergent, and often not exactly intuitive. E.g. LAUNCH_MEASURE reads like
"measure the launch", but surprise, it's "get the measurement".

> Case in point being that the SEV VMSA features would be one of the
> fields above, and they would obviously not be available for TDX.
>
> kvm_run is a different story because it's the result of mmap, and not
> a ioctl. But in this case we have:
>
> - pretty generic APIs like UPDATE_DATA and MEASURE that should just be
> renamed to remove SEV references. Even DBG_DECRYPT and DBG_ENCRYPT
> fall in this category
>
> - APIs that seem okay but may depend on specific initialization flows,
> for example LAUNCH_UPDATE_VMSA. One example of the problems with
> initialization flows is LAUNCH_FINISH, which seems pretty tame but is
> different between SEV{,-ES} and SNP. Another example could be CPUID
> which is slightly different between vendors.
>
> - APIs that are currently vendor-specific, but where a second version
> has a chance of being cross-vendor, for example LAUNCH_SECRET or
> GET_ATTESTATION_REPORT. Or maybe not.

AFAICT, LAUNCH_SECRET (a.k.a. LAUNCH_UPDATE_SECRET) and GET_ATTESTATION_REPORT
shouldn't even be a KVM APIs. Ditto for LAUNCH_MEASURE, and probably other PSP
commands. IIUC, userspace has the VM's firmware handle, I don't see why KVM
needs to be a middle-man.

> - others that have no hope, because they include so many pieces of
> vendor-specific data that there's hardly anything to share. INIT is
> one of them. I guess you could fit the Intel CPUID square hole into
> AMD's CPUID round peg or vice versa, but there's really little in
> common between the two.
>
> I think we should try to go for the first three, but realistically
> will have to stop at the first one in most cases. Honestly, this
> unified API effort should have started years ago if we wanted to go
> there. I see where you're coming from, but the benefits are marginal
> (like the amount of userspace code that could be reused) and the
> effort huge in comparison.

The effort doesn't seem huge, so long as we don't try to make the parameters
common across vendor code. The list of APIs doesn't seem insurmountable (note,
I'm not entirely sure these are correct mappings):

create
init VM (LAUNCH_START / TDH.MNG.INIT)
update (LAUNCH_UPDATE_DATA / TDH.MEM.PAGE.ADD+TDH.MR.EXTEND)
init vCPU (LAUNCH_UPDATE_VMSA / TDH.VP.INIT)
finalize (LAUNCH_FINISH / TDH.MR.FINALIZE)