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
>@@ -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 > >
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.
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.
*/
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
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.
> +}
> +
>
[...]
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.
*/
>> +}
>> +
>>
> [...]
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
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
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
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
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
© 2016 - 2026 Red Hat, Inc.