[PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization

Rick Edgecombe posted 25 patches 1 year, 3 months ago
[PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Rick Edgecombe 1 year, 3 months ago
From: Isaku Yamahata <isaku.yamahata@intel.com>

TDX KVM needs system-wide information about the TDX module. Generate the
data based on tdx_sysinfo td_conf CPUID data.

Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Co-developed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Signed-off-by: Xiaoyao Li <xiaoyao.li@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>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
---
uAPI breakout v2:
 - Update stale patch description (Binbin)
 - Add KVM_TDX_CAPABILITIES where it's first used (Binbin)
 - Drop Drop unused KVM_TDX_CPUID_NO_SUBLEAF (Chao)
 - Drop mmu.h, it's only needed in later patches (Binbin)
 - Fold in Xiaoyao's capabilities changes (Tony)
 - Generate data without struct kvm_tdx_caps (Tony)
 - Use struct kvm_cpuid_entry2 as suggested (Binbin)
 - Use helpers for phys_addr_bits (Paolo)
 - Check TDX and KVM capabilities on _tdx_bringup() (Xiaoyao)
 - Change code around cpuid_config_value since
   struct tdx_cpuid_config_value {} is removed (Kai)

uAPI breakout v1:
 - Mention about hardware_unsetup(). (Binbin)
 - Added Reviewed-by. (Binbin)
 - Eliminated tdx_md_read(). (Kai)
 - Include "x86_ops.h" to tdx.c as the patch to initialize TDX module
   doesn't include it anymore.
 - Introduce tdx_vm_ioctl() as the first tdx func in x86_ops.h

v19:
 - Added features0
 - Use tdx_sys_metadata_read()
 - Fix error recovery path by Yuan

Change v18:
 - Newly Added
---
 arch/x86/include/uapi/asm/kvm.h |   9 +++
 arch/x86/kvm/vmx/tdx.c          | 137 ++++++++++++++++++++++++++++++++
 2 files changed, 146 insertions(+)

diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index b6cb87f2b477..0630530af334 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -928,6 +928,8 @@ struct kvm_hyperv_eventfd {
 
 /* Trust Domain eXtension sub-ioctl() commands. */
 enum kvm_tdx_cmd_id {
+	KVM_TDX_CAPABILITIES = 0,
+
 	KVM_TDX_CMD_NR_MAX,
 };
 
@@ -950,4 +952,11 @@ struct kvm_tdx_cmd {
 	__u64 hw_error;
 };
 
+struct kvm_tdx_capabilities {
+	__u64 supported_attrs;
+	__u64 supported_xfam;
+	__u64 reserved[254];
+	struct kvm_cpuid2 cpuid;
+};
+
 #endif /* _ASM_X86_KVM_H */
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index 76655d82f749..253debbe685f 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -30,6 +30,134 @@ static enum cpuhp_state tdx_cpuhp_state;
 
 static const struct tdx_sys_info *tdx_sysinfo;
 
+#define KVM_SUPPORTED_TD_ATTRS (TDX_TD_ATTR_SEPT_VE_DISABLE)
+
+static u64 tdx_get_supported_attrs(const struct tdx_sys_info_td_conf *td_conf)
+{
+	u64 val = KVM_SUPPORTED_TD_ATTRS;
+
+	if ((val & td_conf->attributes_fixed1) != td_conf->attributes_fixed1)
+		return 0;
+
+	val &= td_conf->attributes_fixed0;
+
+	return val;
+}
+
+static u64 tdx_get_supported_xfam(const struct tdx_sys_info_td_conf *td_conf)
+{
+	u64 val = kvm_caps.supported_xcr0 | kvm_caps.supported_xss;
+
+	/*
+	 * PT and CET can be exposed to TD guest regardless of KVM's XSS, PT
+	 * and, CET support.
+	 */
+	val |= XFEATURE_MASK_PT | XFEATURE_MASK_CET_USER |
+	       XFEATURE_MASK_CET_KERNEL;
+
+	if ((val & td_conf->xfam_fixed1) != td_conf->xfam_fixed1)
+		return 0;
+
+	val &= td_conf->xfam_fixed0;
+
+	return val;
+}
+
+static u32 tdx_set_guest_phys_addr_bits(const u32 eax, int addr_bits)
+{
+	return (eax & ~GENMASK(23, 16)) | (addr_bits & 0xff) << 16;
+}
+
+#define KVM_TDX_CPUID_NO_SUBLEAF	((__u32)-1)
+
+static void td_init_cpuid_entry2(struct kvm_cpuid_entry2 *entry, unsigned char idx)
+{
+	const struct tdx_sys_info_td_conf *td_conf = &tdx_sysinfo->td_conf;
+
+	entry->function = (u32)td_conf->cpuid_config_leaves[idx];
+	entry->index = td_conf->cpuid_config_leaves[idx] >> 32;
+	entry->eax = (u32)td_conf->cpuid_config_values[idx][0];
+	entry->ebx = td_conf->cpuid_config_values[idx][0] >> 32;
+	entry->ecx = (u32)td_conf->cpuid_config_values[idx][1];
+	entry->edx = td_conf->cpuid_config_values[idx][1] >> 32;
+
+	if (entry->index == KVM_TDX_CPUID_NO_SUBLEAF)
+		entry->index = 0;
+
+	/* Work around missing support on old TDX modules */
+	if (entry->function == 0x80000008)
+		entry->eax = tdx_set_guest_phys_addr_bits(entry->eax, 0xff);
+}
+
+static int init_kvm_tdx_caps(const struct tdx_sys_info_td_conf *td_conf,
+			     struct kvm_tdx_capabilities *caps)
+{
+	int i;
+
+	caps->supported_attrs = tdx_get_supported_attrs(td_conf);
+	if (!caps->supported_attrs)
+		return -EIO;
+
+	caps->supported_xfam = tdx_get_supported_xfam(td_conf);
+	if (!caps->supported_xfam)
+		return -EIO;
+
+	caps->cpuid.nent = td_conf->num_cpuid_config;
+
+	for (i = 0; i < td_conf->num_cpuid_config; i++)
+		td_init_cpuid_entry2(&caps->cpuid.entries[i], i);
+
+	return 0;
+}
+
+static int tdx_get_capabilities(struct kvm_tdx_cmd *cmd)
+{
+	const struct tdx_sys_info_td_conf *td_conf = &tdx_sysinfo->td_conf;
+	struct kvm_tdx_capabilities __user *user_caps;
+	struct kvm_tdx_capabilities *caps = NULL;
+	int ret = 0;
+
+	/* flags is reserved for future use */
+	if (cmd->flags)
+		return -EINVAL;
+
+	caps = kmalloc(sizeof(*caps) +
+		       sizeof(struct kvm_cpuid_entry2) * td_conf->num_cpuid_config,
+		       GFP_KERNEL);
+	if (!caps)
+		return -ENOMEM;
+
+	user_caps = u64_to_user_ptr(cmd->data);
+	if (copy_from_user(caps, user_caps, sizeof(*caps))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (caps->cpuid.nent < td_conf->num_cpuid_config) {
+		ret = -E2BIG;
+		goto out;
+	}
+
+	ret = init_kvm_tdx_caps(td_conf, caps);
+	if (ret)
+		goto out;
+
+	if (copy_to_user(user_caps, caps, sizeof(*caps))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (copy_to_user(user_caps->cpuid.entries, caps->cpuid.entries,
+			 caps->cpuid.nent *
+			 sizeof(caps->cpuid.entries[0])))
+		ret = -EFAULT;
+
+out:
+	/* kfree() accepts NULL. */
+	kfree(caps);
+	return ret;
+}
+
 int tdx_vm_ioctl(struct kvm *kvm, void __user *argp)
 {
 	struct kvm_tdx_cmd tdx_cmd;
@@ -48,6 +176,9 @@ int tdx_vm_ioctl(struct kvm *kvm, void __user *argp)
 	mutex_lock(&kvm->lock);
 
 	switch (tdx_cmd.id) {
+	case KVM_TDX_CAPABILITIES:
+		r = tdx_get_capabilities(&tdx_cmd);
+		break;
 	default:
 		r = -EINVAL;
 		goto out;
@@ -147,11 +278,17 @@ static int __init __tdx_bringup(void)
 		goto get_sysinfo_err;
 	}
 
+	/* Check TDX module and KVM capabilities */
+	if (!tdx_get_supported_attrs(&tdx_sysinfo->td_conf) ||
+	    !tdx_get_supported_xfam(&tdx_sysinfo->td_conf))
+		goto get_sysinfo_err;
+
 	/*
 	 * Leave hardware virtualization enabled after TDX is enabled
 	 * successfully.  TDX CPU hotplug depends on this.
 	 */
 	return 0;
+
 get_sysinfo_err:
 	__do_tdx_cleanup();
 tdx_bringup_err:
-- 
2.47.0
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Chao Gao 1 year, 1 month ago
>@@ -147,11 +278,17 @@ static int __init __tdx_bringup(void)
> 		goto get_sysinfo_err;
> 	}
> 
>+	/* Check TDX module and KVM capabilities */
>+	if (!tdx_get_supported_attrs(&tdx_sysinfo->td_conf) ||
>+	    !tdx_get_supported_xfam(&tdx_sysinfo->td_conf))
>+		goto get_sysinfo_err;

The return value should be set to -EINVAL before the goto.

>+
> 	/*
> 	 * Leave hardware virtualization enabled after TDX is enabled
> 	 * successfully.  TDX CPU hotplug depends on this.
> 	 */
> 	return 0;
>+
> get_sysinfo_err:
> 	__do_tdx_cleanup();
> tdx_bringup_err:
>-- 
>2.47.0
>
>
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Huang, Kai 1 year, 1 month ago
On Wed, 2025-01-08 at 10:34 +0800, Gao, Chao wrote:
> > @@ -147,11 +278,17 @@ static int __init __tdx_bringup(void)
> > 		goto get_sysinfo_err;
> > 	}
> > 
> > +	/* Check TDX module and KVM capabilities */
> > +	if (!tdx_get_supported_attrs(&tdx_sysinfo->td_conf) ||
> > +	    !tdx_get_supported_xfam(&tdx_sysinfo->td_conf))
> > +		goto get_sysinfo_err;
> 
> The return value should be set to -EINVAL before the goto.
> 

Yeah.  Sean actually pointed this out before.  I proposed internally to do below
change to the patch "[PATCH v2 02/25] KVM: TDX: Get TDX global information":

--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -3274,12 +3274,11 @@ static int __init __tdx_bringup(void)
        if (r)
                goto tdx_bringup_err;
 
+       r = -EINVAL;
        /* Get TDX global information for later use */
        tdx_sysinfo = tdx_get_sysinfo();
-       if (WARN_ON_ONCE(!tdx_sysinfo)) {
-               r = -EINVAL;
+       if (WARN_ON_ONCE(!tdx_sysinfo))
                goto get_sysinfo_err;
-       }

.. so that further failures can just 'goto <err_label>'.  I.e., below should be
done to the patch "[PATCH v2 18/25] KVM: TDX: Support per-VM KVM_CAP_MAX_VCPUS
extension check":

        /* Check TDX module and KVM capabilities */
        if (!tdx_get_supported_attrs(&tdx_sysinfo->td_conf) ||
@@ -3319,7 +3318,6 @@ static int __init __tdx_bringup(void)
        if (td_conf->max_vcpus_per_td < num_present_cpus()) {
                pr_err("Disable TDX: MAX_VCPU_PER_TD (%u) smaller than number of
logical CPUs (%u).\n",
                                td_conf->max_vcpus_per_td, num_present_cpus());
-               r = -EINVAL;
                goto get_sysinfo_err;
        }

Alternatively, we can just set ret to -EINVAL before the goto which is a simple
fix to this patch, which probably is easier for Paolo to do.
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Xiaoyao Li 1 year, 2 months ago
On 10/31/2024 3:00 AM, Rick Edgecombe wrote:
> From: Isaku Yamahata <isaku.yamahata@intel.com>
> 
> TDX KVM needs system-wide information about the TDX module. Generate the
> data based on tdx_sysinfo td_conf CPUID data.
> 
> Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
> Co-developed-by: Xiaoyao Li <xiaoyao.li@intel.com>
> Signed-off-by: Xiaoyao Li <xiaoyao.li@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>
> Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
> ---
> uAPI breakout v2:
>   - Update stale patch description (Binbin)
>   - Add KVM_TDX_CAPABILITIES where it's first used (Binbin)
>   - Drop Drop unused KVM_TDX_CPUID_NO_SUBLEAF (Chao)
>   - Drop mmu.h, it's only needed in later patches (Binbin)
>   - Fold in Xiaoyao's capabilities changes (Tony)
>   - Generate data without struct kvm_tdx_caps (Tony)
>   - Use struct kvm_cpuid_entry2 as suggested (Binbin)
>   - Use helpers for phys_addr_bits (Paolo)
>   - Check TDX and KVM capabilities on _tdx_bringup() (Xiaoyao)
>   - Change code around cpuid_config_value since
>     struct tdx_cpuid_config_value {} is removed (Kai)
> 
> uAPI breakout v1:
>   - Mention about hardware_unsetup(). (Binbin)
>   - Added Reviewed-by. (Binbin)
>   - Eliminated tdx_md_read(). (Kai)
>   - Include "x86_ops.h" to tdx.c as the patch to initialize TDX module
>     doesn't include it anymore.
>   - Introduce tdx_vm_ioctl() as the first tdx func in x86_ops.h
> 
> v19:
>   - Added features0
>   - Use tdx_sys_metadata_read()
>   - Fix error recovery path by Yuan
> 
> Change v18:
>   - Newly Added
> ---
>   arch/x86/include/uapi/asm/kvm.h |   9 +++
>   arch/x86/kvm/vmx/tdx.c          | 137 ++++++++++++++++++++++++++++++++
>   2 files changed, 146 insertions(+)
> 
> diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
> index b6cb87f2b477..0630530af334 100644
> --- a/arch/x86/include/uapi/asm/kvm.h
> +++ b/arch/x86/include/uapi/asm/kvm.h
> @@ -928,6 +928,8 @@ struct kvm_hyperv_eventfd {
>   
>   /* Trust Domain eXtension sub-ioctl() commands. */
>   enum kvm_tdx_cmd_id {
> +	KVM_TDX_CAPABILITIES = 0,
> +
>   	KVM_TDX_CMD_NR_MAX,
>   };
>   
> @@ -950,4 +952,11 @@ struct kvm_tdx_cmd {
>   	__u64 hw_error;
>   };
>   
> +struct kvm_tdx_capabilities {
> +	__u64 supported_attrs;
> +	__u64 supported_xfam;
> +	__u64 reserved[254];
> +	struct kvm_cpuid2 cpuid;

Could we rename it to "configurable_cpuid" to call out that it only 
reports the bits that are allowable for userspace to configure at 0 or 1 
at will.

If could we can even add a comment of

	/*
          * Bit of value 1 means the bit is free to be configured as
          * 0/1 by userspace VMM.
          * The value 0 only means the bit is not configurable, while
          * the actual value of it depends on TDX module/KVM
          * implementation.
          */
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Tony Lindgren 1 year, 2 months ago
On Fri, Dec 06, 2024 at 04:45:01PM +0800, Xiaoyao Li wrote:
> On 10/31/2024 3:00 AM, Rick Edgecombe wrote:
> > --- a/arch/x86/include/uapi/asm/kvm.h
> > +++ b/arch/x86/include/uapi/asm/kvm.h
> > @@ -928,6 +928,8 @@ struct kvm_hyperv_eventfd {
> >   /* Trust Domain eXtension sub-ioctl() commands. */
> >   enum kvm_tdx_cmd_id {
> > +	KVM_TDX_CAPABILITIES = 0,
> > +
> >   	KVM_TDX_CMD_NR_MAX,
> >   };
> > @@ -950,4 +952,11 @@ struct kvm_tdx_cmd {
> >   	__u64 hw_error;
> >   };
> > +struct kvm_tdx_capabilities {
> > +	__u64 supported_attrs;
> > +	__u64 supported_xfam;
> > +	__u64 reserved[254];
> > +	struct kvm_cpuid2 cpuid;
> 
> Could we rename it to "configurable_cpuid" to call out that it only reports
> the bits that are allowable for userspace to configure at 0 or 1 at will.

Well it's already in the capabilities struct.. So to me it seems like just
adding a comment should do the trick.

Regards,

Tony
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Binbin Wu 1 year, 3 months ago


On 10/31/2024 3:00 AM, Rick Edgecombe wrote:
[...]
> +static u32 tdx_set_guest_phys_addr_bits(const u32 eax, int addr_bits)
> +{
> +	return (eax & ~GENMASK(23, 16)) | (addr_bits & 0xff) << 16;
> +}
> +
> +#define KVM_TDX_CPUID_NO_SUBLEAF	((__u32)-1)
> +
> +static void td_init_cpuid_entry2(struct kvm_cpuid_entry2 *entry, unsigned char idx)
> +{
> +	const struct tdx_sys_info_td_conf *td_conf = &tdx_sysinfo->td_conf;
> +
> +	entry->function = (u32)td_conf->cpuid_config_leaves[idx];
> +	entry->index = td_conf->cpuid_config_leaves[idx] >> 32;
> +	entry->eax = (u32)td_conf->cpuid_config_values[idx][0];
> +	entry->ebx = td_conf->cpuid_config_values[idx][0] >> 32;
> +	entry->ecx = (u32)td_conf->cpuid_config_values[idx][1];
> +	entry->edx = td_conf->cpuid_config_values[idx][1] >> 32;
> +
> +	if (entry->index == KVM_TDX_CPUID_NO_SUBLEAF)
> +		entry->index = 0;
> +
> +	/* Work around missing support on old TDX modules */
> +	if (entry->function == 0x80000008)
> +		entry->eax = tdx_set_guest_phys_addr_bits(entry->eax, 0xff);
Is it necessary to set bit 16~23 to 0xff?
It seems that when userspace wants to retrieve the value, the GPAW will
be set in tdx_read_cpuid() anyway.

> +}
> +
>
[...]
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Xiaoyao Li 1 year, 3 months ago
On 10/31/2024 5:09 PM, Binbin Wu wrote:
> 
> 
> 
> On 10/31/2024 3:00 AM, Rick Edgecombe wrote:
> [...]
>> +static u32 tdx_set_guest_phys_addr_bits(const u32 eax, int addr_bits)
>> +{
>> +    return (eax & ~GENMASK(23, 16)) | (addr_bits & 0xff) << 16;
>> +}
>> +
>> +#define KVM_TDX_CPUID_NO_SUBLEAF    ((__u32)-1)
>> +
>> +static void td_init_cpuid_entry2(struct kvm_cpuid_entry2 *entry, 
>> unsigned char idx)
>> +{
>> +    const struct tdx_sys_info_td_conf *td_conf = &tdx_sysinfo->td_conf;
>> +
>> +    entry->function = (u32)td_conf->cpuid_config_leaves[idx];
>> +    entry->index = td_conf->cpuid_config_leaves[idx] >> 32;
>> +    entry->eax = (u32)td_conf->cpuid_config_values[idx][0];
>> +    entry->ebx = td_conf->cpuid_config_values[idx][0] >> 32;
>> +    entry->ecx = (u32)td_conf->cpuid_config_values[idx][1];
>> +    entry->edx = td_conf->cpuid_config_values[idx][1] >> 32;
>> +
>> +    if (entry->index == KVM_TDX_CPUID_NO_SUBLEAF)
>> +        entry->index = 0;
>> +
>> +    /* Work around missing support on old TDX modules */
>> +    if (entry->function == 0x80000008)
>> +        entry->eax = tdx_set_guest_phys_addr_bits(entry->eax, 0xff);
> Is it necessary to set bit 16~23 to 0xff?
> It seems that when userspace wants to retrieve the value, the GPAW will
> be set in tdx_read_cpuid() anyway.

here it is to initialize the configurable CPUID bits that get reported 
to userspace. Though TDX module doesn't allow them to be set in TD_PARAM 
for KVM_TDX_INIT_VM, they get set to 0xff because KVM reuse these bits 
EBX[23:16] as the interface for userspace to configure GPAW of TD guest 
(implemented in setup_tdparams_eptp_controls() in patch 19). That's why 
they need to be set as all-1 to allow userspace to configure.

And the comment above it is wrong and vague. we need to change it to 
something like

	/*
          * Though TDX module doesn't allow the configuration of guest
          * phys addr bits (EBX[23:16]), KVM uses it as the interface for
          * userspace to configure the GPAW. So need to report these bits
          * as configurable to userspace.
          */
>> +}
>> +
>>
> [...]

Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Tony Lindgren 1 year, 3 months ago
On Thu, Oct 31, 2024 at 05:23:57PM +0800, Xiaoyao Li wrote:
> here it is to initialize the configurable CPUID bits that get reported to
> userspace. Though TDX module doesn't allow them to be set in TD_PARAM for
> KVM_TDX_INIT_VM, they get set to 0xff because KVM reuse these bits
> EBX[23:16] as the interface for userspace to configure GPAW of TD guest
> (implemented in setup_tdparams_eptp_controls() in patch 19). That's why they
> need to be set as all-1 to allow userspace to configure.
> 
> And the comment above it is wrong and vague. we need to change it to
> something like
> 
> 	/*
>          * Though TDX module doesn't allow the configuration of guest
>          * phys addr bits (EBX[23:16]), KVM uses it as the interface for
>          * userspace to configure the GPAW. So need to report these bits
>          * as configurable to userspace.
>          */

That sounds good to me.

Hmm so care to check if we can also just leave out another "old module"
comment in tdx_read_cpuid()?

Regards,

Tony
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Xiaoyao Li 1 year, 3 months ago
On 10/31/2024 5:37 PM, Tony Lindgren wrote:
> On Thu, Oct 31, 2024 at 05:23:57PM +0800, Xiaoyao Li wrote:
>> here it is to initialize the configurable CPUID bits that get reported to
>> userspace. Though TDX module doesn't allow them to be set in TD_PARAM for
>> KVM_TDX_INIT_VM, they get set to 0xff because KVM reuse these bits
>> EBX[23:16] as the interface for userspace to configure GPAW of TD guest
>> (implemented in setup_tdparams_eptp_controls() in patch 19). That's why they
>> need to be set as all-1 to allow userspace to configure.
>>
>> And the comment above it is wrong and vague. we need to change it to
>> something like
>>
>> 	/*
>>           * Though TDX module doesn't allow the configuration of guest
>>           * phys addr bits (EBX[23:16]), KVM uses it as the interface for
>>           * userspace to configure the GPAW. So need to report these bits
>>           * as configurable to userspace.
>>           */
> 
> That sounds good to me.
> 
> Hmm so care to check if we can also just leave out another "old module"
> comment in tdx_read_cpuid()?

That one did relate to old module, the module that without 
TDX_CONFIG_FLAGS_MAXGPA_VIRT reported in tdx_feature0.

I will sent an follow up patch to complement the handling if TDX module 
supports TDX_CONFIG_FLAGS_MAXGPA_VIRT.

> Regards,
> 
> Tony
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Tony Lindgren 1 year, 3 months ago
On Thu, Oct 31, 2024 at 10:27:11PM +0800, Xiaoyao Li wrote:
> On 10/31/2024 5:37 PM, Tony Lindgren wrote:
> > On Thu, Oct 31, 2024 at 05:23:57PM +0800, Xiaoyao Li wrote:
> > > here it is to initialize the configurable CPUID bits that get reported to
> > > userspace. Though TDX module doesn't allow them to be set in TD_PARAM for
> > > KVM_TDX_INIT_VM, they get set to 0xff because KVM reuse these bits
> > > EBX[23:16] as the interface for userspace to configure GPAW of TD guest
> > > (implemented in setup_tdparams_eptp_controls() in patch 19). That's why they
> > > need to be set as all-1 to allow userspace to configure.
> > > 
> > > And the comment above it is wrong and vague. we need to change it to
> > > something like
> > > 
> > > 	/*
> > >           * Though TDX module doesn't allow the configuration of guest
> > >           * phys addr bits (EBX[23:16]), KVM uses it as the interface for
> > >           * userspace to configure the GPAW. So need to report these bits
> > >           * as configurable to userspace.
> > >           */
> > 
> > That sounds good to me.
> > 
> > Hmm so care to check if we can also just leave out another "old module"
> > comment in tdx_read_cpuid()?
> 
> That one did relate to old module, the module that without
> TDX_CONFIG_FLAGS_MAXGPA_VIRT reported in tdx_feature0.

OK thanks for checking.

> I will sent an follow up patch to complement the handling if TDX module
> supports TDX_CONFIG_FLAGS_MAXGPA_VIRT.

OK

Regards,

Tony
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Tony Lindgren 1 year, 3 months ago
On Thu, Oct 31, 2024 at 05:09:17PM +0800, Binbin Wu wrote:
> 
> 
> 
> On 10/31/2024 3:00 AM, Rick Edgecombe wrote:
> [...]
> > +static u32 tdx_set_guest_phys_addr_bits(const u32 eax, int addr_bits)
> > +{
> > +	return (eax & ~GENMASK(23, 16)) | (addr_bits & 0xff) << 16;
> > +}
> > +
> > +#define KVM_TDX_CPUID_NO_SUBLEAF	((__u32)-1)
> > +
> > +static void td_init_cpuid_entry2(struct kvm_cpuid_entry2 *entry, unsigned char idx)
> > +{
> > +	const struct tdx_sys_info_td_conf *td_conf = &tdx_sysinfo->td_conf;
> > +
> > +	entry->function = (u32)td_conf->cpuid_config_leaves[idx];
> > +	entry->index = td_conf->cpuid_config_leaves[idx] >> 32;
> > +	entry->eax = (u32)td_conf->cpuid_config_values[idx][0];
> > +	entry->ebx = td_conf->cpuid_config_values[idx][0] >> 32;
> > +	entry->ecx = (u32)td_conf->cpuid_config_values[idx][1];
> > +	entry->edx = td_conf->cpuid_config_values[idx][1] >> 32;
> > +
> > +	if (entry->index == KVM_TDX_CPUID_NO_SUBLEAF)
> > +		entry->index = 0;
> > +
> > +	/* Work around missing support on old TDX modules */
> > +	if (entry->function == 0x80000008)
> > +		entry->eax = tdx_set_guest_phys_addr_bits(entry->eax, 0xff);
> Is it necessary to set bit 16~23 to 0xff?
> It seems that when userspace wants to retrieve the value, the GPAW will
> be set in tdx_read_cpuid() anyway.

Leaving it out currently produces:

qemu-system-x86_64: KVM_TDX_INIT_VM failed: Invalid argument

Regards,

Tony
Re: [PATCH v2 16/25] KVM: TDX: Get system-wide info about TDX module on initialization
Posted by Binbin Wu 1 year, 3 months ago


On 10/31/2024 5:18 PM, Tony Lindgren wrote:
> On Thu, Oct 31, 2024 at 05:09:17PM +0800, Binbin Wu wrote:
>>
>>
>> On 10/31/2024 3:00 AM, Rick Edgecombe wrote:
>> [...]
>>> +static u32 tdx_set_guest_phys_addr_bits(const u32 eax, int addr_bits)
>>> +{
>>> +	return (eax & ~GENMASK(23, 16)) | (addr_bits & 0xff) << 16;
>>> +}
>>> +
>>> +#define KVM_TDX_CPUID_NO_SUBLEAF	((__u32)-1)
>>> +
>>> +static void td_init_cpuid_entry2(struct kvm_cpuid_entry2 *entry, unsigned char idx)
>>> +{
>>> +	const struct tdx_sys_info_td_conf *td_conf = &tdx_sysinfo->td_conf;
>>> +
>>> +	entry->function = (u32)td_conf->cpuid_config_leaves[idx];
>>> +	entry->index = td_conf->cpuid_config_leaves[idx] >> 32;
>>> +	entry->eax = (u32)td_conf->cpuid_config_values[idx][0];
>>> +	entry->ebx = td_conf->cpuid_config_values[idx][0] >> 32;
>>> +	entry->ecx = (u32)td_conf->cpuid_config_values[idx][1];
>>> +	entry->edx = td_conf->cpuid_config_values[idx][1] >> 32;
>>> +
>>> +	if (entry->index == KVM_TDX_CPUID_NO_SUBLEAF)
>>> +		entry->index = 0;
>>> +
>>> +	/* Work around missing support on old TDX modules */
>>> +	if (entry->function == 0x80000008)
>>> +		entry->eax = tdx_set_guest_phys_addr_bits(entry->eax, 0xff);
>> Is it necessary to set bit 16~23 to 0xff?
>> It seems that when userspace wants to retrieve the value, the GPAW will
>> be set in tdx_read_cpuid() anyway.
> Leaving it out currently produces:
>
> qemu-system-x86_64: KVM_TDX_INIT_VM failed: Invalid argument
Yes, I forgot that userspace would use the value as the mask to filter cpuid.


>
> Regards,
>
> Tony