KVM: TDX: Add place holder for TDX VM specific mem_enc_op ioctl
authorIsaku Yamahata <isaku.yamahata@intel.com>
Wed, 30 Oct 2024 19:00:28 +0000 (12:00 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 14 Mar 2025 18:20:50 +0000 (14:20 -0400)
KVM_MEMORY_ENCRYPT_OP was introduced for VM-scoped operations specific for
guest state-protected VM.  It defined subcommands for technology-specific
operations under KVM_MEMORY_ENCRYPT_OP.  Despite its name, the subcommands
are not limited to memory encryption, but various technology-specific
operations are defined.  It's natural to repurpose KVM_MEMORY_ENCRYPT_OP
for TDX specific operations and define subcommands.

Add a place holder function for TDX specific VM-scoped ioctl as mem_enc_op.
TDX specific sub-commands will be added to retrieve/pass TDX specific
parameters.  Make mem_enc_ioctl non-optional as it's always filled.

Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Co-developed-by: Tony Lindgren <tony.lindgren@linux.intel.com>
Signed-off-by: Tony Lindgren <tony.lindgren@linux.intel.com>
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
---
 - Drop the misleading "defined for consistency" line. It's a copy-paste
   error introduced in the earlier patches. Earlier there was padding at
   the end to match struct kvm_sev_cmd size. (Tony)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/kvm-x86-ops.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/kvm/vmx/main.c
arch/x86/kvm/vmx/tdx.c
arch/x86/kvm/vmx/x86_ops.h
arch/x86/kvm/x86.c

index 823c0434bbad111593c34e5a6bf9e9778264bfa6..1eca04087cf4f4ddaddc6bd29e444ed15fb6ef31 100644 (file)
@@ -125,7 +125,7 @@ KVM_X86_OP(leave_smm)
 KVM_X86_OP(enable_smi_window)
 #endif
 KVM_X86_OP_OPTIONAL(dev_get_attr)
-KVM_X86_OP_OPTIONAL(mem_enc_ioctl)
+KVM_X86_OP(mem_enc_ioctl)
 KVM_X86_OP_OPTIONAL(mem_enc_register_region)
 KVM_X86_OP_OPTIONAL(mem_enc_unregister_region)
 KVM_X86_OP_OPTIONAL(vm_copy_enc_context_from)
index 9e75da97bce070a9054e678d951426d4ae072db6..2b0317b47e4752f87d1fd94c086ca1dbddd13497 100644 (file)
@@ -927,4 +927,27 @@ struct kvm_hyperv_eventfd {
 #define KVM_X86_SNP_VM         4
 #define KVM_X86_TDX_VM         5
 
+/* Trust Domain eXtension sub-ioctl() commands. */
+enum kvm_tdx_cmd_id {
+       KVM_TDX_CMD_NR_MAX,
+};
+
+struct kvm_tdx_cmd {
+       /* enum kvm_tdx_cmd_id */
+       __u32 id;
+       /* flags for sub-commend. If sub-command doesn't use this, set zero. */
+       __u32 flags;
+       /*
+        * data for each sub-command. An immediate or a pointer to the actual
+        * data in process virtual address.  If sub-command doesn't use it,
+        * set zero.
+        */
+       __u64 data;
+       /*
+        * Auxiliary error code.  The sub-command may return TDX SEAMCALL
+        * status code in addition to -Exxx.
+        */
+       __u64 hw_error;
+};
+
 #endif /* _ASM_X86_KVM_H */
index 5c1acc88feefe35f3982bb1251069b1f4a3ea25f..69c65085f81acaaf24dcfd0542e5404303d40991 100644 (file)
@@ -41,6 +41,14 @@ static __init int vt_hardware_setup(void)
        return 0;
 }
 
+static int vt_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
+{
+       if (!is_td(kvm))
+               return -ENOTTY;
+
+       return tdx_vm_ioctl(kvm, argp);
+}
+
 #define VMX_REQUIRED_APICV_INHIBITS                            \
        (BIT(APICV_INHIBIT_REASON_DISABLED) |                   \
         BIT(APICV_INHIBIT_REASON_ABSENT) |                     \
@@ -193,6 +201,8 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
        .vcpu_deliver_sipi_vector = kvm_vcpu_deliver_sipi_vector,
 
        .get_untagged_addr = vmx_get_untagged_addr,
+
+       .mem_enc_ioctl = vt_mem_enc_ioctl,
 };
 
 struct kvm_x86_init_ops vt_init_ops __initdata = {
index 8928b27547c1031280f5e67f9356bf51c149f09f..a20de9db315fdb92f1b9f995a7335b7f2636914c 100644 (file)
@@ -3,6 +3,7 @@
 #include <asm/cpufeature.h>
 #include <asm/tdx.h>
 #include "capabilities.h"
+#include "x86_ops.h"
 #include "tdx.h"
 
 #pragma GCC poison to_vmx
@@ -42,6 +43,37 @@ static __always_inline struct vcpu_tdx *to_tdx(struct kvm_vcpu *vcpu)
        return container_of(vcpu, struct vcpu_tdx, vcpu);
 }
 
+int tdx_vm_ioctl(struct kvm *kvm, void __user *argp)
+{
+       struct kvm_tdx_cmd tdx_cmd;
+       int r;
+
+       if (copy_from_user(&tdx_cmd, argp, sizeof(struct kvm_tdx_cmd)))
+               return -EFAULT;
+
+       /*
+        * Userspace should never set hw_error. It is used to fill
+        * hardware-defined error by the kernel.
+        */
+       if (tdx_cmd.hw_error)
+               return -EINVAL;
+
+       mutex_lock(&kvm->lock);
+
+       switch (tdx_cmd.id) {
+       default:
+               r = -EINVAL;
+               goto out;
+       }
+
+       if (copy_to_user(argp, &tdx_cmd, sizeof(struct kvm_tdx_cmd)))
+               r = -EFAULT;
+
+out:
+       mutex_unlock(&kvm->lock);
+       return r;
+}
+
 static int tdx_online_cpu(unsigned int cpu)
 {
        unsigned long flags;
index 430773a5ef8e3ecab141bea52cf26ed84111576c..75e0ca29a39e0b727f208373260f273dbea34fb7 100644 (file)
@@ -121,4 +121,10 @@ void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu);
 #endif
 void vmx_setup_mce(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_INTEL_TDX
+int tdx_vm_ioctl(struct kvm *kvm, void __user *argp);
+#else
+static inline int tdx_vm_ioctl(struct kvm *kvm, void __user *argp) { return -EOPNOTSUPP; }
+#endif
+
 #endif /* __KVM_X86_VMX_X86_OPS_H */
index eceb97734646ca1fdedc12c07f20b5c9ac988ef4..2434da7ac973721e22d0d1393fb0aa18eb1f741d 100644 (file)
@@ -7289,10 +7289,6 @@ set_pit2_out:
                goto out;
        }
        case KVM_MEMORY_ENCRYPT_OP: {
-               r = -ENOTTY;
-               if (!kvm_x86_ops.mem_enc_ioctl)
-                       goto out;
-
                r = kvm_x86_call(mem_enc_ioctl)(kvm, argp);
                break;
        }