linux/arch/x86/include/asm/tdx_global_metadata.h

45 lines
958 B
C
Raw Permalink Normal View History

x86/virt/tdx: Use auto-generated code to read global metadata The TDX module provides a set of "Global Metadata Fields". They report things like TDX module version, supported features, and fields related to create/run TDX guests and so on. Currently the kernel only reads "TD Memory Region" (TDMR) related fields for module initialization. There are needs to read more global metadata fields for future use: - Supported features ("TDX_FEATURES0") to fail module initialization when the module doesn't support "not clobbering host RBP when exiting from TDX guest" feature [1]. - KVM TDX baseline support and other features like TDX Connect will need to read more. The current global metadata reading code has limitations (e.g., it only has a primitive helper to read metadata field with 16-bit element size, while TDX supports 8/16/32/64 bits metadata element sizes). It needs tweaks in order to read more metadata fields. But even with the tweaks, when new code is added to read a new field, the reviewers will still need to review against the spec to make sure the new code doesn't screw up things like using the wrong metadata field ID (each metadata field is associated with a unique field ID, which is a TDX-defined u64 constant) etc. TDX documents all global metadata fields in a 'global_metadata.json' file as part of TDX spec [2]. JSON format is machine readable. Instead of tweaking the metadata reading code, use a script to generate the code so that: 1) Using the generated C is simple. 2) Adding a field is simple, e.g., the script just pulls the field ID out of the JSON for a given field thus no manual review is needed. Specifically, to match the layout of the 'struct tdx_sys_info' and its sub-structures, the script uses a table with each entry containing the the name of the sub-structures (which reflects the "Class") and the "Field Name" of all its fields, and auto-generate: 1) The 'struct tdx_sys_info' and all 'struct tdx_sys_info_xx' sub-structures in 'tdx_global_metadata.h'. 2) The main function 'get_tdx_sys_info()' which reads all metadata to 'struct tdx_sys_info' and the 'get_tdx_sys_info_xx()' functions which read 'struct tdx_sys_info_xx()' in 'tdx_global_metadata.c'. Using the generated C is simple: 1) include "tdx_global_metadata.h" to the local "tdx.h"; 2) explicitly include "tdx_global_metadata.c" to the local "tdx.c" after the read_sys_metadata_field() primitive (which is a wrapper of TDH.SYS.RD SEAMCALL to read global metadata). Adding a field is also simple: 1) just add the new field to an existing structure, or add it with a new structure; 2) re-run the script to generate the new code; 3) update the existing tdx_global_metadata.{hc} with the new ones. For now, use the auto-generated code to read the TDMR related fields and the aforesaid metadata field "TDX_FEATURES0". The tdx_global_metadata.{hc} can be generated by running below: #python tdx_global_metadata.py global_metadata.json \ tdx_global_metadata.h tdx_global_metadata.c .. where the 'global_metadata.json' can be fetched from [2] and the 'tdx_global_metadata.py' can be found from [3]. Co-developed-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Dan Williams <dan.j.williams@intel.com> Link: https://lore.kernel.org/fc0e8ab7-86d4-4428-be31-82e1ece6dd21@intel.com/ [1] Link: https://cdrdv2.intel.com/v1/dl/getContent/795381 [2] Link: https://lore.kernel.org/762a50133300710771337398284567b299a86f67.camel@intel.com/ [3] Link: https://lore.kernel.org/all/cbe3f12b1e5479399b53f4873f2ff783d9fc669b.1734188033.git.kai.huang%40intel.com
2024-12-15 04:15:44 +13:00
/* SPDX-License-Identifier: GPL-2.0 */
/* Automatically generated TDX global metadata structures. */
#ifndef _X86_VIRT_TDX_AUTO_GENERATED_TDX_GLOBAL_METADATA_H
#define _X86_VIRT_TDX_AUTO_GENERATED_TDX_GLOBAL_METADATA_H
#include <linux/types.h>
struct tdx_sys_info_features {
u64 tdx_features0;
};
struct tdx_sys_info_tdmr {
u16 max_tdmrs;
u16 max_reserved_per_tdmr;
u16 pamt_4k_entry_size;
u16 pamt_2m_entry_size;
u16 pamt_1g_entry_size;
};
x86/virt/tdx: Read essential global metadata for KVM KVM needs two classes of global metadata to create and run TDX guests: - "TD Control Structures" - "TD Configurability" The first class contains the sizes of TDX guest per-VM and per-vCPU control structures. KVM will need to use them to allocate enough space for those control structures. The second class contains info which reports things like which features are configurable to TDX guest etc. KVM will need to use them to properly configure TDX guests. Read them for KVM TDX to use. The code change is auto-generated by re-running the script in [1] after uncommenting the "td_conf" and "td_ctrl" part to regenerate the tdx_global_metadata.{hc} and update them to the existing ones in the kernel. #python tdx.py global_metadata.json tdx_global_metadata.h \ tdx_global_metadata.c The 'global_metadata.json' can be fetched from [2]. Note that as of this writing, the JSON file only allows a maximum of 32 CPUID entries. While this is enough for current contents of the CPUID leaves, there were plans to change the JSON per TDX module release which would change the ABI and potentially prevent future versions of the TDX module from working with older kernels. While discussions are ongoing with the TDX module team on what exactly constitutes an ABI breakage, in the meantime the TDX module team has agreed to not increase the number of CPUID entries beyond 128 without an opt in. Therefore the file was tweaked by hand to change the maximum number of CPUID_CONFIGs. Link: https://lore.kernel.org/kvm/0853b155ec9aac09c594caa60914ed6ea4dc0a71.camel@intel.com/ [1] Link: https://cdrdv2.intel.com/v1/dl/getContent/795381 [2] Signed-off-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> Message-ID: <20241030190039.77971-4-rick.p.edgecombe@intel.com> Acked-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-24 09:07:40 -05:00
struct tdx_sys_info_td_ctrl {
u16 tdr_base_size;
u16 tdcs_base_size;
u16 tdvps_base_size;
};
struct tdx_sys_info_td_conf {
u64 attributes_fixed0;
u64 attributes_fixed1;
u64 xfam_fixed0;
u64 xfam_fixed1;
u16 num_cpuid_config;
u16 max_vcpus_per_td;
u64 cpuid_config_leaves[128];
u64 cpuid_config_values[128][2];
};
x86/virt/tdx: Use auto-generated code to read global metadata The TDX module provides a set of "Global Metadata Fields". They report things like TDX module version, supported features, and fields related to create/run TDX guests and so on. Currently the kernel only reads "TD Memory Region" (TDMR) related fields for module initialization. There are needs to read more global metadata fields for future use: - Supported features ("TDX_FEATURES0") to fail module initialization when the module doesn't support "not clobbering host RBP when exiting from TDX guest" feature [1]. - KVM TDX baseline support and other features like TDX Connect will need to read more. The current global metadata reading code has limitations (e.g., it only has a primitive helper to read metadata field with 16-bit element size, while TDX supports 8/16/32/64 bits metadata element sizes). It needs tweaks in order to read more metadata fields. But even with the tweaks, when new code is added to read a new field, the reviewers will still need to review against the spec to make sure the new code doesn't screw up things like using the wrong metadata field ID (each metadata field is associated with a unique field ID, which is a TDX-defined u64 constant) etc. TDX documents all global metadata fields in a 'global_metadata.json' file as part of TDX spec [2]. JSON format is machine readable. Instead of tweaking the metadata reading code, use a script to generate the code so that: 1) Using the generated C is simple. 2) Adding a field is simple, e.g., the script just pulls the field ID out of the JSON for a given field thus no manual review is needed. Specifically, to match the layout of the 'struct tdx_sys_info' and its sub-structures, the script uses a table with each entry containing the the name of the sub-structures (which reflects the "Class") and the "Field Name" of all its fields, and auto-generate: 1) The 'struct tdx_sys_info' and all 'struct tdx_sys_info_xx' sub-structures in 'tdx_global_metadata.h'. 2) The main function 'get_tdx_sys_info()' which reads all metadata to 'struct tdx_sys_info' and the 'get_tdx_sys_info_xx()' functions which read 'struct tdx_sys_info_xx()' in 'tdx_global_metadata.c'. Using the generated C is simple: 1) include "tdx_global_metadata.h" to the local "tdx.h"; 2) explicitly include "tdx_global_metadata.c" to the local "tdx.c" after the read_sys_metadata_field() primitive (which is a wrapper of TDH.SYS.RD SEAMCALL to read global metadata). Adding a field is also simple: 1) just add the new field to an existing structure, or add it with a new structure; 2) re-run the script to generate the new code; 3) update the existing tdx_global_metadata.{hc} with the new ones. For now, use the auto-generated code to read the TDMR related fields and the aforesaid metadata field "TDX_FEATURES0". The tdx_global_metadata.{hc} can be generated by running below: #python tdx_global_metadata.py global_metadata.json \ tdx_global_metadata.h tdx_global_metadata.c .. where the 'global_metadata.json' can be fetched from [2] and the 'tdx_global_metadata.py' can be found from [3]. Co-developed-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Dan Williams <dan.j.williams@intel.com> Link: https://lore.kernel.org/fc0e8ab7-86d4-4428-be31-82e1ece6dd21@intel.com/ [1] Link: https://cdrdv2.intel.com/v1/dl/getContent/795381 [2] Link: https://lore.kernel.org/762a50133300710771337398284567b299a86f67.camel@intel.com/ [3] Link: https://lore.kernel.org/all/cbe3f12b1e5479399b53f4873f2ff783d9fc669b.1734188033.git.kai.huang%40intel.com
2024-12-15 04:15:44 +13:00
struct tdx_sys_info {
struct tdx_sys_info_features features;
struct tdx_sys_info_tdmr tdmr;
x86/virt/tdx: Read essential global metadata for KVM KVM needs two classes of global metadata to create and run TDX guests: - "TD Control Structures" - "TD Configurability" The first class contains the sizes of TDX guest per-VM and per-vCPU control structures. KVM will need to use them to allocate enough space for those control structures. The second class contains info which reports things like which features are configurable to TDX guest etc. KVM will need to use them to properly configure TDX guests. Read them for KVM TDX to use. The code change is auto-generated by re-running the script in [1] after uncommenting the "td_conf" and "td_ctrl" part to regenerate the tdx_global_metadata.{hc} and update them to the existing ones in the kernel. #python tdx.py global_metadata.json tdx_global_metadata.h \ tdx_global_metadata.c The 'global_metadata.json' can be fetched from [2]. Note that as of this writing, the JSON file only allows a maximum of 32 CPUID entries. While this is enough for current contents of the CPUID leaves, there were plans to change the JSON per TDX module release which would change the ABI and potentially prevent future versions of the TDX module from working with older kernels. While discussions are ongoing with the TDX module team on what exactly constitutes an ABI breakage, in the meantime the TDX module team has agreed to not increase the number of CPUID entries beyond 128 without an opt in. Therefore the file was tweaked by hand to change the maximum number of CPUID_CONFIGs. Link: https://lore.kernel.org/kvm/0853b155ec9aac09c594caa60914ed6ea4dc0a71.camel@intel.com/ [1] Link: https://cdrdv2.intel.com/v1/dl/getContent/795381 [2] Signed-off-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> Message-ID: <20241030190039.77971-4-rick.p.edgecombe@intel.com> Acked-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-24 09:07:40 -05:00
struct tdx_sys_info_td_ctrl td_ctrl;
struct tdx_sys_info_td_conf td_conf;
x86/virt/tdx: Use auto-generated code to read global metadata The TDX module provides a set of "Global Metadata Fields". They report things like TDX module version, supported features, and fields related to create/run TDX guests and so on. Currently the kernel only reads "TD Memory Region" (TDMR) related fields for module initialization. There are needs to read more global metadata fields for future use: - Supported features ("TDX_FEATURES0") to fail module initialization when the module doesn't support "not clobbering host RBP when exiting from TDX guest" feature [1]. - KVM TDX baseline support and other features like TDX Connect will need to read more. The current global metadata reading code has limitations (e.g., it only has a primitive helper to read metadata field with 16-bit element size, while TDX supports 8/16/32/64 bits metadata element sizes). It needs tweaks in order to read more metadata fields. But even with the tweaks, when new code is added to read a new field, the reviewers will still need to review against the spec to make sure the new code doesn't screw up things like using the wrong metadata field ID (each metadata field is associated with a unique field ID, which is a TDX-defined u64 constant) etc. TDX documents all global metadata fields in a 'global_metadata.json' file as part of TDX spec [2]. JSON format is machine readable. Instead of tweaking the metadata reading code, use a script to generate the code so that: 1) Using the generated C is simple. 2) Adding a field is simple, e.g., the script just pulls the field ID out of the JSON for a given field thus no manual review is needed. Specifically, to match the layout of the 'struct tdx_sys_info' and its sub-structures, the script uses a table with each entry containing the the name of the sub-structures (which reflects the "Class") and the "Field Name" of all its fields, and auto-generate: 1) The 'struct tdx_sys_info' and all 'struct tdx_sys_info_xx' sub-structures in 'tdx_global_metadata.h'. 2) The main function 'get_tdx_sys_info()' which reads all metadata to 'struct tdx_sys_info' and the 'get_tdx_sys_info_xx()' functions which read 'struct tdx_sys_info_xx()' in 'tdx_global_metadata.c'. Using the generated C is simple: 1) include "tdx_global_metadata.h" to the local "tdx.h"; 2) explicitly include "tdx_global_metadata.c" to the local "tdx.c" after the read_sys_metadata_field() primitive (which is a wrapper of TDH.SYS.RD SEAMCALL to read global metadata). Adding a field is also simple: 1) just add the new field to an existing structure, or add it with a new structure; 2) re-run the script to generate the new code; 3) update the existing tdx_global_metadata.{hc} with the new ones. For now, use the auto-generated code to read the TDMR related fields and the aforesaid metadata field "TDX_FEATURES0". The tdx_global_metadata.{hc} can be generated by running below: #python tdx_global_metadata.py global_metadata.json \ tdx_global_metadata.h tdx_global_metadata.c .. where the 'global_metadata.json' can be fetched from [2] and the 'tdx_global_metadata.py' can be found from [3]. Co-developed-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kai Huang <kai.huang@intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Dan Williams <dan.j.williams@intel.com> Link: https://lore.kernel.org/fc0e8ab7-86d4-4428-be31-82e1ece6dd21@intel.com/ [1] Link: https://cdrdv2.intel.com/v1/dl/getContent/795381 [2] Link: https://lore.kernel.org/762a50133300710771337398284567b299a86f67.camel@intel.com/ [3] Link: https://lore.kernel.org/all/cbe3f12b1e5479399b53f4873f2ff783d9fc669b.1734188033.git.kai.huang%40intel.com
2024-12-15 04:15:44 +13:00
};
#endif