Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'x86_tdx_for_6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 TDX updates from Dave Hansen:
"Intel Trust Domain updates.

The existing TDX code needs a _bit_ of metadata from the TDX module.
But KVM is going to need a bunch more very shortly. Rework the
interface with the TDX module to be more consistent and handle the new
higher volume.

The TDX module has added a few new features. The first is a promise
not to clobber RBP under any circumstances. Basically the kernel now
will refuse to use any modules that don't have this promise. Second,
enable the new "REDUCE_VE" feature. This ensures that the TDX module
will not send some silly virtualization exceptions that the guest had
no good way to handle anyway.

- Centralize global metadata infrastructure

- Use new TDX module features for exception suppression and RBP
clobbering"

* tag 'x86_tdx_for_6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/virt/tdx: Require the module to assert it has the NO_RBP_MOD mitigation
x86/virt/tdx: Switch to use auto-generated global metadata reading code
x86/virt/tdx: Use dedicated struct members for PAMT entry sizes
x86/virt/tdx: Use auto-generated code to read global metadata
x86/virt/tdx: Start to track all global metadata in one structure
x86/virt/tdx: Rename 'struct tdx_tdmr_sysinfo' to reflect the spec better
x86/tdx: Dump attributes and TD_CTLS on boot
x86/tdx: Disable unnecessary virtualization exceptions

+253 -113
+1 -1
arch/x86/coco/tdx/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 - obj-y += tdx.o tdx-shared.o tdcall.o 3 + obj-y += debug.o tdcall.o tdx.o tdx-shared.o
+69
arch/x86/coco/tdx/debug.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #undef pr_fmt 4 + #define pr_fmt(fmt) "tdx: " fmt 5 + 6 + #include <linux/array_size.h> 7 + #include <linux/printk.h> 8 + #include <asm/tdx.h> 9 + 10 + #define DEF_TDX_ATTR_NAME(_name) [TDX_ATTR_##_name##_BIT] = __stringify(_name) 11 + 12 + static __initdata const char *tdx_attributes[] = { 13 + DEF_TDX_ATTR_NAME(DEBUG), 14 + DEF_TDX_ATTR_NAME(HGS_PLUS_PROF), 15 + DEF_TDX_ATTR_NAME(PERF_PROF), 16 + DEF_TDX_ATTR_NAME(PMT_PROF), 17 + DEF_TDX_ATTR_NAME(ICSSD), 18 + DEF_TDX_ATTR_NAME(LASS), 19 + DEF_TDX_ATTR_NAME(SEPT_VE_DISABLE), 20 + DEF_TDX_ATTR_NAME(MIGRTABLE), 21 + DEF_TDX_ATTR_NAME(PKS), 22 + DEF_TDX_ATTR_NAME(KL), 23 + DEF_TDX_ATTR_NAME(TPA), 24 + DEF_TDX_ATTR_NAME(PERFMON), 25 + }; 26 + 27 + #define DEF_TD_CTLS_NAME(_name) [TD_CTLS_##_name##_BIT] = __stringify(_name) 28 + 29 + static __initdata const char *tdcs_td_ctls[] = { 30 + DEF_TD_CTLS_NAME(PENDING_VE_DISABLE), 31 + DEF_TD_CTLS_NAME(ENUM_TOPOLOGY), 32 + DEF_TD_CTLS_NAME(VIRT_CPUID2), 33 + DEF_TD_CTLS_NAME(REDUCE_VE), 34 + DEF_TD_CTLS_NAME(LOCK), 35 + }; 36 + 37 + void __init tdx_dump_attributes(u64 td_attr) 38 + { 39 + pr_info("Attributes:"); 40 + 41 + for (int i = 0; i < ARRAY_SIZE(tdx_attributes); i++) { 42 + if (!tdx_attributes[i]) 43 + continue; 44 + if (td_attr & BIT(i)) 45 + pr_cont(" %s", tdx_attributes[i]); 46 + td_attr &= ~BIT(i); 47 + } 48 + 49 + if (td_attr) 50 + pr_cont(" unknown:%#llx", td_attr); 51 + pr_cont("\n"); 52 + 53 + } 54 + 55 + void __init tdx_dump_td_ctls(u64 td_ctls) 56 + { 57 + pr_info("TD_CTLS:"); 58 + 59 + for (int i = 0; i < ARRAY_SIZE(tdcs_td_ctls); i++) { 60 + if (!tdcs_td_ctls[i]) 61 + continue; 62 + if (td_ctls & BIT(i)) 63 + pr_cont(" %s", tdcs_td_ctls[i]); 64 + td_ctls &= ~BIT(i); 65 + } 66 + if (td_ctls) 67 + pr_cont(" unknown:%#llx", td_ctls); 68 + pr_cont("\n"); 69 + }
+35 -9
arch/x86/coco/tdx/tdx.c
··· 32 32 #define VE_GET_PORT_NUM(e) ((e) >> 16) 33 33 #define VE_IS_IO_STRING(e) ((e) & BIT(4)) 34 34 35 - #define ATTR_DEBUG BIT(0) 36 - #define ATTR_SEPT_VE_DISABLE BIT(28) 37 - 38 35 /* TDX Module call error codes */ 39 36 #define TDCALL_RETURN_CODE(a) ((a) >> 32) 40 37 #define TDCALL_INVALID_OPERAND 0xc0000100 ··· 197 200 * 198 201 * TDX 1.0 does not allow the guest to disable SEPT #VE on its own. The VMM 199 202 * controls if the guest will receive such #VE with TD attribute 200 - * ATTR_SEPT_VE_DISABLE. 203 + * TDX_ATTR_SEPT_VE_DISABLE. 201 204 * 202 205 * Newer TDX modules allow the guest to control if it wants to receive SEPT 203 206 * violation #VEs. 204 207 * 205 208 * Check if the feature is available and disable SEPT #VE if possible. 206 209 * 207 - * If the TD is allowed to disable/enable SEPT #VEs, the ATTR_SEPT_VE_DISABLE 210 + * If the TD is allowed to disable/enable SEPT #VEs, the TDX_ATTR_SEPT_VE_DISABLE 208 211 * attribute is no longer reliable. It reflects the initial state of the 209 212 * control for the TD, but it will not be updated if someone (e.g. bootloader) 210 213 * changes it before the kernel starts. Kernel must check TDCS_TD_CTLS bit to ··· 213 216 static void disable_sept_ve(u64 td_attr) 214 217 { 215 218 const char *msg = "TD misconfiguration: SEPT #VE has to be disabled"; 216 - bool debug = td_attr & ATTR_DEBUG; 219 + bool debug = td_attr & TDX_ATTR_DEBUG; 217 220 u64 config, controls; 218 221 219 222 /* Is this TD allowed to disable SEPT #VE */ 220 223 tdg_vm_rd(TDCS_CONFIG_FLAGS, &config); 221 224 if (!(config & TDCS_CONFIG_FLEXIBLE_PENDING_VE)) { 222 225 /* No SEPT #VE controls for the guest: check the attribute */ 223 - if (td_attr & ATTR_SEPT_VE_DISABLE) 226 + if (td_attr & TDX_ATTR_SEPT_VE_DISABLE) 224 227 return; 225 228 226 229 /* Relax SEPT_VE_DISABLE check for debug TD for backtraces */ ··· 271 274 tdg_vm_wr(TDCS_TD_CTLS, TD_CTLS_ENUM_TOPOLOGY, TD_CTLS_ENUM_TOPOLOGY); 272 275 } 273 276 277 + static void reduce_unnecessary_ve(void) 278 + { 279 + u64 err = tdg_vm_wr(TDCS_TD_CTLS, TD_CTLS_REDUCE_VE, TD_CTLS_REDUCE_VE); 280 + 281 + if (err == TDX_SUCCESS) 282 + return; 283 + 284 + /* 285 + * Enabling REDUCE_VE includes ENUM_TOPOLOGY. Only try to 286 + * enable ENUM_TOPOLOGY if REDUCE_VE was not successful. 287 + */ 288 + enable_cpu_topology_enumeration(); 289 + } 290 + 274 291 static void tdx_setup(u64 *cc_mask) 275 292 { 276 293 struct tdx_module_args args = {}; ··· 316 305 tdg_vm_wr(TDCS_NOTIFY_ENABLES, 0, -1ULL); 317 306 318 307 disable_sept_ve(td_attr); 319 - enable_cpu_topology_enumeration(); 308 + 309 + reduce_unnecessary_ve(); 320 310 } 321 311 322 312 /* ··· 1037 1025 } 1038 1026 } 1039 1027 1028 + static __init void tdx_announce(void) 1029 + { 1030 + struct tdx_module_args args = {}; 1031 + u64 controls; 1032 + 1033 + pr_info("Guest detected\n"); 1034 + 1035 + tdcall(TDG_VP_INFO, &args); 1036 + tdx_dump_attributes(args.rdx); 1037 + 1038 + tdg_vm_rd(TDCS_TD_CTLS, &controls); 1039 + tdx_dump_td_ctls(controls); 1040 + } 1041 + 1040 1042 void __init tdx_early_init(void) 1041 1043 { 1042 1044 u64 cc_mask; ··· 1120 1094 */ 1121 1095 x86_cpuinit.parallel_bringup = false; 1122 1096 1123 - pr_info("Guest detected\n"); 1097 + tdx_announce(); 1124 1098 }
+36 -2
arch/x86/include/asm/shared/tdx.h
··· 19 19 #define TDG_VM_RD 7 20 20 #define TDG_VM_WR 8 21 21 22 + /* TDX attributes */ 23 + #define TDX_ATTR_DEBUG_BIT 0 24 + #define TDX_ATTR_DEBUG BIT_ULL(TDX_ATTR_DEBUG_BIT) 25 + #define TDX_ATTR_HGS_PLUS_PROF_BIT 4 26 + #define TDX_ATTR_HGS_PLUS_PROF BIT_ULL(TDX_ATTR_HGS_PLUS_PROF_BIT) 27 + #define TDX_ATTR_PERF_PROF_BIT 5 28 + #define TDX_ATTR_PERF_PROF BIT_ULL(TDX_ATTR_PERF_PROF_BIT) 29 + #define TDX_ATTR_PMT_PROF_BIT 6 30 + #define TDX_ATTR_PMT_PROF BIT_ULL(TDX_ATTR_PMT_PROF_BIT) 31 + #define TDX_ATTR_ICSSD_BIT 16 32 + #define TDX_ATTR_ICSSD BIT_ULL(TDX_ATTR_ICSSD_BIT) 33 + #define TDX_ATTR_LASS_BIT 27 34 + #define TDX_ATTR_LASS BIT_ULL(TDX_ATTR_LASS_BIT) 35 + #define TDX_ATTR_SEPT_VE_DISABLE_BIT 28 36 + #define TDX_ATTR_SEPT_VE_DISABLE BIT_ULL(TDX_ATTR_SEPT_VE_DISABLE_BIT) 37 + #define TDX_ATTR_MIGRTABLE_BIT 29 38 + #define TDX_ATTR_MIGRTABLE BIT_ULL(TDX_ATTR_MIGRTABLE_BIT) 39 + #define TDX_ATTR_PKS_BIT 30 40 + #define TDX_ATTR_PKS BIT_ULL(TDX_ATTR_PKS_BIT) 41 + #define TDX_ATTR_KL_BIT 31 42 + #define TDX_ATTR_KL BIT_ULL(TDX_ATTR_KL_BIT) 43 + #define TDX_ATTR_TPA_BIT 62 44 + #define TDX_ATTR_TPA BIT_ULL(TDX_ATTR_TPA_BIT) 45 + #define TDX_ATTR_PERFMON_BIT 63 46 + #define TDX_ATTR_PERFMON BIT_ULL(TDX_ATTR_PERFMON_BIT) 47 + 22 48 /* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */ 23 49 #define TDCS_CONFIG_FLAGS 0x1110000300000016 24 50 #define TDCS_TD_CTLS 0x1110000300000017 ··· 55 29 #define TDCS_CONFIG_FLEXIBLE_PENDING_VE BIT_ULL(1) 56 30 57 31 /* TDCS_TD_CTLS bits */ 58 - #define TD_CTLS_PENDING_VE_DISABLE BIT_ULL(0) 59 - #define TD_CTLS_ENUM_TOPOLOGY BIT_ULL(1) 32 + #define TD_CTLS_PENDING_VE_DISABLE_BIT 0 33 + #define TD_CTLS_PENDING_VE_DISABLE BIT_ULL(TD_CTLS_PENDING_VE_DISABLE_BIT) 34 + #define TD_CTLS_ENUM_TOPOLOGY_BIT 1 35 + #define TD_CTLS_ENUM_TOPOLOGY BIT_ULL(TD_CTLS_ENUM_TOPOLOGY_BIT) 36 + #define TD_CTLS_VIRT_CPUID2_BIT 2 37 + #define TD_CTLS_VIRT_CPUID2 BIT_ULL(TD_CTLS_VIRT_CPUID2_BIT) 38 + #define TD_CTLS_REDUCE_VE_BIT 3 39 + #define TD_CTLS_REDUCE_VE BIT_ULL(TD_CTLS_REDUCE_VE_BIT) 40 + #define TD_CTLS_LOCK_BIT 63 41 + #define TD_CTLS_LOCK BIT_ULL(TD_CTLS_LOCK_BIT) 60 42 61 43 /* TDX hypercall Leaf IDs */ 62 44 #define TDVMCALL_MAP_GPA 0x10001
+3
arch/x86/include/asm/tdx.h
··· 66 66 67 67 u64 tdx_hcall_get_quote(u8 *buf, size_t size); 68 68 69 + void __init tdx_dump_attributes(u64 td_attr); 70 + void __init tdx_dump_td_ctls(u64 td_ctls); 71 + 69 72 #else 70 73 71 74 static inline void tdx_early_init(void) { };
+32 -65
arch/x86/virt/vmx/tdx/tdx.c
··· 270 270 return 0; 271 271 } 272 272 273 - static int read_sys_metadata_field16(u64 field_id, 274 - int offset, 275 - struct tdx_tdmr_sysinfo *ts) 276 - { 277 - u16 *ts_member = ((void *)ts) + offset; 278 - u64 tmp; 279 - int ret; 273 + #include "tdx_global_metadata.c" 280 274 281 - if (WARN_ON_ONCE(MD_FIELD_ID_ELE_SIZE_CODE(field_id) != 282 - MD_FIELD_ID_ELE_SIZE_16BIT)) 275 + static int check_features(struct tdx_sys_info *sysinfo) 276 + { 277 + u64 tdx_features0 = sysinfo->features.tdx_features0; 278 + 279 + if (!(tdx_features0 & TDX_FEATURES0_NO_RBP_MOD)) { 280 + pr_err("frame pointer (RBP) clobber bug present, upgrade TDX module\n"); 283 281 return -EINVAL; 284 - 285 - ret = read_sys_metadata_field(field_id, &tmp); 286 - if (ret) 287 - return ret; 288 - 289 - *ts_member = tmp; 290 - 291 - return 0; 292 - } 293 - 294 - struct field_mapping { 295 - u64 field_id; 296 - int offset; 297 - }; 298 - 299 - #define TD_SYSINFO_MAP(_field_id, _offset) \ 300 - { .field_id = MD_FIELD_ID_##_field_id, \ 301 - .offset = offsetof(struct tdx_tdmr_sysinfo, _offset) } 302 - 303 - /* Map TD_SYSINFO fields into 'struct tdx_tdmr_sysinfo': */ 304 - static const struct field_mapping fields[] = { 305 - TD_SYSINFO_MAP(MAX_TDMRS, max_tdmrs), 306 - TD_SYSINFO_MAP(MAX_RESERVED_PER_TDMR, max_reserved_per_tdmr), 307 - TD_SYSINFO_MAP(PAMT_4K_ENTRY_SIZE, pamt_entry_size[TDX_PS_4K]), 308 - TD_SYSINFO_MAP(PAMT_2M_ENTRY_SIZE, pamt_entry_size[TDX_PS_2M]), 309 - TD_SYSINFO_MAP(PAMT_1G_ENTRY_SIZE, pamt_entry_size[TDX_PS_1G]), 310 - }; 311 - 312 - static int get_tdx_tdmr_sysinfo(struct tdx_tdmr_sysinfo *tdmr_sysinfo) 313 - { 314 - int ret; 315 - int i; 316 - 317 - /* Populate 'tdmr_sysinfo' fields using the mapping structure above: */ 318 - for (i = 0; i < ARRAY_SIZE(fields); i++) { 319 - ret = read_sys_metadata_field16(fields[i].field_id, 320 - fields[i].offset, 321 - tdmr_sysinfo); 322 - if (ret) 323 - return ret; 324 282 } 325 283 326 284 return 0; ··· 300 342 } 301 343 302 344 static int alloc_tdmr_list(struct tdmr_info_list *tdmr_list, 303 - struct tdx_tdmr_sysinfo *tdmr_sysinfo) 345 + struct tdx_sys_info_tdmr *sysinfo_tdmr) 304 346 { 305 347 size_t tdmr_sz, tdmr_array_sz; 306 348 void *tdmr_array; 307 349 308 - tdmr_sz = tdmr_size_single(tdmr_sysinfo->max_reserved_per_tdmr); 309 - tdmr_array_sz = tdmr_sz * tdmr_sysinfo->max_tdmrs; 350 + tdmr_sz = tdmr_size_single(sysinfo_tdmr->max_reserved_per_tdmr); 351 + tdmr_array_sz = tdmr_sz * sysinfo_tdmr->max_tdmrs; 310 352 311 353 /* 312 354 * To keep things simple, allocate all TDMRs together. ··· 325 367 * at a given index in the TDMR list. 326 368 */ 327 369 tdmr_list->tdmr_sz = tdmr_sz; 328 - tdmr_list->max_tdmrs = tdmr_sysinfo->max_tdmrs; 370 + tdmr_list->max_tdmrs = sysinfo_tdmr->max_tdmrs; 329 371 tdmr_list->nr_consumed_tdmrs = 0; 330 372 331 373 return 0; ··· 879 921 /* 880 922 * Construct a list of TDMRs on the preallocated space in @tdmr_list 881 923 * to cover all TDX memory regions in @tmb_list based on the TDX module 882 - * TDMR global information in @tdmr_sysinfo. 924 + * TDMR global information in @sysinfo_tdmr. 883 925 */ 884 926 static int construct_tdmrs(struct list_head *tmb_list, 885 927 struct tdmr_info_list *tdmr_list, 886 - struct tdx_tdmr_sysinfo *tdmr_sysinfo) 928 + struct tdx_sys_info_tdmr *sysinfo_tdmr) 887 929 { 930 + u16 pamt_entry_size[TDX_PS_NR] = { 931 + sysinfo_tdmr->pamt_4k_entry_size, 932 + sysinfo_tdmr->pamt_2m_entry_size, 933 + sysinfo_tdmr->pamt_1g_entry_size, 934 + }; 888 935 int ret; 889 936 890 937 ret = fill_out_tdmrs(tmb_list, tdmr_list); 891 938 if (ret) 892 939 return ret; 893 940 894 - ret = tdmrs_set_up_pamt_all(tdmr_list, tmb_list, 895 - tdmr_sysinfo->pamt_entry_size); 941 + ret = tdmrs_set_up_pamt_all(tdmr_list, tmb_list, pamt_entry_size); 896 942 if (ret) 897 943 return ret; 898 944 899 945 ret = tdmrs_populate_rsvd_areas_all(tdmr_list, tmb_list, 900 - tdmr_sysinfo->max_reserved_per_tdmr); 946 + sysinfo_tdmr->max_reserved_per_tdmr); 901 947 if (ret) 902 948 tdmrs_free_pamt_all(tdmr_list); 903 949 ··· 1060 1098 1061 1099 static int init_tdx_module(void) 1062 1100 { 1063 - struct tdx_tdmr_sysinfo tdmr_sysinfo; 1101 + struct tdx_sys_info sysinfo; 1064 1102 int ret; 1103 + 1104 + ret = get_tdx_sys_info(&sysinfo); 1105 + if (ret) 1106 + return ret; 1107 + 1108 + /* Check whether the kernel can support this module */ 1109 + ret = check_features(&sysinfo); 1110 + if (ret) 1111 + return ret; 1065 1112 1066 1113 /* 1067 1114 * To keep things simple, assume that all TDX-protected memory ··· 1088 1117 if (ret) 1089 1118 goto out_put_tdxmem; 1090 1119 1091 - ret = get_tdx_tdmr_sysinfo(&tdmr_sysinfo); 1092 - if (ret) 1093 - goto err_free_tdxmem; 1094 - 1095 1120 /* Allocate enough space for constructing TDMRs */ 1096 - ret = alloc_tdmr_list(&tdx_tdmr_list, &tdmr_sysinfo); 1121 + ret = alloc_tdmr_list(&tdx_tdmr_list, &sysinfo.tdmr); 1097 1122 if (ret) 1098 1123 goto err_free_tdxmem; 1099 1124 1100 1125 /* Cover all TDX-usable memory regions in TDMRs */ 1101 - ret = construct_tdmrs(&tdx_memlist, &tdx_tdmr_list, &tdmr_sysinfo); 1126 + ret = construct_tdmrs(&tdx_memlist, &tdx_tdmr_list, &sysinfo.tdmr); 1102 1127 if (ret) 1103 1128 goto err_free_tdmrs; 1104 1129
+4 -36
arch/x86/virt/vmx/tdx/tdx.h
··· 3 3 #define _X86_VIRT_TDX_H 4 4 5 5 #include <linux/bits.h> 6 + #include "tdx_global_metadata.h" 6 7 7 8 /* 8 9 * This file contains both macros and data structures defined by the TDX ··· 26 25 /* TDX page types */ 27 26 #define PT_NDA 0x0 28 27 #define PT_RSVD 0x1 29 - 30 - /* 31 - * Global scope metadata field ID. 32 - * 33 - * See Table "Global Scope Metadata", TDX module 1.5 ABI spec. 34 - */ 35 - #define MD_FIELD_ID_MAX_TDMRS 0x9100000100000008ULL 36 - #define MD_FIELD_ID_MAX_RESERVED_PER_TDMR 0x9100000100000009ULL 37 - #define MD_FIELD_ID_PAMT_4K_ENTRY_SIZE 0x9100000100000010ULL 38 - #define MD_FIELD_ID_PAMT_2M_ENTRY_SIZE 0x9100000100000011ULL 39 - #define MD_FIELD_ID_PAMT_1G_ENTRY_SIZE 0x9100000100000012ULL 40 - 41 - /* 42 - * Sub-field definition of metadata field ID. 43 - * 44 - * See Table "MD_FIELD_ID (Metadata Field Identifier / Sequence Header) 45 - * Definition", TDX module 1.5 ABI spec. 46 - * 47 - * - Bit 33:32: ELEMENT_SIZE_CODE -- size of a single element of metadata 48 - * 49 - * 0: 8 bits 50 - * 1: 16 bits 51 - * 2: 32 bits 52 - * 3: 64 bits 53 - */ 54 - #define MD_FIELD_ID_ELE_SIZE_CODE(_field_id) \ 55 - (((_field_id) & GENMASK_ULL(33, 32)) >> 32) 56 - 57 - #define MD_FIELD_ID_ELE_SIZE_16BIT 1 58 28 59 29 struct tdmr_reserved_area { 60 30 u64 offset; ··· 52 80 DECLARE_FLEX_ARRAY(struct tdmr_reserved_area, reserved_areas); 53 81 } __packed __aligned(TDMR_INFO_ALIGNMENT); 54 82 83 + /* Bit definitions of TDX_FEATURES0 metadata field */ 84 + #define TDX_FEATURES0_NO_RBP_MOD BIT(18) 85 + 55 86 /* 56 87 * Do not put any hardware-defined TDX structure representations below 57 88 * this comment! ··· 72 97 unsigned long start_pfn; 73 98 unsigned long end_pfn; 74 99 int nid; 75 - }; 76 - 77 - /* "TDMR info" part of "Global Scope Metadata" for constructing TDMRs */ 78 - struct tdx_tdmr_sysinfo { 79 - u16 max_tdmrs; 80 - u16 max_reserved_per_tdmr; 81 - u16 pamt_entry_size[TDX_PS_NR]; 82 100 }; 83 101 84 102 /* Warn if kernel has less than TDMR_NR_WARN TDMRs after allocation */
+48
arch/x86/virt/vmx/tdx/tdx_global_metadata.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Automatically generated functions to read TDX global metadata. 4 + * 5 + * This file doesn't compile on its own as it lacks of inclusion 6 + * of SEAMCALL wrapper primitive which reads global metadata. 7 + * Include this file to other C file instead. 8 + */ 9 + 10 + static int get_tdx_sys_info_features(struct tdx_sys_info_features *sysinfo_features) 11 + { 12 + int ret = 0; 13 + u64 val; 14 + 15 + if (!ret && !(ret = read_sys_metadata_field(0x0A00000300000008, &val))) 16 + sysinfo_features->tdx_features0 = val; 17 + 18 + return ret; 19 + } 20 + 21 + static int get_tdx_sys_info_tdmr(struct tdx_sys_info_tdmr *sysinfo_tdmr) 22 + { 23 + int ret = 0; 24 + u64 val; 25 + 26 + if (!ret && !(ret = read_sys_metadata_field(0x9100000100000008, &val))) 27 + sysinfo_tdmr->max_tdmrs = val; 28 + if (!ret && !(ret = read_sys_metadata_field(0x9100000100000009, &val))) 29 + sysinfo_tdmr->max_reserved_per_tdmr = val; 30 + if (!ret && !(ret = read_sys_metadata_field(0x9100000100000010, &val))) 31 + sysinfo_tdmr->pamt_4k_entry_size = val; 32 + if (!ret && !(ret = read_sys_metadata_field(0x9100000100000011, &val))) 33 + sysinfo_tdmr->pamt_2m_entry_size = val; 34 + if (!ret && !(ret = read_sys_metadata_field(0x9100000100000012, &val))) 35 + sysinfo_tdmr->pamt_1g_entry_size = val; 36 + 37 + return ret; 38 + } 39 + 40 + static int get_tdx_sys_info(struct tdx_sys_info *sysinfo) 41 + { 42 + int ret = 0; 43 + 44 + ret = ret ?: get_tdx_sys_info_features(&sysinfo->features); 45 + ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr); 46 + 47 + return ret; 48 + }
+25
arch/x86/virt/vmx/tdx/tdx_global_metadata.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Automatically generated TDX global metadata structures. */ 3 + #ifndef _X86_VIRT_TDX_AUTO_GENERATED_TDX_GLOBAL_METADATA_H 4 + #define _X86_VIRT_TDX_AUTO_GENERATED_TDX_GLOBAL_METADATA_H 5 + 6 + #include <linux/types.h> 7 + 8 + struct tdx_sys_info_features { 9 + u64 tdx_features0; 10 + }; 11 + 12 + struct tdx_sys_info_tdmr { 13 + u16 max_tdmrs; 14 + u16 max_reserved_per_tdmr; 15 + u16 pamt_4k_entry_size; 16 + u16 pamt_2m_entry_size; 17 + u16 pamt_1g_entry_size; 18 + }; 19 + 20 + struct tdx_sys_info { 21 + struct tdx_sys_info_features features; 22 + struct tdx_sys_info_tdmr tdmr; 23 + }; 24 + 25 + #endif