1use bitfield_struct::bitfield;
7use zerocopy::FromBytes;
8use zerocopy::Immutable;
9use zerocopy::IntoBytes;
10use zerocopy::KnownLayout;
11
12pub const SEV_INTR_TYPE_EXT: u32 = 0;
14pub const SEV_INTR_TYPE_NMI: u32 = 2;
15pub const SEV_INTR_TYPE_EXCEPT: u32 = 3;
16pub const SEV_INTR_TYPE_SW: u32 = 4;
17
18pub const REG_TWEAK_BITMAP_OFFSET: usize = 0x100;
20pub const REG_TWEAK_BITMAP_SIZE: usize = 0x40;
21
22#[bitfield(u64)]
23#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
24pub struct SevEventInjectInfo {
25 pub vector: u8,
26 #[bits(3)]
27 pub interruption_type: u32,
28 pub deliver_error_code: bool,
29 #[bits(19)]
30 _rsvd1: u64,
31 pub valid: bool,
32 pub error_code: u32,
33}
34
35#[repr(u8)]
36#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
37pub enum Vmpl {
38 Vmpl0 = 0,
39 Vmpl1 = 1,
40 Vmpl2 = 2,
41 Vmpl3 = 3,
42}
43
44impl From<Vmpl> for u8 {
45 fn from(value: Vmpl) -> Self {
46 value as _
47 }
48}
49
50#[repr(C)]
52#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
53pub struct SevSelector {
54 pub selector: u16,
55 pub attrib: u16,
56 pub limit: u32,
57 pub base: u64,
58}
59
60impl SevSelector {
61 pub fn as_u128(&self) -> u128 {
62 ((self.base as u128) << 64)
63 | ((self.limit as u128) << 32)
64 | ((self.attrib as u128) << 16)
65 | self.selector as u128
66 }
67}
68
69impl From<u128> for SevSelector {
70 fn from(val: u128) -> Self {
71 SevSelector {
72 selector: val as u16,
73 attrib: (val >> 16) as u16,
74 limit: (val >> 32) as u32,
75 base: (val >> 64) as u64,
76 }
77 }
78}
79
80#[repr(C)]
82#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
83pub struct SevXmmRegister {
84 low: u64,
85 high: u64,
86}
87
88impl SevXmmRegister {
89 pub fn as_u128(&self) -> u128 {
90 ((self.high as u128) << 64) | self.low as u128
91 }
92}
93
94impl From<u128> for SevXmmRegister {
95 fn from(val: u128) -> Self {
96 SevXmmRegister {
97 low: val as u64,
98 high: (val >> 64) as u64,
99 }
100 }
101}
102
103#[bitfield(u64)]
104#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
105pub struct SevFeatures {
106 pub snp: bool,
107 pub vtom: bool,
108 pub reflect_vc: bool,
109 pub restrict_injection: bool,
110 pub alternate_injection: bool,
111 pub debug_swap: bool,
112 pub prevent_host_ibs: bool,
113 pub snp_btb_isolation: bool,
114 pub vmpl_isss: bool,
115 pub secure_tsc: bool,
116 pub vmgexit_param: bool,
117 pub pmc_virt: bool,
118 pub ibs_virt: bool,
119 rsvd: bool,
120 pub vmsa_reg_prot: bool,
121 pub smt_prot: bool,
122 pub secure_avic: bool,
123 #[bits(47)]
124 _unused: u64,
125}
126
127#[bitfield(u64)]
128#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
129pub struct SevVirtualInterruptControl {
130 pub tpr: u8,
131 pub irq: bool,
132 pub gif: bool,
133 pub intr_shadow: bool,
134 #[bits(5)]
135 _rsvd1: u64,
136 #[bits(4)]
137 pub priority: u64,
138 pub ignore_tpr: bool,
139 #[bits(11)]
140 _rsvd2: u64,
141 pub vector: u8,
142 #[bits(23)]
143 _rsvd3: u64,
144 pub guest_busy: bool,
145}
146
147#[bitfield(u64)]
148#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
149pub struct SevRmpAdjust {
150 pub target_vmpl: u8,
151 pub enable_read: bool,
152 pub enable_write: bool,
153 pub enable_user_execute: bool,
154 pub enable_kernel_execute: bool,
155 #[bits(4)]
156 _rsvd1: u64,
157 pub vmsa: bool,
158 #[bits(47)]
159 _rsvd2: u64,
160}
161
162#[bitfield(u32)]
163#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
164pub struct SevIoAccessInfo {
165 pub read_access: bool,
166 #[bits(1)]
167 reserved1: u32,
168 pub string_access: bool,
169 pub rep_access: bool,
170 pub access_size8: bool,
171 pub access_size16: bool,
172 pub access_size32: bool,
173 pub address_size8: bool,
174 pub address_size16: bool,
175 pub address_size32: bool,
176 #[bits(3)]
177 pub effective_segment: u32,
178 #[bits(3)]
179 rsvd2: u32,
180 pub port: u16,
181}
182
183#[bitfield(u64)]
184#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
185pub struct SevNpfInfo {
186 pub present: bool,
187 pub read_write: bool,
188 pub user: bool,
189 pub reserved_bit_set: bool,
190 pub fetch: bool,
191 #[bits(1)]
192 rsvd5: u64,
193 pub shadow_stack: bool,
194 #[bits(24)]
195 rsvd7_31: u64,
196 pub rmp_failure: bool,
197 pub caused_by_gpa_access: bool,
198 pub caused_by_page_table_access: bool,
199 pub encrypted_access: bool,
200 pub rmp_size_mismatch: bool,
201 pub vmpl_violation: bool,
202 pub npt_supervisor_shadow_stack: bool,
203 #[bits(26)]
204 rsvd38_63: u64,
205}
206
207#[repr(C)]
209#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
210pub struct SevVmsa {
211 pub es: SevSelector,
213 pub cs: SevSelector,
214 pub ss: SevSelector,
215 pub ds: SevSelector,
216 pub fs: SevSelector,
217 pub gs: SevSelector,
218
219 pub gdtr: SevSelector,
221 pub ldtr: SevSelector,
222 pub idtr: SevSelector,
223 pub tr: SevSelector,
224
225 pub pl0_ssp: u64,
227 pub pl1_ssp: u64,
228 pub pl2_ssp: u64,
229 pub pl3_ssp: u64,
230 pub u_cet: u64,
231
232 pub vmsa_reserved1: [u8; 2],
234
235 pub vmpl: u8,
237
238 pub cpl: u8,
240
241 pub vmsa_reserved2: u32,
243
244 pub efer: u64,
246
247 pub vmsa_reserved3: [u32; 26],
249
250 pub xss: u64,
252
253 pub cr4: u64,
255 pub cr3: u64,
256 pub cr0: u64,
257
258 pub dr7: u64,
260 pub dr6: u64,
261
262 pub rflags: u64,
264
265 pub rip: u64,
267
268 pub dr0: u64,
270 pub dr1: u64,
271 pub dr2: u64,
272 pub dr3: u64,
273
274 pub dr0_addr_mask: u64,
276 pub dr1_addr_mask: u64,
277 pub dr2_addr_mask: u64,
278 pub dr3_addr_mask: u64,
279
280 pub vmsa_reserved4: [u64; 3],
282
283 pub rsp: u64,
285
286 pub s_cet: u64,
288 pub ssp: u64,
289 pub interrupt_ssp_table_addr: u64,
290
291 pub rax: u64,
293
294 pub star: u64,
296 pub lstar: u64,
297 pub cstar: u64,
298 pub sfmask: u64,
299
300 pub kernel_gs_base: u64,
302
303 pub sysenter_cs: u64,
305 pub sysenter_esp: u64,
306 pub sysenter_eip: u64,
307
308 pub cr2: u64,
310
311 pub vmsa_reserved5: [u64; 4],
313
314 pub pat: u64,
316
317 pub dbgctl: u64,
319 pub last_branch_from_ip: u64,
320 pub last_branch_to_ip: u64,
321 pub last_excp_from_ip: u64,
322 pub last_excp_to_ip: u64,
323
324 pub vmsa_reserved6: [u64; 9],
326
327 pub spec_ctrl: u64,
329
330 pub pkru: u32,
332
333 pub tsc_aux: u32,
335
336 pub vmsa_reserved7: [u32; 4],
338
339 pub register_protection_nonce: u64,
340
341 pub rcx: u64,
343 pub rdx: u64,
344 pub rbx: u64,
345 pub vmsa_reserved8: u64, pub rbp: u64,
347 pub rsi: u64,
348 pub rdi: u64,
349 pub r8: u64,
350 pub r9: u64,
351 pub r10: u64,
352 pub r11: u64,
353 pub r12: u64,
354 pub r13: u64,
355 pub r14: u64,
356 pub r15: u64,
357
358 pub vmsa_reserved9: [u64; 2],
360
361 pub exit_info1: u64,
363 pub exit_info2: u64,
364 pub exit_int_info: u64,
365
366 pub next_rip: u64,
368
369 pub sev_features: SevFeatures,
371
372 pub v_intr_cntrl: SevVirtualInterruptControl,
374
375 pub guest_error_code: u64,
377
378 pub virtual_tom: u64,
380
381 pub tlb_id: u64,
384 pub pcpu_id: u64,
385
386 pub event_inject: SevEventInjectInfo,
388
389 pub xcr0: u64,
391
392 pub xsave_valid_bitmap: [u8; 16],
394
395 pub x87dp: u64,
397 pub mxcsr: u32,
398 pub x87_ftw: u16,
399 pub x87_fsw: u16,
400 pub x87_fcw: u16,
401 pub x87_op: u16,
402 pub x87_ds: u16,
403 pub x87_cs: u16,
404 pub x87_rip: u64,
405
406 pub x87_registers: [u64; 10],
409
410 pub xmm_registers: [SevXmmRegister; 16],
412
413 pub ymm_registers: [SevXmmRegister; 16],
415}
416
417open_enum::open_enum! {
419 pub enum GhcbInfo: u64 {
420 NORMAL = 0x000,
421 SEV_INFO_RESPONSE = 0x001,
422 SEV_INFO_REQUEST = 0x002,
423 AP_JUMP_TABLE = 0x003,
424 CPUID_REQUEST = 0x004,
425 CPUID_RESPONSE = 0x005,
426 PREFERRED_REQUEST = 0x010,
427 PREFERRED_RESPONSE = 0x011,
428 REGISTER_REQUEST = 0x012,
429 REGISTER_RESPONSE = 0x013,
430 PAGE_STATE_CHANGE = 0x014,
431 PAGE_STATE_UPDATED = 0x015,
432 HYP_FEATURE_REQUEST = 0x080,
433 HYP_FEATURE_RESPONSE = 0x081,
434 SPECIAL_HYPERCALL = 0xF00,
435 SPECIAL_FAST_CALL = 0xF01,
436 HYPERCALL_OUTPUT = 0xF02,
437 SPECIAL_DBGPRINT = 0xF03,
438 SHUTDOWN_REQUEST = 0x100,
439 }
440}
441
442pub const GHCB_DATA_PAGE_STATE_PRIVATE: u64 = 0x001;
443pub const GHCB_DATA_PAGE_STATE_SHARED: u64 = 0x002;
444pub const GHCB_DATA_PAGE_STATE_PSMASH: u64 = 0x003;
445pub const GHCB_DATA_PAGE_STATE_UNSMASH: u64 = 0x004;
446pub const GHCB_DATA_PAGE_STATE_MASK: u64 = 0x00F;
447pub const GHCB_DATA_PAGE_STATE_LARGE_PAGE: u64 = 0x010;
448
449open_enum::open_enum! {
450 pub enum GhcbUsage: u32 {
451 BASE = 0,
452 HYPERCALL = 1,
453 VTL_RETURN = 2,
454 }
455}
456
457#[repr(C)]
460#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
461pub struct GhcbHypercallParameters {
462 pub output_gpa: u64,
463 pub input_control: u64,
464}
465
466pub const GHCB_PAGE_HYPERCALL_PARAMETERS_OFFSET: usize = 4072;
467pub const GHCB_PAGE_HYPERCALL_OUTPUT_OFFSET: usize = 4080;
468
469open_enum::open_enum! {
471 pub enum SevExitCode: u64 {
472 CR0_READ = 0,
473 CR1_READ = 1,
474 CR2_READ = 2,
475 CR3_READ = 3,
476 CR4_READ = 4,
477 CR5_READ = 5,
478 CR6_READ = 6,
479 CR7_READ = 7,
480 CR8_READ = 8,
481 CR9_READ = 9,
482 CR10_READ = 10,
483 CR11_READ = 11,
484 CR12_READ = 12,
485 CR13_READ = 13,
486 CR14_READ = 14,
487 CR15_READ = 15,
488 CR0_WRITE = 16,
489 CR1_WRITE = 17,
490 CR2_WRITE = 18,
491 CR3_WRITE = 19,
492 CR4_WRITE = 20,
493 CR5_WRITE = 21,
494 CR6_WRITE = 22,
495 CR7_WRITE = 23,
496 CR8_WRITE = 24,
497 CR9_WRITE = 25,
498 CR10_WRITE = 26,
499 CR11_WRITE = 27,
500 CR12_WRITE = 28,
501 CR13_WRITE = 29,
502 CR14_WRITE = 30,
503 CR15_WRITE = 31,
504 DR0_READ = 32,
505 DR1_READ = 33,
506 DR2_READ = 34,
507 DR3_READ = 35,
508 DR4_READ = 36,
509 DR5_READ = 37,
510 DR6_READ = 38,
511 DR7_READ = 39,
512 DR8_READ = 40,
513 DR9_READ = 41,
514 DR10_READ = 42,
515 DR11_READ = 43,
516 DR12_READ = 44,
517 DR13_READ = 45,
518 DR14_READ = 46,
519 DR15_READ = 47,
520 DR0_WRITE = 48,
521 DR1_WRITE = 49,
522 DR2_WRITE = 50,
523 DR3_WRITE = 51,
524 DR4_WRITE = 52,
525 DR5_WRITE = 53,
526 DR6_WRITE = 54,
527 DR7_WRITE = 55,
528 DR8_WRITE = 56,
529 DR9_WRITE = 57,
530 DR10_WRITE = 58,
531 DR11_WRITE = 59,
532 DR12_WRITE = 60,
533 DR13_WRITE = 61,
534 DR14_WRITE = 62,
535 DR15_WRITE = 63,
536 EXCP0 = 64,
537 EXCP_DB = 65,
538 EXCP2 = 66,
539 EXCP3 = 67,
540 EXCP4 = 68,
541 EXCP5 = 69,
542 EXCP6 = 70,
543 EXCP7 = 71,
544 EXCP8 = 72,
545 EXCP9 = 73,
546 EXCP10 = 74,
547 EXCP11 = 75,
548 EXCP12 = 76,
549 EXCP13 = 77,
550 EXCP14 = 78,
551 EXCP15 = 79,
552 EXCP16 = 80,
553 EXCP17 = 81,
554 EXCP18 = 82,
555 EXCP19 = 83,
556 EXCP20 = 84,
557 EXCP21 = 85,
558 EXCP22 = 86,
559 EXCP23 = 87,
560 EXCP24 = 88,
561 EXCP25 = 89,
562 EXCP26 = 90,
563 EXCP27 = 91,
564 EXCP28 = 92,
565 EXCP29 = 93,
566 EXCP30 = 94,
567 EXCP31 = 95,
568 INTR = 96,
569 NMI = 97,
570 SMI = 98,
571 INIT = 99,
572 VINTR = 100,
573 CR0_SEL_WRITE = 101,
574 IDTR_READ = 102,
575 GDTR_READ = 103,
576 LDTR_READ = 104,
577 TR_READ = 105,
578 IDTR_WRITE = 106,
579 GDTR_WRITE = 107,
580 LDTR_WRITE = 108,
581 TR_WRITE = 109,
582 RDTSC = 110,
583 RDPMC = 111,
584 PUSHF = 112,
585 POPF = 113,
586 CPUID = 114,
587 RSM = 115,
588 IRET = 116,
589 SWINT = 117,
590 INVD = 118,
591 PAUSE = 119,
592 HLT = 120,
593 INVLPG = 121,
594 INVLPGA = 122,
595 IOIO = 123,
596 MSR = 124,
597 TASK_SWITCH = 125,
598 FERR_FREEZE = 126,
599 SHUTDOWN = 127,
600 VMRUN = 128,
601 VMMCALL = 129,
602 VMLOAD = 130,
603 VMSAVE = 131,
604 STGI = 132,
605 CLGI = 133,
606 SKINIT = 134,
607 RDTSCP = 135,
608 ICEBP = 136,
609 WBINVD = 137,
610 MONITOR = 138,
611 MWAIT = 139,
612 MWAIT_CONDITIONAL = 140,
613 XSETBV = 141,
614 INVLPGB = 160,
615 ILLEGAL_INVLPGB = 161,
616 NPF = 1024,
617 AVIC_INCOMPLETE_IPI = 1025,
618 AVIC_NOACCEL = 1026,
619 VMGEXIT = 1027,
620 PAGE_NOT_VALIDATED = 1028,
621 SNP_GUEST_REQUEST = 0x80000011,
622 SNP_EXTENDED_GUEST_REQUEST = 0x80000012,
623 HV_DOORBELL_PAGE = 0x80000014,
624 INVALID_VMCB = 0xffff_ffff_ffff_ffff,
625 }
626}
627
628#[bitfield(u64)]
629#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
630pub struct GhcbMsr {
631 #[bits(12)]
632 pub info: u64,
633 #[bits(40)]
634 pub pfn: u64,
635 #[bits(12)]
636 pub extra_data: u64,
637}
638
639#[repr(C)]
641#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Clone, Copy)]
642pub struct HvPspCpuidLeaf {
643 pub eax_in: u32,
644 pub ecx_in: u32,
645 pub xfem_in: u64,
646 pub xss_in: u64,
647 pub eax_out: u32,
648 pub ebx_out: u32,
649 pub ecx_out: u32,
650 pub edx_out: u32,
651 pub reserved_z: u64,
652}
653
654pub const HV_PSP_CPUID_LEAF_COUNT_MAX: usize = 64;
655
656#[repr(C)]
657#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Clone, Copy)]
658pub struct HvPspCpuidPage {
659 pub count: u32,
660 pub reserved_z1: u32,
661 pub reserved_z2: u64,
662 pub cpuid_leaf_info: [HvPspCpuidLeaf; HV_PSP_CPUID_LEAF_COUNT_MAX],
663 pub reserved_z3: [u64; 126],
664}
665
666#[repr(C)]
670#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes)]
671pub struct SnpPageInfo {
672 pub digest_current: [u8; 48],
674 pub contents: [u8; 48],
676 pub length: u16,
678 pub page_type: SnpPageType,
680 pub imi_page_bit: u8,
682 pub lower_vmpl_permissions: u32,
684 pub gpa: u64,
687}
688
689open_enum::open_enum! {
690 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
692 pub enum SnpPageType: u8 {
693 RESERVED = 0x0,
695 NORMAL = 0x1,
697 VMSA = 0x2,
699 ZERO = 0x3,
701 UNMEASURED = 0x4,
703 SECRETS = 0x5,
705 CPUID = 0x6,
707 }
708}
709
710#[repr(C)]
714#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes)]
715pub struct SnpPspIdBlock {
716 pub ld: [u8; 48],
718 pub family_id: [u8; 16],
720 pub image_id: [u8; 16],
722 pub version: u32,
724 pub guest_svn: u32,
726 pub policy: u64,
728}
729
730#[bitfield(u64)]
731#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
732pub struct SevStatusMsr {
733 pub sev_enabled: bool,
734 pub es_enabled: bool,
735 pub snp_enabled: bool,
736 pub vtom: bool,
737 pub reflect_vc: bool,
738 pub restrict_injection: bool,
739 pub alternate_injection: bool,
740 pub debug_swap: bool,
741 pub prevent_host_ibs: bool,
742 pub snp_btb_isolation: bool,
743 pub _rsvd1: bool,
744 pub secure_tsc: bool,
745 pub _rsvd2: bool,
746 pub _rsvd3: bool,
747 pub _rsvd4: bool,
748 pub _rsvd5: bool,
749 pub vmsa_reg_prot: bool,
750 #[bits(47)]
751 _unused: u64,
752}
753
754#[bitfield(u64)]
755#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
756pub struct SevInvlpgbRax {
757 pub va_valid: bool,
758 pub pcid_valid: bool,
759 pub asid_valid: bool,
760 pub global: bool,
761 pub final_only: bool,
762 pub nested: bool,
763 #[bits(6)]
764 reserved: u64,
765 #[bits(52)]
766 pub virtual_page_number: u64,
767}
768
769#[bitfield(u32)]
770#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
771pub struct SevInvlpgbEdx {
772 #[bits(16)]
773 pub asid: u64,
774 #[bits(12)]
775 pub pcid: u64,
776 #[bits(4)]
777 reserved: u32,
778}
779
780#[bitfield(u32)]
781#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
782pub struct SevInvlpgbEcx {
783 #[bits(16)]
784 pub additional_count: u64,
785 #[bits(15)]
786 reserved: u64,
787 pub large_page: bool,
788}
789
790#[bitfield(u64)]
791pub struct MovCrxDrxInfo {
792 #[bits(4)]
793 pub gpr_number: u64,
794 #[bits(59)]
795 pub reserved: u64,
796 pub mov_crx: bool,
797}