1use crate::vmx;
7use bitfield_struct::bitfield;
8use open_enum::open_enum;
9use zerocopy::FromBytes;
10use zerocopy::Immutable;
11use zerocopy::IntoBytes;
12use zerocopy::KnownLayout;
13
14pub const TDX_SHARED_GPA_BOUNDARY_BITS: u8 = 47;
15pub const TDX_SHARED_GPA_BOUNDARY_ADDRESS_BIT: u64 = 1 << TDX_SHARED_GPA_BOUNDARY_BITS;
16pub const RESET_VECTOR_PAGE: u64 = 0xfffff000;
17
18pub const TDX_REPORT_SIZE: usize = 0x400;
20
21pub const TDX_REPORT_DATA_SIZE: usize = 64;
23
24pub const TDX_TDKEYREQUEST_SIZE: usize = 128;
27
28pub const TDX_DERIVED_KEY_SIZE: usize = 32;
30
31open_enum! {
32 pub enum TdCallLeaf: u64 {
35 VP_VMCALL = 0,
36 VP_INFO = 1,
37 MR_RTMR_EXTEND = 2,
38 VP_VEINFO_GET = 3,
39 MR_REPORT = 4,
40 VP_CPUIDVE_SET = 5,
41 MEM_PAGE_ACCEPT = 6,
42 VM_RD = 7,
43 VM_WR = 8,
44 VP_RD = 9,
45 VP_WR = 10,
46 SYS_RD = 11,
47 MEM_PAGE_ATTR_RD = 23,
48 MEM_PAGE_ATTR_WR = 24,
49 VP_ENTER = 25,
50 VP_INVGLA = 27,
51 MR_KEY_GET = 29,
52 MEM_PAGE_RELEASE = 30,
53 }
54}
55
56#[bitfield(u64)]
57pub struct TdConfigFlags {
58 pub gpaw: bool,
59 pub flexible_pending_ve: bool,
60 pub no_rbp_mod: bool,
61 pub maxpa_virt: bool,
62 pub maxgpa_virt: bool,
63 pub tdx_connect: bool,
64 pub page_release: bool,
65 pub sealing: bool,
66 #[bits(56)]
67 pub reserved: u64,
68}
69
70pub type TdgVmRdResult = u64;
71
72#[repr(u8)]
74#[derive(Clone, Copy, Debug, PartialEq, Eq)]
75pub enum TdgMemPageLevel {
76 Size4k = 0,
77 Size2Mb = 1,
78 Size1Gb = 2,
79}
80
81impl TdgMemPageLevel {
82 const fn from_bits(value: u64) -> Self {
83 match value {
84 0 => Self::Size4k,
85 1 => Self::Size2Mb,
86 2 => Self::Size1Gb,
87 _ => panic!("invalid TdgMemPageLevel value"),
88 }
89 }
90
91 const fn into_bits(self) -> u64 {
92 self as u64
93 }
94}
95
96#[bitfield(u16)]
98#[derive(PartialEq, Eq)]
99pub struct GpaVmAttributes {
100 pub read: bool,
101 pub write: bool,
102 pub kernel_execute: bool,
103 pub user_execute: bool,
104 #[bits(3)]
105 reserved: u8,
106 suppress_ve: bool,
107 #[bits(7)]
108 reserved2: u8,
109 pub valid: bool,
110}
111
112impl GpaVmAttributes {
114 pub const FULL_ACCESS: Self = Self::new()
115 .with_read(true)
116 .with_write(true)
117 .with_kernel_execute(true)
118 .with_user_execute(true)
119 .with_valid(true);
120}
121
122#[bitfield(u16)]
124pub struct GpaVmAttributesMask {
125 pub read: bool,
126 pub write: bool,
127 pub kernel_execute: bool,
128 pub user_execute: bool,
129 #[bits(3)]
130 reserved: u8,
131 pub suppress_ve: bool,
132 #[bits(7)]
133 reserved2: u8,
134 pub inv_ept: bool,
136}
137
138impl GpaVmAttributesMask {
139 pub const ALL_CHANGED: Self = Self::new()
140 .with_read(true)
141 .with_write(true)
142 .with_kernel_execute(true)
143 .with_user_execute(true);
144}
145
146#[bitfield(u64)]
149#[derive(PartialEq, Eq)]
150pub struct TdgMemPageGpaAttr {
151 #[bits(16)]
153 pub l1: GpaVmAttributes,
154 #[bits(16)]
156 pub l2_vm1: GpaVmAttributes,
157 #[bits(16)]
159 pub l2_vm2: GpaVmAttributes,
160 #[bits(16)]
161 pub l2_vm3: GpaVmAttributes,
162}
163
164#[bitfield(u64)]
165pub struct TdgMemPageAcceptRcx {
166 #[bits(3)]
167 pub level: TdgMemPageLevel,
168 #[bits(9)]
169 pub reserved: u64,
170 #[bits(40)]
172 pub gpa_page_number: u64,
173 #[bits(12)]
174 pub reserved2: u64,
175}
176
177#[bitfield(u64)]
178pub struct TdgMemPageReleaseRcx {
179 #[bits(3)]
180 pub level: TdgMemPageLevel,
181 #[bits(9)]
182 pub reserved: u64,
183 #[bits(40)]
185 pub gpa_page_number: u64,
186 #[bits(12)]
187 pub reserved2: u64,
188}
189
190#[bitfield(u64)]
191pub struct TdgMemPageReleaseRcxResult {
192 #[bits(3)]
193 pub level: TdgMemPageLevel,
194 #[bits(9)]
195 pub reserved: u64,
196 #[bits(40)]
198 pub gpa_page_number: u64,
199 #[bits(9)]
200 pub reserved2: u64,
201 #[bits(1)]
202 pub mmio: bool,
203 #[bits(1)]
204 pub pending: bool,
205 #[bits(1)]
206 pub reserved3: u8,
207}
208
209#[bitfield(u64)]
210pub struct TdgMemPageAttrGpaMappingReadRcxResult {
211 #[bits(3)]
212 pub level: TdgMemPageLevel,
213 #[bits(9)]
214 pub reserved: u64,
215 #[bits(40)]
217 pub gpa_page_number: u64,
218 #[bits(10)]
219 pub reserved2: u64,
220 #[bits(1)]
223 pub pending: u8,
224 #[bits(1)]
225 pub reserved3: u64,
226}
227
228#[bitfield(u64)]
230#[derive(PartialEq, Eq)]
231pub struct TdgMemPageAttrWriteRcx {
232 #[bits(3)]
233 pub level: TdgMemPageLevel,
234 #[bits(9)]
235 pub reserved: u64,
236 #[bits(40)]
238 pub gpa_page_number: u64,
239 #[bits(12)]
240 pub reserved2: u64,
241}
242
243#[bitfield(u64)]
245pub struct TdgMemPageAttrWriteR8 {
246 #[bits(16)]
247 pub reserved: u64,
248 #[bits(16)]
250 pub l2_vm1: GpaVmAttributesMask,
251 #[bits(16)]
253 pub l2_vm2: GpaVmAttributesMask,
254 #[bits(16)]
256 pub l2_vm3: GpaVmAttributesMask,
257}
258
259#[repr(u64)]
262pub enum TdVmCallSubFunction {
263 IoInstr = 0x1e,
264 RdMsr = 0x1f,
265 WrMsr = 0x20,
266 MapGpa = 0x10001,
267}
268
269open_enum! {
270 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
272 pub enum TdCallResultCode: u32 {
273 SUCCESS = 0x00000000,
274 NON_RECOVERABLE_VCPU = 0x40000001,
275 NON_RECOVERABLE_TD = 0x60000002,
276 INTERRUPTED_RESUMABLE = 0x80000003,
277 INTERRUPTED_RESTARTABLE = 0x80000004,
278 NON_RECOVERABLE_TD_NON_ACCESSIBLE = 0x60000005,
279 INVALID_RESUMPTION = 0xC0000006,
280 NON_RECOVERABLE_TD_WRONG_APIC_MODE = 0xE0000007,
281 CROSS_TD_FAULT = 0x80000008,
282 CROSS_TD_TRAP = 0x90000009,
283 NON_RECOVERABLE_TD_CORRUPTED_MD = 0x6000000A,
284 OPERAND_INVALID = 0xC0000100,
285 OPERAND_ADDR_RANGE_ERROR = 0xC0000101,
286 OPERAND_BUSY = 0x80000200,
287 PREVIOUS_TLB_EPOCH_BUSY = 0x80000201,
288 SYS_BUSY = 0x80000202,
289 RND_NO_ENTROPY = 0x80000203,
290 OPERAND_BUSY_HOST_PRIORITY = 0x80000204,
291 HOST_PRIORITY_BUSY_TIMEOUT = 0x90000205,
292 PAGE_METADATA_INCORRECT = 0xC0000300,
293 PAGE_ALREADY_FREE = 0x00000301,
294 PAGE_NOT_OWNED_BY_TD = 0xC0000302,
295 PAGE_NOT_FREE = 0xC0000303,
296 TD_ASSOCIATED_PAGES_EXIST = 0xC0000400,
297 SYS_INIT_NOT_PENDING = 0xC0000500,
298 SYS_LP_INIT_NOT_DONE = 0xC0000502,
299 SYS_LP_INIT_DONE = 0xC0000503,
300 SYS_NOT_READY = 0xC0000505,
301 SYS_SHUTDOWN = 0xC0000506,
302 SYS_KEY_CONFIG_NOT_PENDING = 0xC0000507,
303 SYS_STATE_INCORRECT = 0xC0000508,
304 SYS_INVALID_HANDOFF = 0xC0000509,
305 SYS_INCOMPATIBLE_SIGSTRUCT = 0xC000050A,
306 SYS_LP_INIT_NOT_PENDING = 0xC000050B,
307 SYS_CONFIG_NOT_PENDING = 0xC000050C,
308 INCOMPATIBLE_SEAM_CAPABILITIES = 0xC000050D,
309 TD_FATAL = 0xE0000604,
310 TD_NON_DEBUG = 0xC0000605,
311 TDCS_NOT_ALLOCATED = 0xC0000606,
312 LIFECYCLE_STATE_INCORRECT = 0xC0000607,
313 OP_STATE_INCORRECT = 0xC0000608,
314 NO_VCPUS = 0xC0000609,
315 TDCX_NUM_INCORRECT = 0xC0000610,
316 VCPU_STATE_INCORRECT = 0xC0000700,
317 VCPU_ASSOCIATED = 0x80000701,
318 VCPU_NOT_ASSOCIATED = 0x80000702,
319 NO_VALID_VE_INFO = 0xC0000704,
320 MAX_VCPUS_EXCEEDED = 0xC0000705,
321 TSC_ROLLBACK = 0xC0000706,
322 TD_VMCS_FIELD_NOT_INITIALIZED = 0xC0000730,
323 MCS_FIELD_ERROR = 0xC0000731,
324 KEY_GENERATION_FAILED = 0x80000800,
325 TD_KEYS_NOT_CONFIGURED = 0x80000810,
326 KEY_STATE_INCORRECT = 0xC0000811,
327 KEY_CONFIGURED = 0x00000815,
328 WBCACHE_NOT_COMPLETE = 0x80000817,
329 HKID_NOT_FREE = 0xC0000820,
330 NO_HKID_READY_TO_WBCACHE = 0x00000821,
331 WBCACHE_RESUME_ERROR = 0xC0000823,
332 FLUSHVP_NOT_DONE = 0x80000824,
333 NUM_ACTIVATED_HKIDS_NOT_SUPPORTED = 0xC0000825,
334 INCORRECT_CPUID_VALUE = 0xC0000900,
335 LIMIT_CPUID_MAXVAL_SET = 0xC0000901,
336 INCONSISTENT_CPUID_FIELD = 0xC0000902,
337 CPUID_MAX_SUBLEAVES_UNRECOGNIZED = 0xC0000903,
338 CPUID_LEAF_1F_FORMAT_UNRECOGNIZED = 0xC0000904,
339 INVALID_WBINVD_SCOPE = 0xC0000905,
340 INVALID_PKG_ID = 0xC0000906,
341 ENABLE_MONITOR_FSM_NOT_SET = 0xC0000907,
342 CPUID_LEAF_NOT_SUPPORTED = 0xC0000908,
343 SMRR_NOT_LOCKED = 0xC0000910,
344 INVALID_SMRR_CONFIGURATION = 0xC0000911,
345 SMRR_OVERLAPS_CMR = 0xC0000912,
346 SMRR_LOCK_NOT_SUPPORTED = 0xC0000913,
347 SMRR_NOT_SUPPORTED = 0xC0000914,
348 INCONSISTENT_MSR = 0xC0000920,
349 INCORRECT_MSR_VALUE = 0xC0000921,
350 SEAMREPORT_NOT_AVAILABLE = 0xC0000930,
351 SEAMDB_GETREF_NOT_AVAILABLE = 0xC0000931,
352 SEAMDB_REPORT_NOT_AVAILABLE = 0xC0000932,
353 SEAMVERIFYREPORT_NOT_AVAILABLE = 0xC0000933,
354 INVALID_TDMR = 0xC0000A00,
355 NON_ORDERED_TDMR = 0xC0000A01,
356 TDMR_OUTSIDE_CMRS = 0xC0000A02,
357 TDMR_ALREADY_INITIALIZED = 0x00000A03,
358 INVALID_PAMT = 0xC0000A10,
359 PAMT_OUTSIDE_CMRS = 0xC0000A11,
360 PAMT_OVERLAP = 0xC0000A12,
361 INVALID_RESERVED_IN_TDMR = 0xC0000A20,
362 NON_ORDERED_RESERVED_IN_TDMR = 0xC0000A21,
363 CMR_LIST_INVALID = 0xC0000A22,
364 EPT_WALK_FAILED = 0xC0000B00,
365 EPT_ENTRY_FREE = 0xC0000B01,
366 EPT_ENTRY_NOT_FREE = 0xC0000B02,
367 EPT_ENTRY_NOT_PRESENT = 0xC0000B03,
368 EPT_ENTRY_NOT_LEAF = 0xC0000B04,
369 EPT_ENTRY_LEAF = 0xC0000B05,
370 GPA_RANGE_NOT_BLOCKED = 0xC0000B06,
371 GPA_RANGE_ALREADY_BLOCKED = 0x00000B07,
372 TLB_TRACKING_NOT_DONE = 0xC0000B08,
373 EPT_INVALID_PROMOTE_CONDITIONS = 0xC0000B09,
374 PAGE_ALREADY_ACCEPTED = 0x00000B0A,
375 PAGE_SIZE_MISMATCH = 0xC0000B0B,
376 GPA_RANGE_BLOCKED = 0xC0000B0C,
377 EPT_ENTRY_STATE_INCORRECT = 0xC0000B0D,
378 EPT_PAGE_NOT_FREE = 0xC0000B0E,
379 L2_SEPT_WALK_FAILED = 0xC0000B0F,
380 L2_SEPT_ENTRY_NOT_FREE = 0xC0000B10,
381 PAGE_ATTR_INVALID = 0xC0000B11,
382 L2_SEPT_PAGE_NOT_PROVIDED = 0xC0000B12,
383 METADATA_FIELD_ID_INCORRECT = 0xC0000C00,
384 METADATA_FIELD_NOT_WRITABLE = 0xC0000C01,
385 METADATA_FIELD_NOT_READABLE = 0xC0000C02,
386 METADATA_FIELD_VALUE_NOT_VALID = 0xC0000C03,
387 METADATA_LIST_OVERFLOW = 0xC0000C04,
388 INVALID_METADATA_LIST_HEADER = 0xC0000C05,
389 REQUIRED_METADATA_FIELD_MISSING = 0xC0000C06,
390 METADATA_ELEMENT_SIZE_INCORRECT = 0xC0000C07,
391 METADATA_LAST_ELEMENT_INCORRECT = 0xC0000C08,
392 METADATA_FIELD_CURRENTLY_NOT_WRITABLE = 0xC0000C09,
393 METADATA_WR_MASK_NOT_VALID = 0xC0000C0A,
394 METADATA_FIRST_FIELD_ID_IN_CONTEXT = 0x00000C0B,
395 METADATA_FIELD_SKIP = 0x00000C0C,
396 SERVTD_ALREADY_BOUND_FOR_TYPE = 0xC0000D00,
397 SERVTD_TYPE_MISMATCH = 0xC0000D01,
398 SERVTD_ATTR_MISMATCH = 0xC0000D02,
399 SERVTD_INFO_HASH_MISMATCH = 0xC0000D03,
400 SERVTD_UUID_MISMATCH = 0xC0000D04,
401 SERVTD_NOT_BOUND = 0xC0000D05,
402 SERVTD_BOUND = 0xC0000D06,
403 TARGET_UUID_MISMATCH = 0xC0000D07,
404 TARGET_UUID_UPDATED = 0xC0000D08,
405 INVALID_MBMD = 0xC0000E00,
406 INCORRECT_MBMD_MAC = 0xC0000E01,
407 NOT_WRITE_BLOCKED = 0xC0000E02,
408 ALREADY_WRITE_BLOCKED = 0x00000E03,
409 NOT_EXPORTED = 0xC0000E04,
410 MIGRATION_STREAM_STATE_INCORRECT = 0xC0000E05,
411 MAX_MIGS_NUM_EXCEEDED = 0xC0000E06,
412 EXPORTED_DIRTY_PAGES_REMAIN = 0xC0000E07,
413 MIGRATION_DECRYPTION_KEY_NOT_SET = 0xC0000E08,
414 TD_NOT_MIGRATABLE = 0xC0000E09,
415 PREVIOUS_EXPORT_CLEANUP_INCOMPLETE = 0xC0000E0A,
416 NUM_MIGS_HIGHER_THAN_CREATED = 0xC0000E0B,
417 IMPORT_MISMATCH = 0xC0000E0C,
418 MIGRATION_EPOCH_OVERFLOW = 0xC0000E0D,
419 MAX_EXPORTS_EXCEEDED = 0xC0000E0E,
420 INVALID_PAGE_MAC = 0xC0000E0F,
421 MIGRATED_IN_CURRENT_EPOCH = 0xC0000E10,
422 DISALLOWED_IMPORT_OVER_REMOVED = 0xC0000E11,
423 SOME_VCPUS_NOT_MIGRATED = 0xC0000E12,
424 ALL_VCPUS_IMPORTED = 0xC0000E13,
425 MIN_MIGS_NOT_CREATED = 0xC0000E14,
426 VCPU_ALREADY_EXPORTED = 0xC0000E15,
427 INVALID_MIGRATION_DECRYPTION_KEY = 0xC0000E16,
428 INVALID_CPUSVN = 0xC0001000,
429 INVALID_REPORTMACSTRUCT = 0xC0001001,
430 L2_EXIT_HOST_ROUTED_ASYNC = 0x00001100,
431 L2_EXIT_HOST_ROUTED_TDVMCALL = 0x00001101,
432 L2_EXIT_PENDING_INTERRUPT = 0x00001102,
433 PENDING_INTERRUPT = 0x00001120,
434 TD_EXIT_BEFORE_L2_ENTRY = 0x00001140,
435 TD_EXIT_ON_L2_VM_EXIT = 0x00001141,
436 TD_EXIT_ON_L2_TO_L1 = 0x00001142,
437 GLA_NOT_CANONICAL = 0xC0001160,
438 }
439}
440
441impl TdCallResultCode {
442 const fn from_bits(value: u64) -> Self {
443 Self(value as u32)
444 }
445
446 const fn into_bits(self) -> u64 {
447 self.0 as u64
448 }
449}
450
451#[bitfield(u64)]
453pub struct TdCallResult {
454 pub details: u32,
455 #[bits(32)]
456 pub code: TdCallResultCode,
457}
458
459open_enum! {
460 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
462 pub enum TdVmCallR10Result: u64 {
463 SUCCESS = 0,
464 RETRY = 1,
465 OPERAND_INVALID = 0x80000000_00000000,
466 GPA_INUSE = 0x80000000_00000001,
467 ALIGN_ERROR = 0x80000000_00000002,
468 }
469}
470
471#[repr(u64)]
473#[derive(Debug)]
474pub enum FieldSize {
475 Invalid = 0,
476 Size16Bit = 1,
477 Size32Bit = 2,
478 Size64Bit = 3,
479}
480
481impl FieldSize {
482 const fn from_bits(value: u64) -> Self {
483 match value {
484 0 => FieldSize::Invalid,
485 1 => FieldSize::Size16Bit,
486 2 => FieldSize::Size32Bit,
487 3 => FieldSize::Size64Bit,
488 _ => panic!("Invalid field size"),
489 }
490 }
491
492 const fn into_bits(self) -> u64 {
493 self as u64
494 }
495}
496
497open_enum! {
498 pub enum TdVpsClassCode: u8 {
499 TD_VMCS = 0,
500 VAPIC = 1,
501 VE_INFO = 2,
502 GUEST_GPR_STATE = 16,
503 GUEST_STATE = 17,
504 GUEST_EXT_STATE = 18,
505 GUEST_MSR_STATE = 19,
506 MANAGEMENT = 32,
507 CPUID_CONTROL = 33,
508 EPT_VIOLATION_LOG = 34,
509 VMCS_1 = 36,
510 MSR_BITMAPS_1 = 37,
511 MSR_BITMAPS_SHADOW_1 = 38,
512 VMCS_2 = 44,
513 MSR_BITMAPS_2 = 45,
514 MSR_BITMAPS_SHADOW_2 = 46,
515 VMCS_3 = 52,
516 }
517}
518
519open_enum! {
520 pub enum TdxContextCode: u8 {
521 PLATFORM = 0,
522 TD = 1,
523 TD_VCPU = 2,
524 }
525}
526
527impl TdxContextCode {
528 const fn from_bits(value: u64) -> Self {
529 Self(value as u8)
530 }
531 const fn into_bits(self) -> u64 {
532 self.0 as u64
533 }
534}
535
536pub const TDX_FIELD_CODE_L2_CTLS_VM1: TdxExtendedFieldCode =
538 TdxExtendedFieldCode(0xA020000300000051);
539pub const TDX_FIELD_CODE_L2_CTLS_VM2: TdxExtendedFieldCode =
540 TdxExtendedFieldCode(0xA020000300000052);
541
542pub const TDX_FIELD_CODE_CONFIG_FLAGS: TdxExtendedFieldCode =
544 TdxExtendedFieldCode(0x9110000300000016);
545
546pub const TDX_FIELD_CODE_TD_CTLS: TdxExtendedFieldCode = TdxExtendedFieldCode(0x1110000300000017);
549
550pub const TDX_FIELD_ID_TDX_FEATURES0: u64 = 0x0A00000300000008;
553
554#[bitfield(u64)]
561#[derive(PartialEq, Eq)]
562pub struct TdxFeatures0 {
563 #[bits(12)]
564 _reserved0: u64,
565 pub sealing: bool,
568 #[bits(9)]
569 _reserved1: u64,
570 pub td_signing_and_svn: bool,
573 #[bits(27)]
574 _reserved2: u64,
575 pub sealkey_128: bool,
577 #[bits(13)]
578 _reserved3: u64,
579}
580
581#[bitfield(u64)]
584#[derive(PartialEq, Eq)]
585pub struct TdCtls {
586 pub pending_ve_disable: bool,
588 pub enum_topology: bool,
590 pub virt_cpuid2: bool,
592 pub reduce_ve: bool,
594 pub enable_hw_seal_keys: bool,
598 #[bits(58)]
599 _reserved: u64,
600 pub lock: bool,
602}
603
604#[bitfield(u64)]
607#[derive(PartialEq, Eq)]
608pub struct TdxExtendedFieldCode {
609 #[bits(24)]
610 pub field_code: u32,
611 #[bits(8)]
612 _reserved0: u64,
613 #[bits(2)]
614 pub field_size: FieldSize,
615 #[bits(4)]
616 pub last_element: u8,
617 #[bits(9)]
618 pub last_field: u16,
619 #[bits(3)]
620 _reserved1: u64,
621 pub increment_size: bool,
622 pub write_mask_valid: bool,
623 #[bits(3)]
624 pub context_code: TdxContextCode,
625 #[bits(1)]
626 _reserved2: u64,
627 #[bits(6)]
628 pub class_code: u8,
629 #[bits(1)]
630 _reserved3: u64,
631 pub non_arch: bool,
632}
633
634#[bitfield(u64)]
636pub struct TdxInstructionInfo {
637 pub info: u32,
638 pub length: u32,
639}
640
641#[bitfield(u64)]
642pub struct TdxL2Ctls {
643 pub enable_shared_ept: bool,
644 pub enable_tdvmcall: bool,
645 #[bits(62)]
646 pub reserved: u64,
647}
648
649#[bitfield(u64)]
650pub struct TdxVpEnterRaxResult {
651 #[bits(32)]
653 pub vmx_exit: vmx::VmxExit,
654 #[bits(32)]
656 pub tdx_exit: TdCallResultCode,
657}
658
659#[bitfield(u64)]
660pub struct TdxExtendedExitQualification {
661 #[bits(4)]
662 pub ty: TdxExtendedExitQualificationType,
663 #[bits(60)]
664 _reserved: u64,
665}
666
667open_enum! {
668 pub enum TdxExtendedExitQualificationType: u8 {
669 NONE = 0,
670 PENDING_EPT_VIOLATION = 6,
671 }
672}
673
674impl TdxExtendedExitQualificationType {
675 const fn from_bits(value: u64) -> Self {
676 Self(value as u8)
677 }
678
679 const fn into_bits(self) -> u64 {
680 self.0 as u64
681 }
682}
683
684#[repr(C)]
687#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
688pub struct TdxL2EnterGuestState {
689 pub gps: [u64; 16],
691 pub rflags: u64,
692 pub rip: u64,
693 pub ssp: u64,
694 pub rvi: u8, pub svi: u8, pub reserved: [u8; 6],
697}
698
699pub enum TdxGp {}
700impl TdxGp {
701 pub const RAX: usize = 0;
702 pub const RCX: usize = 1;
703 pub const RDX: usize = 2;
704 pub const RBX: usize = 3;
705 pub const RSP: usize = 4;
706 pub const RBP: usize = 5;
707 pub const RSI: usize = 6;
708 pub const RDI: usize = 7;
709 pub const R8: usize = 8;
710 pub const R9: usize = 9;
711 pub const R10: usize = 10;
712 pub const R11: usize = 11;
713 pub const R12: usize = 12;
714 pub const R13: usize = 13;
715 pub const R14: usize = 14;
716 pub const R15: usize = 15;
717}
718
719#[bitfield(u64)]
720pub struct TdxGlaListInfo {
721 #[bits(9)]
722 pub first_entry: u64,
723 #[bits(3)]
724 _reserved_z0: u64,
725 #[bits(40)]
726 pub list_gpa: u64,
727 #[bits(10)]
728 pub num_entries: u64,
729 #[bits(2)]
730 _reserved_z1: u64,
731}
732
733#[bitfield(u64)]
734pub struct TdGlaVmAndFlags {
735 pub list: bool,
736 #[bits(51)]
737 _reserved_z0: u64,
738 #[bits(2)]
739 pub vm_index: u64,
740 #[bits(10)]
741 _reserved_z1: u64,
742}
743
744#[bitfield(u64)]
745#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
746pub struct TdxVmFlags {
747 #[bits(2)]
748 pub invd_translations: u8,
749
750 #[bits(50)]
751 _reserved: u64,
752
753 #[bits(2)]
755 pub vm_index: u8,
756
757 #[bits(10)]
758 _reserved_2: u64,
759}
760
761pub const TDX_VP_ENTER_INVD_INVEPT: u8 = 1;
762pub const TDX_VP_ENTER_INVD_INVVPID: u8 = 2;
763pub const TDX_VP_ENTER_INVD_INVVPID_NON_GLOBAL: u8 = 3;
764
765#[repr(C)]
768#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
769pub struct TdReport {
770 pub report_mac_struct: ReportMac,
772 pub tee_tcb_info: TeeTcbInfo,
774 pub _reserved: [u8; 17],
776 pub td_info: TdInfo,
778}
779
780static_assertions::const_assert_eq!(TDX_REPORT_SIZE, size_of::<TdReport>());
781
782#[repr(C)]
784#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
785pub struct ReportMac {
786 pub report_type: ReportType,
788 pub _reserved0: [u8; 12],
790 pub cpu_svn: [u8; 16],
792 pub tee_tcb_info_hash: [u8; 48],
794 pub tee_info_hash: [u8; 48],
796 pub report_data: [u8; TDX_REPORT_DATA_SIZE],
798 pub _reserved1: [u8; 32],
800 pub mac: [u8; 32],
802}
803
804#[repr(C)]
806#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
807pub struct ReportType {
808 pub tee_type: u8,
812 pub sub_type: u8,
815 pub version: u8,
820 pub _reserved: u8,
822}
823
824#[repr(C)]
826#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
827pub struct TeeTcbInfo {
828 pub valid: [u8; 8],
831 pub tee_tcb_svn: TeeTcbSvn,
834 pub mr_seam: [u8; 48],
837 pub mr_signer_seam: [u8; 48],
839 pub attributes: [u8; 8],
841 pub tee_tcb_svn2: TeeTcbSvn,
843 pub reserved: [u8; 95],
845}
846
847#[repr(C)]
849#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
850pub struct TeeTcbSvn {
851 pub tdx_module_svn_minor: u8,
853 pub tdx_module_svn_major: u8,
855 pub seam_last_patch_svn: u8,
857 pub _reserved: [u8; 13],
859}
860
861#[repr(C)]
863#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
864pub struct TdInfo {
865 pub td_info_base: TdInfoBase,
867 pub td_info_extension: [u8; 64],
869}
870
871pub type Rtmr = [u8; 48];
873
874#[bitfield(u64)]
876#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
877pub struct TdAttributes {
878 #[bits(1)]
879 pub debug: bool,
880 #[bits(3)]
881 _reserved1: u8,
882 #[bits(1)]
883 pub hgs_plus_prof: bool,
884 #[bits(1)]
885 pub perf_prof: bool,
886 #[bits(1)]
887 pub pmt_prof: bool,
888 #[bits(9)]
889 _reserved2: u16,
890 #[bits(7)]
891 _reserved_p: u8,
892 #[bits(4)]
893 _reserved_n: u8,
894 #[bits(1)]
895 pub lass: bool,
896 #[bits(1)]
897 pub sept_ve_disable: bool,
898 #[bits(1)]
899 pub migratable: bool,
900 #[bits(1)]
901 pub pks: bool,
902 #[bits(1)]
903 pub kl: bool,
904 #[bits(24)]
905 _reserved3: u32,
906 #[bits(6)]
907 _reserved4: u32,
908 #[bits(1)]
909 pub tpa: bool,
910 #[bits(1)]
911 pub perfmon: bool,
912}
913
914#[repr(C)]
916#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
917pub struct TdInfoBase {
918 pub attributes: TdAttributes,
920 pub xfam: [u8; 8],
922 pub mr_td: [u8; 48],
924 pub mr_config_id: [u8; 48],
927 pub mr_owner: [u8; 48],
929 pub mr_owner_config: [u8; 48],
932 pub rtmr: [Rtmr; 4],
934 pub servd_hash: [u8; 48],
936}
937
938#[bitfield(u64)]
945#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
946pub struct TdxKeyPolicy {
947 pub mr_td: bool,
949 _reserved0: bool,
951 pub mr_owner: bool,
953 pub mr_config_id: bool,
955 pub mr_owner_config: bool,
957 #[bits(27)]
959 _reserved1: u32,
960 #[bits(16)]
963 pub rtmr: u16,
964 #[bits(16)]
966 _reserved2: u16,
967}
968
969pub const TDX_KEY_NAME_SEAL: u16 = 0;
971
972pub const TDX_KEY_SIZE_128: u8 = 0;
974
975pub const TDX_KEY_SIZE_256: u8 = 1;
977
978#[repr(C)]
985#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes)]
986pub struct TdKeyRequest {
987 pub key_name: u16,
990 pub sw_key_name: u8,
992 pub key_size: u8,
995 pub _reserved0: [u8; 4],
997 pub key_policy: TdxKeyPolicy,
1000 pub attributes_mask: u64,
1003 pub xfam_mask: u64,
1005 pub cpu_svn: [u8; 16],
1007 pub tee_tcb_svn: [u8; 16],
1009 pub isv_svn: u16,
1011 pub mr_config_svn: u16,
1013 pub mr_owner_config_svn: u16,
1015 pub salt: [u8; 32],
1018 pub _reserved1: [u8; 26],
1020}
1021
1022static_assertions::const_assert_eq!(TDX_TDKEYREQUEST_SIZE, size_of::<TdKeyRequest>());