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 TDI_RD = 67,
56 TDI_START = 68,
57 DMAR_ACCEPT = 70,
58 TDI_MMIO_ACCEPT = 71,
59 }
60}
61
62#[bitfield(u64)]
63pub struct TdConfigFlags {
64 pub gpaw: bool,
65 pub flexible_pending_ve: bool,
66 pub no_rbp_mod: bool,
67 pub maxpa_virt: bool,
68 pub maxgpa_virt: bool,
69 pub tdx_connect: bool,
70 pub page_release: bool,
71 pub sealing: bool,
72 #[bits(56)]
73 pub reserved: u64,
74}
75
76pub type TdgVmRdResult = u64;
77
78#[repr(u8)]
80#[derive(Clone, Copy, Debug, PartialEq, Eq)]
81pub enum TdgMemPageLevel {
82 Size4k = 0,
83 Size2Mb = 1,
84 Size1Gb = 2,
85}
86
87impl TdgMemPageLevel {
88 const fn from_bits(value: u64) -> Self {
89 match value {
90 0 => Self::Size4k,
91 1 => Self::Size2Mb,
92 2 => Self::Size1Gb,
93 _ => panic!("invalid TdgMemPageLevel value"),
94 }
95 }
96
97 const fn into_bits(self) -> u64 {
98 self as u64
99 }
100}
101
102#[bitfield(u16)]
104#[derive(PartialEq, Eq)]
105pub struct GpaVmAttributes {
106 pub read: bool,
107 pub write: bool,
108 pub kernel_execute: bool,
109 pub user_execute: bool,
110 #[bits(3)]
111 reserved: u8,
112 suppress_ve: bool,
113 #[bits(7)]
114 reserved2: u8,
115 pub valid: bool,
116}
117
118impl GpaVmAttributes {
120 pub const FULL_ACCESS: Self = Self::new()
121 .with_read(true)
122 .with_write(true)
123 .with_kernel_execute(true)
124 .with_user_execute(true)
125 .with_valid(true);
126}
127
128#[bitfield(u16)]
130pub struct GpaVmAttributesMask {
131 pub read: bool,
132 pub write: bool,
133 pub kernel_execute: bool,
134 pub user_execute: bool,
135 #[bits(3)]
136 reserved: u8,
137 pub suppress_ve: bool,
138 #[bits(7)]
139 reserved2: u8,
140 pub inv_ept: bool,
142}
143
144impl GpaVmAttributesMask {
145 pub const ALL_CHANGED: Self = Self::new()
146 .with_read(true)
147 .with_write(true)
148 .with_kernel_execute(true)
149 .with_user_execute(true);
150}
151
152#[bitfield(u64)]
155#[derive(PartialEq, Eq)]
156pub struct TdgMemPageGpaAttr {
157 #[bits(16)]
159 pub l1: GpaVmAttributes,
160 #[bits(16)]
162 pub l2_vm1: GpaVmAttributes,
163 #[bits(16)]
165 pub l2_vm2: GpaVmAttributes,
166 #[bits(16)]
167 pub l2_vm3: GpaVmAttributes,
168}
169
170#[bitfield(u64)]
171pub struct TdgMemPageAcceptRcx {
172 #[bits(3)]
173 pub level: TdgMemPageLevel,
174 #[bits(9)]
175 pub reserved: u64,
176 #[bits(40)]
178 pub gpa_page_number: u64,
179 #[bits(12)]
180 pub reserved2: u64,
181}
182
183#[bitfield(u64)]
184pub struct TdgMemPageReleaseRcx {
185 #[bits(3)]
186 pub level: TdgMemPageLevel,
187 #[bits(9)]
188 pub reserved: u64,
189 #[bits(40)]
191 pub gpa_page_number: u64,
192 #[bits(12)]
193 pub reserved2: u64,
194}
195
196#[bitfield(u64)]
197pub struct TdgMemPageReleaseRcxResult {
198 #[bits(3)]
199 pub level: TdgMemPageLevel,
200 #[bits(9)]
201 pub reserved: u64,
202 #[bits(40)]
204 pub gpa_page_number: u64,
205 #[bits(9)]
206 pub reserved2: u64,
207 #[bits(1)]
208 pub mmio: bool,
209 #[bits(1)]
210 pub pending: bool,
211 #[bits(1)]
212 pub reserved3: u8,
213}
214
215#[bitfield(u64)]
216pub struct TdgMemPageAttrGpaMappingReadRcxResult {
217 #[bits(3)]
218 pub level: TdgMemPageLevel,
219 #[bits(9)]
220 pub reserved: u64,
221 #[bits(40)]
223 pub gpa_page_number: u64,
224 #[bits(9)]
225 pub reserved2: u64,
226 #[bits(1)]
229 pub mmio: bool,
230 #[bits(1)]
234 pub pending: bool,
235 #[bits(1)]
236 pub reserved3: u8,
237}
238
239#[bitfield(u64)]
241#[derive(PartialEq, Eq)]
242pub struct TdgMemPageAttrWriteRcx {
243 #[bits(3)]
244 pub level: TdgMemPageLevel,
245 #[bits(9)]
246 pub reserved: u64,
247 #[bits(40)]
249 pub gpa_page_number: u64,
250 #[bits(12)]
251 pub reserved2: u64,
252}
253
254#[bitfield(u64)]
256pub struct TdgMemPageAttrWriteR8 {
257 #[bits(16)]
258 pub reserved: u64,
259 #[bits(16)]
261 pub l2_vm1: GpaVmAttributesMask,
262 #[bits(16)]
264 pub l2_vm2: GpaVmAttributesMask,
265 #[bits(16)]
267 pub l2_vm3: GpaVmAttributesMask,
268}
269
270#[bitfield(u64)]
273pub struct DmarTarget {
274 pub vm_idx: u8,
275 #[bits(56)]
276 pub reserved: u64,
277}
278
279#[bitfield(u64)]
282pub struct TdgTdiMmioAcceptRcx {
283 #[bits(3)]
284 pub level: TdgMemPageLevel,
285 #[bits(9)]
286 pub reserved: u64,
287 #[bits(40)]
289 pub gpa_page_number: u64,
290 #[bits(12)]
291 pub reserved2: u64,
292}
293
294#[bitfield(u64)]
297pub struct TdgTdiMmioAcceptR9 {
298 pub range_size: u32,
300 pub range_offset: u32,
302}
303
304open_enum! {
305 pub enum TdiRdField: u64 {
307 GET_TDISP_VERSION = 0x01,
308 GET_TDISP_STATE = 0x02,
309 GET_TDISP_REPORT_HASH = 0x03,
310 GET_DEVICE_ATTESTATION_INFO_HASH = 0x04,
311 GET_BIND_SESSION_ID = 0x05,
312 }
313}
314
315#[bitfield(u32)]
318pub struct TdxFunctionId {
319 #[bits(16)]
321 pub requester_id: u16,
322 #[bits(8)]
324 pub requester_segment: u8,
325 pub segment_valid: bool,
327 #[bits(7)]
328 pub reserved: u8,
329}
330
331open_enum! {
332 pub enum TdispInterfaceState: u64 {
338 CONFIG_UNLOCKED = 0,
339 CONFIG_LOCKED = 1,
340 RUN = 2,
341 ERROR = 3,
342 }
343}
344
345#[repr(u64)]
348pub enum TdVmCallSubFunction {
349 IoInstr = 0x1e,
350 RdMsr = 0x1f,
351 WrMsr = 0x20,
352 MapGpa = 0x10001,
353}
354
355open_enum! {
356 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
358 pub enum TdCallResultCode: u32 {
359 SUCCESS = 0x00000000,
360 NON_RECOVERABLE_VCPU = 0x40000001,
361 NON_RECOVERABLE_TD = 0x60000002,
362 INTERRUPTED_RESUMABLE = 0x80000003,
363 INTERRUPTED_RESTARTABLE = 0x80000004,
364 NON_RECOVERABLE_TD_NON_ACCESSIBLE = 0x60000005,
365 INVALID_RESUMPTION = 0xC0000006,
366 NON_RECOVERABLE_TD_WRONG_APIC_MODE = 0xE0000007,
367 CROSS_TD_FAULT = 0x80000008,
368 CROSS_TD_TRAP = 0x90000009,
369 NON_RECOVERABLE_TD_CORRUPTED_MD = 0x6000000A,
370 OPERAND_INVALID = 0xC0000100,
371 OPERAND_ADDR_RANGE_ERROR = 0xC0000101,
372 OPERAND_BUSY = 0x80000200,
373 PREVIOUS_TLB_EPOCH_BUSY = 0x80000201,
374 SYS_BUSY = 0x80000202,
375 RND_NO_ENTROPY = 0x80000203,
376 OPERAND_BUSY_HOST_PRIORITY = 0x80000204,
377 HOST_PRIORITY_BUSY_TIMEOUT = 0x90000205,
378 PAGE_METADATA_INCORRECT = 0xC0000300,
379 PAGE_ALREADY_FREE = 0x00000301,
380 PAGE_NOT_OWNED_BY_TD = 0xC0000302,
381 PAGE_NOT_FREE = 0xC0000303,
382 TD_ASSOCIATED_PAGES_EXIST = 0xC0000400,
383 SYS_INIT_NOT_PENDING = 0xC0000500,
384 SYS_LP_INIT_NOT_DONE = 0xC0000502,
385 SYS_LP_INIT_DONE = 0xC0000503,
386 SYS_NOT_READY = 0xC0000505,
387 SYS_SHUTDOWN = 0xC0000506,
388 SYS_KEY_CONFIG_NOT_PENDING = 0xC0000507,
389 SYS_STATE_INCORRECT = 0xC0000508,
390 SYS_INVALID_HANDOFF = 0xC0000509,
391 SYS_INCOMPATIBLE_SIGSTRUCT = 0xC000050A,
392 SYS_LP_INIT_NOT_PENDING = 0xC000050B,
393 SYS_CONFIG_NOT_PENDING = 0xC000050C,
394 INCOMPATIBLE_SEAM_CAPABILITIES = 0xC000050D,
395 TD_FATAL = 0xE0000604,
396 TD_NON_DEBUG = 0xC0000605,
397 TDCS_NOT_ALLOCATED = 0xC0000606,
398 LIFECYCLE_STATE_INCORRECT = 0xC0000607,
399 OP_STATE_INCORRECT = 0xC0000608,
400 NO_VCPUS = 0xC0000609,
401 TDCX_NUM_INCORRECT = 0xC0000610,
402 VCPU_STATE_INCORRECT = 0xC0000700,
403 VCPU_ASSOCIATED = 0x80000701,
404 VCPU_NOT_ASSOCIATED = 0x80000702,
405 NO_VALID_VE_INFO = 0xC0000704,
406 MAX_VCPUS_EXCEEDED = 0xC0000705,
407 TSC_ROLLBACK = 0xC0000706,
408 TD_VMCS_FIELD_NOT_INITIALIZED = 0xC0000730,
409 MCS_FIELD_ERROR = 0xC0000731,
410 KEY_GENERATION_FAILED = 0x80000800,
411 TD_KEYS_NOT_CONFIGURED = 0x80000810,
412 KEY_STATE_INCORRECT = 0xC0000811,
413 KEY_CONFIGURED = 0x00000815,
414 WBCACHE_NOT_COMPLETE = 0x80000817,
415 HKID_NOT_FREE = 0xC0000820,
416 NO_HKID_READY_TO_WBCACHE = 0x00000821,
417 WBCACHE_RESUME_ERROR = 0xC0000823,
418 FLUSHVP_NOT_DONE = 0x80000824,
419 NUM_ACTIVATED_HKIDS_NOT_SUPPORTED = 0xC0000825,
420 INCORRECT_CPUID_VALUE = 0xC0000900,
421 LIMIT_CPUID_MAXVAL_SET = 0xC0000901,
422 INCONSISTENT_CPUID_FIELD = 0xC0000902,
423 CPUID_MAX_SUBLEAVES_UNRECOGNIZED = 0xC0000903,
424 CPUID_LEAF_1F_FORMAT_UNRECOGNIZED = 0xC0000904,
425 INVALID_WBINVD_SCOPE = 0xC0000905,
426 INVALID_PKG_ID = 0xC0000906,
427 ENABLE_MONITOR_FSM_NOT_SET = 0xC0000907,
428 CPUID_LEAF_NOT_SUPPORTED = 0xC0000908,
429 SMRR_NOT_LOCKED = 0xC0000910,
430 INVALID_SMRR_CONFIGURATION = 0xC0000911,
431 SMRR_OVERLAPS_CMR = 0xC0000912,
432 SMRR_LOCK_NOT_SUPPORTED = 0xC0000913,
433 SMRR_NOT_SUPPORTED = 0xC0000914,
434 INCONSISTENT_MSR = 0xC0000920,
435 INCORRECT_MSR_VALUE = 0xC0000921,
436 SEAMREPORT_NOT_AVAILABLE = 0xC0000930,
437 SEAMDB_GETREF_NOT_AVAILABLE = 0xC0000931,
438 SEAMDB_REPORT_NOT_AVAILABLE = 0xC0000932,
439 SEAMVERIFYREPORT_NOT_AVAILABLE = 0xC0000933,
440 INVALID_TDMR = 0xC0000A00,
441 NON_ORDERED_TDMR = 0xC0000A01,
442 TDMR_OUTSIDE_CMRS = 0xC0000A02,
443 TDMR_ALREADY_INITIALIZED = 0x00000A03,
444 INVALID_PAMT = 0xC0000A10,
445 PAMT_OUTSIDE_CMRS = 0xC0000A11,
446 PAMT_OVERLAP = 0xC0000A12,
447 INVALID_RESERVED_IN_TDMR = 0xC0000A20,
448 NON_ORDERED_RESERVED_IN_TDMR = 0xC0000A21,
449 CMR_LIST_INVALID = 0xC0000A22,
450 EPT_WALK_FAILED = 0xC0000B00,
451 EPT_ENTRY_FREE = 0xC0000B01,
452 EPT_ENTRY_NOT_FREE = 0xC0000B02,
453 EPT_ENTRY_NOT_PRESENT = 0xC0000B03,
454 EPT_ENTRY_NOT_LEAF = 0xC0000B04,
455 EPT_ENTRY_LEAF = 0xC0000B05,
456 GPA_RANGE_NOT_BLOCKED = 0xC0000B06,
457 GPA_RANGE_ALREADY_BLOCKED = 0x00000B07,
458 TLB_TRACKING_NOT_DONE = 0xC0000B08,
459 EPT_INVALID_PROMOTE_CONDITIONS = 0xC0000B09,
460 PAGE_ALREADY_ACCEPTED = 0x00000B0A,
461 PAGE_SIZE_MISMATCH = 0xC0000B0B,
462 GPA_RANGE_BLOCKED = 0xC0000B0C,
463 EPT_ENTRY_STATE_INCORRECT = 0xC0000B0D,
464 EPT_PAGE_NOT_FREE = 0xC0000B0E,
465 L2_SEPT_WALK_FAILED = 0xC0000B0F,
466 L2_SEPT_ENTRY_NOT_FREE = 0xC0000B10,
467 PAGE_ATTR_INVALID = 0xC0000B11,
468 L2_SEPT_PAGE_NOT_PROVIDED = 0xC0000B12,
469 METADATA_FIELD_ID_INCORRECT = 0xC0000C00,
470 METADATA_FIELD_NOT_WRITABLE = 0xC0000C01,
471 METADATA_FIELD_NOT_READABLE = 0xC0000C02,
472 METADATA_FIELD_VALUE_NOT_VALID = 0xC0000C03,
473 METADATA_LIST_OVERFLOW = 0xC0000C04,
474 INVALID_METADATA_LIST_HEADER = 0xC0000C05,
475 REQUIRED_METADATA_FIELD_MISSING = 0xC0000C06,
476 METADATA_ELEMENT_SIZE_INCORRECT = 0xC0000C07,
477 METADATA_LAST_ELEMENT_INCORRECT = 0xC0000C08,
478 METADATA_FIELD_CURRENTLY_NOT_WRITABLE = 0xC0000C09,
479 METADATA_WR_MASK_NOT_VALID = 0xC0000C0A,
480 METADATA_FIRST_FIELD_ID_IN_CONTEXT = 0x00000C0B,
481 METADATA_FIELD_SKIP = 0x00000C0C,
482 SERVTD_ALREADY_BOUND_FOR_TYPE = 0xC0000D00,
483 SERVTD_TYPE_MISMATCH = 0xC0000D01,
484 SERVTD_ATTR_MISMATCH = 0xC0000D02,
485 SERVTD_INFO_HASH_MISMATCH = 0xC0000D03,
486 SERVTD_UUID_MISMATCH = 0xC0000D04,
487 SERVTD_NOT_BOUND = 0xC0000D05,
488 SERVTD_BOUND = 0xC0000D06,
489 TARGET_UUID_MISMATCH = 0xC0000D07,
490 TARGET_UUID_UPDATED = 0xC0000D08,
491 INVALID_MBMD = 0xC0000E00,
492 INCORRECT_MBMD_MAC = 0xC0000E01,
493 NOT_WRITE_BLOCKED = 0xC0000E02,
494 ALREADY_WRITE_BLOCKED = 0x00000E03,
495 NOT_EXPORTED = 0xC0000E04,
496 MIGRATION_STREAM_STATE_INCORRECT = 0xC0000E05,
497 MAX_MIGS_NUM_EXCEEDED = 0xC0000E06,
498 EXPORTED_DIRTY_PAGES_REMAIN = 0xC0000E07,
499 MIGRATION_DECRYPTION_KEY_NOT_SET = 0xC0000E08,
500 TD_NOT_MIGRATABLE = 0xC0000E09,
501 PREVIOUS_EXPORT_CLEANUP_INCOMPLETE = 0xC0000E0A,
502 NUM_MIGS_HIGHER_THAN_CREATED = 0xC0000E0B,
503 IMPORT_MISMATCH = 0xC0000E0C,
504 MIGRATION_EPOCH_OVERFLOW = 0xC0000E0D,
505 MAX_EXPORTS_EXCEEDED = 0xC0000E0E,
506 INVALID_PAGE_MAC = 0xC0000E0F,
507 MIGRATED_IN_CURRENT_EPOCH = 0xC0000E10,
508 DISALLOWED_IMPORT_OVER_REMOVED = 0xC0000E11,
509 SOME_VCPUS_NOT_MIGRATED = 0xC0000E12,
510 ALL_VCPUS_IMPORTED = 0xC0000E13,
511 MIN_MIGS_NOT_CREATED = 0xC0000E14,
512 VCPU_ALREADY_EXPORTED = 0xC0000E15,
513 INVALID_MIGRATION_DECRYPTION_KEY = 0xC0000E16,
514 INVALID_CPUSVN = 0xC0001000,
515 INVALID_REPORTMACSTRUCT = 0xC0001001,
516 L2_EXIT_HOST_ROUTED_ASYNC = 0x00001100,
517 L2_EXIT_HOST_ROUTED_TDVMCALL = 0x00001101,
518 L2_EXIT_PENDING_INTERRUPT = 0x00001102,
519 PENDING_INTERRUPT = 0x00001120,
520 TD_EXIT_BEFORE_L2_ENTRY = 0x00001140,
521 TD_EXIT_ON_L2_VM_EXIT = 0x00001141,
522 TD_EXIT_ON_L2_TO_L1 = 0x00001142,
523 GLA_NOT_CANONICAL = 0xC0001160,
524 DMAR_INVALID_MAPPING_STATE = 0xC0000F07,
528 TDI_INVALID_STATE = 0xC0000F11,
529 IDE_STREAM_INVALID_STATE = 0xC0000F24,
530 MMIO_TDI_OWNER_MISMATCH = 0xC0000F27,
531 TDI_NOT_PRESENT = 0xC0000F40,
532 TDI_INVALID_METADATA = 0xC0000F41,
533 MMIO_PAGE_NOT_IN_ASSOC_RANGE = 0xC0000F4C,
534 MMIO_INVALID_HPA_OFFSET = 0xC0000F4D,
535 }
536}
537
538impl TdCallResultCode {
539 const fn from_bits(value: u64) -> Self {
540 Self(value as u32)
541 }
542
543 const fn into_bits(self) -> u64 {
544 self.0 as u64
545 }
546}
547
548#[bitfield(u64)]
550pub struct TdCallResult {
551 pub details: u32,
552 #[bits(32)]
553 pub code: TdCallResultCode,
554}
555
556open_enum! {
557 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
559 pub enum TdVmCallR10Result: u64 {
560 SUCCESS = 0,
561 RETRY = 1,
562 OPERAND_INVALID = 0x80000000_00000000,
563 GPA_INUSE = 0x80000000_00000001,
564 ALIGN_ERROR = 0x80000000_00000002,
565 }
566}
567
568#[repr(u64)]
570#[derive(Debug)]
571pub enum FieldSize {
572 Invalid = 0,
573 Size16Bit = 1,
574 Size32Bit = 2,
575 Size64Bit = 3,
576}
577
578impl FieldSize {
579 const fn from_bits(value: u64) -> Self {
580 match value {
581 0 => FieldSize::Invalid,
582 1 => FieldSize::Size16Bit,
583 2 => FieldSize::Size32Bit,
584 3 => FieldSize::Size64Bit,
585 _ => panic!("Invalid field size"),
586 }
587 }
588
589 const fn into_bits(self) -> u64 {
590 self as u64
591 }
592}
593
594open_enum! {
595 pub enum TdVpsClassCode: u8 {
596 TD_VMCS = 0,
597 VAPIC = 1,
598 VE_INFO = 2,
599 GUEST_GPR_STATE = 16,
600 GUEST_STATE = 17,
601 GUEST_EXT_STATE = 18,
602 GUEST_MSR_STATE = 19,
603 MANAGEMENT = 32,
604 CPUID_CONTROL = 33,
605 EPT_VIOLATION_LOG = 34,
606 VMCS_1 = 36,
607 MSR_BITMAPS_1 = 37,
608 MSR_BITMAPS_SHADOW_1 = 38,
609 VMCS_2 = 44,
610 MSR_BITMAPS_2 = 45,
611 MSR_BITMAPS_SHADOW_2 = 46,
612 VMCS_3 = 52,
613 }
614}
615
616open_enum! {
617 pub enum TdxContextCode: u8 {
618 PLATFORM = 0,
619 TD = 1,
620 TD_VCPU = 2,
621 }
622}
623
624impl TdxContextCode {
625 const fn from_bits(value: u64) -> Self {
626 Self(value as u8)
627 }
628 const fn into_bits(self) -> u64 {
629 self.0 as u64
630 }
631}
632
633pub const TDX_FIELD_CODE_L2_CTLS_VM1: TdxExtendedFieldCode =
635 TdxExtendedFieldCode(0xA020000300000051);
636pub const TDX_FIELD_CODE_L2_CTLS_VM2: TdxExtendedFieldCode =
637 TdxExtendedFieldCode(0xA020000300000052);
638
639pub const TDX_FIELD_CODE_CONFIG_FLAGS: TdxExtendedFieldCode =
641 TdxExtendedFieldCode(0x9110000300000016);
642
643pub const TDX_FIELD_CODE_TD_CTLS: TdxExtendedFieldCode = TdxExtendedFieldCode(0x1110000300000017);
646
647pub const TDX_FIELD_ID_TDX_FEATURES0: u64 = 0x0A00000300000008;
650
651#[bitfield(u64)]
658#[derive(PartialEq, Eq)]
659pub struct TdxFeatures0 {
660 #[bits(12)]
661 _reserved0: u64,
662 pub sealing: bool,
665 #[bits(9)]
666 _reserved1: u64,
667 pub td_signing_and_svn: bool,
670 #[bits(27)]
671 _reserved2: u64,
672 pub sealkey_128: bool,
674 #[bits(13)]
675 _reserved3: u64,
676}
677
678#[bitfield(u64)]
681#[derive(PartialEq, Eq)]
682pub struct TdCtls {
683 pub pending_ve_disable: bool,
685 pub enum_topology: bool,
687 pub virt_cpuid2: bool,
689 pub reduce_ve: bool,
691 pub enable_hw_seal_keys: bool,
695 #[bits(58)]
696 _reserved: u64,
697 pub lock: bool,
699}
700
701#[bitfield(u64)]
704#[derive(PartialEq, Eq)]
705pub struct TdxExtendedFieldCode {
706 #[bits(24)]
707 pub field_code: u32,
708 #[bits(8)]
709 _reserved0: u64,
710 #[bits(2)]
711 pub field_size: FieldSize,
712 #[bits(4)]
713 pub last_element: u8,
714 #[bits(9)]
715 pub last_field: u16,
716 #[bits(3)]
717 _reserved1: u64,
718 pub increment_size: bool,
719 pub write_mask_valid: bool,
720 #[bits(3)]
721 pub context_code: TdxContextCode,
722 #[bits(1)]
723 _reserved2: u64,
724 #[bits(6)]
725 pub class_code: u8,
726 #[bits(1)]
727 _reserved3: u64,
728 pub non_arch: bool,
729}
730
731#[bitfield(u64)]
733pub struct TdxInstructionInfo {
734 pub info: u32,
735 pub length: u32,
736}
737
738#[bitfield(u64)]
739pub struct TdxL2Ctls {
740 pub enable_shared_ept: bool,
741 pub enable_tdvmcall: bool,
742 #[bits(62)]
743 pub reserved: u64,
744}
745
746#[bitfield(u64)]
747pub struct TdxVpEnterRaxResult {
748 #[bits(32)]
750 pub vmx_exit: vmx::VmxExit,
751 #[bits(32)]
753 pub tdx_exit: TdCallResultCode,
754}
755
756#[bitfield(u64)]
757pub struct TdxExtendedExitQualification {
758 #[bits(4)]
759 pub ty: TdxExtendedExitQualificationType,
760 #[bits(60)]
761 _reserved: u64,
762}
763
764open_enum! {
765 pub enum TdxExtendedExitQualificationType: u8 {
766 NONE = 0,
767 PENDING_EPT_VIOLATION = 6,
768 }
769}
770
771impl TdxExtendedExitQualificationType {
772 const fn from_bits(value: u64) -> Self {
773 Self(value as u8)
774 }
775
776 const fn into_bits(self) -> u64 {
777 self.0 as u64
778 }
779}
780
781#[repr(C)]
784#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
785pub struct TdxL2EnterGuestState {
786 pub gps: [u64; 16],
788 pub rflags: u64,
789 pub rip: u64,
790 pub ssp: u64,
791 pub rvi: u8, pub svi: u8, pub reserved: [u8; 6],
794}
795
796pub enum TdxGp {}
797impl TdxGp {
798 pub const RAX: usize = 0;
799 pub const RCX: usize = 1;
800 pub const RDX: usize = 2;
801 pub const RBX: usize = 3;
802 pub const RSP: usize = 4;
803 pub const RBP: usize = 5;
804 pub const RSI: usize = 6;
805 pub const RDI: usize = 7;
806 pub const R8: usize = 8;
807 pub const R9: usize = 9;
808 pub const R10: usize = 10;
809 pub const R11: usize = 11;
810 pub const R12: usize = 12;
811 pub const R13: usize = 13;
812 pub const R14: usize = 14;
813 pub const R15: usize = 15;
814}
815
816#[bitfield(u64)]
817pub struct TdxGlaListInfo {
818 #[bits(9)]
819 pub first_entry: u64,
820 #[bits(3)]
821 _reserved_z0: u64,
822 #[bits(40)]
823 pub list_gpa: u64,
824 #[bits(10)]
825 pub num_entries: u64,
826 #[bits(2)]
827 _reserved_z1: u64,
828}
829
830#[bitfield(u64)]
831pub struct TdGlaVmAndFlags {
832 pub list: bool,
833 #[bits(51)]
834 _reserved_z0: u64,
835 #[bits(2)]
836 pub vm_index: u64,
837 #[bits(10)]
838 _reserved_z1: u64,
839}
840
841#[bitfield(u64)]
842#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
843pub struct TdxVmFlags {
844 #[bits(2)]
845 pub invd_translations: u8,
846
847 #[bits(50)]
848 _reserved: u64,
849
850 #[bits(2)]
852 pub vm_index: u8,
853
854 #[bits(10)]
855 _reserved_2: u64,
856}
857
858pub const TDX_VP_ENTER_INVD_INVEPT: u8 = 1;
859pub const TDX_VP_ENTER_INVD_INVVPID: u8 = 2;
860pub const TDX_VP_ENTER_INVD_INVVPID_NON_GLOBAL: u8 = 3;
861
862#[repr(C)]
865#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
866pub struct TdReport {
867 pub report_mac_struct: ReportMac,
869 pub tee_tcb_info: TeeTcbInfo,
871 pub _reserved: [u8; 17],
873 pub td_info: TdInfo,
875}
876
877static_assertions::const_assert_eq!(TDX_REPORT_SIZE, size_of::<TdReport>());
878
879#[repr(C)]
881#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
882pub struct ReportMac {
883 pub report_type: ReportType,
885 pub _reserved0: [u8; 12],
887 pub cpu_svn: [u8; 16],
889 pub tee_tcb_info_hash: [u8; 48],
891 pub tee_info_hash: [u8; 48],
893 pub report_data: [u8; TDX_REPORT_DATA_SIZE],
895 pub _reserved1: [u8; 32],
897 pub mac: [u8; 32],
899}
900
901#[repr(C)]
903#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
904pub struct ReportType {
905 pub tee_type: u8,
909 pub sub_type: u8,
912 pub version: u8,
917 pub _reserved: u8,
919}
920
921#[repr(C)]
923#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
924pub struct TeeTcbInfo {
925 pub valid: [u8; 8],
928 pub tee_tcb_svn: TeeTcbSvn,
931 pub mr_seam: [u8; 48],
934 pub mr_signer_seam: [u8; 48],
936 pub attributes: [u8; 8],
938 pub tee_tcb_svn2: TeeTcbSvn,
940 pub reserved: [u8; 95],
942}
943
944#[repr(C)]
946#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
947pub struct TeeTcbSvn {
948 pub tdx_module_svn_minor: u8,
950 pub tdx_module_svn_major: u8,
952 pub seam_last_patch_svn: u8,
954 pub _reserved: [u8; 13],
956}
957
958#[repr(C)]
960#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
961pub struct TdInfo {
962 pub td_info_base: TdInfoBase,
964 pub td_info_extension: [u8; 64],
966}
967
968pub type Rtmr = [u8; 48];
970
971#[bitfield(u64)]
973#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
974pub struct TdAttributes {
975 #[bits(1)]
976 pub debug: bool,
977 #[bits(3)]
978 _reserved1: u8,
979 #[bits(1)]
980 pub hgs_plus_prof: bool,
981 #[bits(1)]
982 pub perf_prof: bool,
983 #[bits(1)]
984 pub pmt_prof: bool,
985 #[bits(9)]
986 _reserved2: u16,
987 #[bits(7)]
988 _reserved_p: u8,
989 #[bits(4)]
990 _reserved_n: u8,
991 #[bits(1)]
992 pub lass: bool,
993 #[bits(1)]
994 pub sept_ve_disable: bool,
995 #[bits(1)]
996 pub migratable: bool,
997 #[bits(1)]
998 pub pks: bool,
999 #[bits(1)]
1000 pub kl: bool,
1001 #[bits(24)]
1002 _reserved3: u32,
1003 #[bits(6)]
1004 _reserved4: u32,
1005 #[bits(1)]
1006 pub tpa: bool,
1007 #[bits(1)]
1008 pub perfmon: bool,
1009}
1010
1011#[repr(C)]
1013#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1014pub struct TdInfoBase {
1015 pub attributes: TdAttributes,
1017 pub xfam: [u8; 8],
1019 pub mr_td: [u8; 48],
1021 pub mr_config_id: [u8; 48],
1024 pub mr_owner: [u8; 48],
1026 pub mr_owner_config: [u8; 48],
1029 pub rtmr: [Rtmr; 4],
1031 pub servd_hash: [u8; 48],
1033}
1034
1035#[bitfield(u64)]
1042#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1043pub struct TdxKeyPolicy {
1044 pub mr_td: bool,
1046 _reserved0: bool,
1048 pub mr_owner: bool,
1050 pub mr_config_id: bool,
1052 pub mr_owner_config: bool,
1054 #[bits(27)]
1056 _reserved1: u32,
1057 #[bits(16)]
1060 pub rtmr: u16,
1061 #[bits(16)]
1063 _reserved2: u16,
1064}
1065
1066pub const TDX_KEY_NAME_SEAL: u16 = 0;
1068
1069pub const TDX_KEY_SIZE_128: u8 = 0;
1071
1072pub const TDX_KEY_SIZE_256: u8 = 1;
1074
1075#[repr(C)]
1082#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes)]
1083pub struct TdKeyRequest {
1084 pub key_name: u16,
1087 pub sw_key_name: u8,
1089 pub key_size: u8,
1092 pub _reserved0: [u8; 4],
1094 pub key_policy: TdxKeyPolicy,
1097 pub attributes_mask: u64,
1100 pub xfam_mask: u64,
1102 pub cpu_svn: [u8; 16],
1104 pub tee_tcb_svn: [u8; 16],
1106 pub isv_svn: u16,
1108 pub mr_config_svn: u16,
1110 pub mr_owner_config_svn: u16,
1112 pub salt: [u8; 32],
1115 pub _reserved1: [u8; 26],
1117}
1118
1119static_assertions::const_assert_eq!(TDX_TDKEYREQUEST_SIZE, size_of::<TdKeyRequest>());