Message ID | 20220512031803.3315890-7-xiaoyao.li@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | TDX QEMU support | expand |
On Thu, May 12, 2022 at 11:17:33AM +0800, Xiaoyao Li <xiaoyao.li@intel.com> wrote: > KVM provides TDX capabilities via sub command KVM_TDX_CAPABILITIES of > IOCTL(KVM_MEMORY_ENCRYPT_OP). Get the capabilities when initializing > TDX context. It will be used to validate user's setting later. > > Besides, introduce the interfaces to invoke TDX "ioctls" at different > scope (KVM, VM and VCPU) in preparation. > > Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> > --- > target/i386/kvm/tdx.c | 85 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 85 insertions(+) > > diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c > index 77e33ae01147..68bedbad0ebe 100644 > --- a/target/i386/kvm/tdx.c > +++ b/target/i386/kvm/tdx.c > @@ -14,12 +14,97 @@ > #include "qemu/osdep.h" > #include "qapi/error.h" > #include "qom/object_interfaces.h" > +#include "sysemu/kvm.h" > > #include "hw/i386/x86.h" > #include "tdx.h" > > +enum tdx_ioctl_level{ > + TDX_PLATFORM_IOCTL, > + TDX_VM_IOCTL, > + TDX_VCPU_IOCTL, > +}; > + > +static int __tdx_ioctl(void *state, enum tdx_ioctl_level level, int cmd_id, > + __u32 flags, void *data) > +{ > + struct kvm_tdx_cmd tdx_cmd; > + int r; > + > + memset(&tdx_cmd, 0x0, sizeof(tdx_cmd)); > + > + tdx_cmd.id = cmd_id; > + tdx_cmd.flags = flags; > + tdx_cmd.data = (__u64)(unsigned long)data; > + > + switch (level) { > + case TDX_PLATFORM_IOCTL: > + r = kvm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); > + break; > + case TDX_VM_IOCTL: > + r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); > + break; > + case TDX_VCPU_IOCTL: > + r = kvm_vcpu_ioctl(state, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); > + break; > + default: > + error_report("Invalid tdx_ioctl_level %d", level); > + exit(1); > + } > + > + return r; > +} > + > +static inline int tdx_platform_ioctl(int cmd_id, __u32 metadata, void *data) nitpick: Because metadata was renamed to flags for clarity, please update those. > +{ > + return __tdx_ioctl(NULL, TDX_PLATFORM_IOCTL, cmd_id, metadata, data); > +} > + > +static inline int tdx_vm_ioctl(int cmd_id, __u32 metadata, void *data) > +{ > + return __tdx_ioctl(NULL, TDX_VM_IOCTL, cmd_id, metadata, data); > +} > + > +static inline int tdx_vcpu_ioctl(void *vcpu_fd, int cmd_id, __u32 metadata, > + void *data) > +{ > + return __tdx_ioctl(vcpu_fd, TDX_VCPU_IOCTL, cmd_id, metadata, data); > +} > + > +static struct kvm_tdx_capabilities *tdx_caps; > + > +static void get_tdx_capabilities(void) > +{ > + struct kvm_tdx_capabilities *caps; > + int max_ent = 1; Because we know the number of entries for TDX 1.0. We can start with better value with comment on it. > + int r, size; > + > + do { > + size = sizeof(struct kvm_tdx_capabilities) + > + max_ent * sizeof(struct kvm_tdx_cpuid_config); > + caps = g_malloc0(size); > + caps->nr_cpuid_configs = max_ent; > + > + r = tdx_platform_ioctl(KVM_TDX_CAPABILITIES, 0, caps); > + if (r == -E2BIG) { > + g_free(caps); > + max_ent *= 2; > + } else if (r < 0) { > + error_report("KVM_TDX_CAPABILITIES failed: %s\n", strerror(-r)); > + exit(1); > + } > + } > + while (r == -E2BIG); > + > + tdx_caps = caps; > +} > + > int tdx_kvm_init(MachineState *ms, Error **errp) > { > + if (!tdx_caps) { > + get_tdx_capabilities(); > + } > + > return 0; > } > > -- > 2.27.0 > >
Hi, > + do { > + size = sizeof(struct kvm_tdx_capabilities) + > + max_ent * sizeof(struct kvm_tdx_cpuid_config); > + caps = g_malloc0(size); > + caps->nr_cpuid_configs = max_ent; > + > + r = tdx_platform_ioctl(KVM_TDX_CAPABILITIES, 0, caps); > + if (r == -E2BIG) { > + g_free(caps); > + max_ent *= 2; > + } else if (r < 0) { > + error_report("KVM_TDX_CAPABILITIES failed: %s\n", strerror(-r)); > + exit(1); > + } > + } > + while (r == -E2BIG); This should have a limit for the number of loop runs. take care, Gerd
On 5/23/2022 4:45 PM, Gerd Hoffmann wrote: > Hi, > >> + do { >> + size = sizeof(struct kvm_tdx_capabilities) + >> + max_ent * sizeof(struct kvm_tdx_cpuid_config); >> + caps = g_malloc0(size); >> + caps->nr_cpuid_configs = max_ent; >> + >> + r = tdx_platform_ioctl(KVM_TDX_CAPABILITIES, 0, caps); >> + if (r == -E2BIG) { >> + g_free(caps); >> + max_ent *= 2; >> + } else if (r < 0) { >> + error_report("KVM_TDX_CAPABILITIES failed: %s\n", strerror(-r)); >> + exit(1); >> + } >> + } >> + while (r == -E2BIG); > > This should have a limit for the number of loop runs. Actually, this logic is copied from get_supported_cpuid(). Anyway, I can put a maximum limit as 256 (it should be large enough) or maybe re-use KVM_MAX_CPUID_ENTRIES. When it gets hit, we know we need to update QEMU to fit with TDX on new platform. > take care, > Gerd >
diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c index 77e33ae01147..68bedbad0ebe 100644 --- a/target/i386/kvm/tdx.c +++ b/target/i386/kvm/tdx.c @@ -14,12 +14,97 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qom/object_interfaces.h" +#include "sysemu/kvm.h" #include "hw/i386/x86.h" #include "tdx.h" +enum tdx_ioctl_level{ + TDX_PLATFORM_IOCTL, + TDX_VM_IOCTL, + TDX_VCPU_IOCTL, +}; + +static int __tdx_ioctl(void *state, enum tdx_ioctl_level level, int cmd_id, + __u32 flags, void *data) +{ + struct kvm_tdx_cmd tdx_cmd; + int r; + + memset(&tdx_cmd, 0x0, sizeof(tdx_cmd)); + + tdx_cmd.id = cmd_id; + tdx_cmd.flags = flags; + tdx_cmd.data = (__u64)(unsigned long)data; + + switch (level) { + case TDX_PLATFORM_IOCTL: + r = kvm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); + break; + case TDX_VM_IOCTL: + r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); + break; + case TDX_VCPU_IOCTL: + r = kvm_vcpu_ioctl(state, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); + break; + default: + error_report("Invalid tdx_ioctl_level %d", level); + exit(1); + } + + return r; +} + +static inline int tdx_platform_ioctl(int cmd_id, __u32 metadata, void *data) +{ + return __tdx_ioctl(NULL, TDX_PLATFORM_IOCTL, cmd_id, metadata, data); +} + +static inline int tdx_vm_ioctl(int cmd_id, __u32 metadata, void *data) +{ + return __tdx_ioctl(NULL, TDX_VM_IOCTL, cmd_id, metadata, data); +} + +static inline int tdx_vcpu_ioctl(void *vcpu_fd, int cmd_id, __u32 metadata, + void *data) +{ + return __tdx_ioctl(vcpu_fd, TDX_VCPU_IOCTL, cmd_id, metadata, data); +} + +static struct kvm_tdx_capabilities *tdx_caps; + +static void get_tdx_capabilities(void) +{ + struct kvm_tdx_capabilities *caps; + int max_ent = 1; + int r, size; + + do { + size = sizeof(struct kvm_tdx_capabilities) + + max_ent * sizeof(struct kvm_tdx_cpuid_config); + caps = g_malloc0(size); + caps->nr_cpuid_configs = max_ent; + + r = tdx_platform_ioctl(KVM_TDX_CAPABILITIES, 0, caps); + if (r == -E2BIG) { + g_free(caps); + max_ent *= 2; + } else if (r < 0) { + error_report("KVM_TDX_CAPABILITIES failed: %s\n", strerror(-r)); + exit(1); + } + } + while (r == -E2BIG); + + tdx_caps = caps; +} + int tdx_kvm_init(MachineState *ms, Error **errp) { + if (!tdx_caps) { + get_tdx_capabilities(); + } + return 0; }
KVM provides TDX capabilities via sub command KVM_TDX_CAPABILITIES of IOCTL(KVM_MEMORY_ENCRYPT_OP). Get the capabilities when initializing TDX context. It will be used to validate user's setting later. Besides, introduce the interfaces to invoke TDX "ioctls" at different scope (KVM, VM and VCPU) in preparation. Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> --- target/i386/kvm/tdx.c | 85 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+)