1use crate::ApicRegisterValue;
7use bitfield_struct::bitfield;
8use static_assertions::const_assert_eq;
9use zerocopy::FromBytes;
10use zerocopy::Immutable;
11use zerocopy::IntoBytes;
12use zerocopy::KnownLayout;
13
14pub const SEV_INTR_TYPE_EXT: u32 = 0;
16pub const SEV_INTR_TYPE_NMI: u32 = 2;
17pub const SEV_INTR_TYPE_EXCEPT: u32 = 3;
18pub const SEV_INTR_TYPE_SW: u32 = 4;
19
20pub const REG_TWEAK_BITMAP_OFFSET: usize = 0x100;
22pub const REG_TWEAK_BITMAP_SIZE: usize = 0x40;
23
24pub const SNP_GUEST_REQ_MSG_VERSION: u32 = 1;
27
28#[bitfield(u64)]
29#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
30pub struct SevEventInjectInfo {
31 pub vector: u8,
32 #[bits(3)]
33 pub interruption_type: u32,
34 pub deliver_error_code: bool,
35 #[bits(19)]
36 _rsvd1: u64,
37 pub valid: bool,
38 pub error_code: u32,
39}
40
41#[repr(u8)]
42#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
43pub enum Vmpl {
44 Vmpl0 = 0,
45 Vmpl1 = 1,
46 Vmpl2 = 2,
47 Vmpl3 = 3,
48}
49
50impl From<Vmpl> for u8 {
51 fn from(value: Vmpl) -> Self {
52 value as _
53 }
54}
55
56#[repr(C)]
58#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
59pub struct SevSelector {
60 pub selector: u16,
61 pub attrib: u16,
62 pub limit: u32,
63 pub base: u64,
64}
65
66impl SevSelector {
67 pub fn as_u128(&self) -> u128 {
68 ((self.base as u128) << 64)
69 | ((self.limit as u128) << 32)
70 | ((self.attrib as u128) << 16)
71 | self.selector as u128
72 }
73}
74
75impl From<u128> for SevSelector {
76 fn from(val: u128) -> Self {
77 SevSelector {
78 selector: val as u16,
79 attrib: (val >> 16) as u16,
80 limit: (val >> 32) as u32,
81 base: (val >> 64) as u64,
82 }
83 }
84}
85
86#[repr(C)]
88#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
89pub struct SevXmmRegister {
90 low: u64,
91 high: u64,
92}
93
94impl SevXmmRegister {
95 pub fn as_u128(&self) -> u128 {
96 ((self.high as u128) << 64) | self.low as u128
97 }
98}
99
100impl From<u128> for SevXmmRegister {
101 fn from(val: u128) -> Self {
102 SevXmmRegister {
103 low: val as u64,
104 high: (val >> 64) as u64,
105 }
106 }
107}
108
109#[bitfield(u64)]
110#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
111pub struct SevFeatures {
112 pub snp: bool,
113 pub vtom: bool,
114 pub reflect_vc: bool,
115 pub restrict_injection: bool,
116 pub alternate_injection: bool,
117 pub debug_swap: bool,
118 pub prevent_host_ibs: bool,
119 pub snp_btb_isolation: bool,
120 pub vmpl_isss: bool,
121 pub secure_tsc: bool,
122 pub vmgexit_param: bool,
123 pub pmc_virt: bool,
124 pub ibs_virt: bool,
125 pub guest_intercept_control: bool,
126 pub vmsa_reg_prot: bool,
127 pub smt_prot: bool,
128 pub secure_avic: bool,
129 #[bits(4)]
130 _reserved0: u64,
131 pub ibpb_on_entry: bool,
132 #[bits(41)]
133 _reserved1: u64,
134 pub allowed_sev_features_enable: bool,
135}
136
137#[bitfield(u64)]
138#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
139pub struct SevVirtualInterruptControl {
140 pub tpr: u8,
141 pub irq: bool,
142 pub gif: bool,
143 pub intr_shadow: bool,
144 pub nmi: bool,
145 pub nmi_mask: bool,
146 #[bits(3)]
147 _rsvd1: u64,
148 #[bits(4)]
149 pub priority: u64,
150 pub ignore_tpr: bool,
151 #[bits(5)]
152 _rsvd2: u64,
153 pub nmi_enable: bool,
154 #[bits(5)]
155 _rsvd3: u64,
156 pub vector: u8,
157 #[bits(23)]
158 _rsvd4: u64,
159 pub guest_busy: bool,
160}
161
162#[bitfield(u64)]
163#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
164pub struct SevRmpAdjust {
165 pub target_vmpl: u8,
166 pub enable_read: bool,
167 pub enable_write: bool,
168 pub enable_user_execute: bool,
169 pub enable_kernel_execute: bool,
170 #[bits(4)]
171 _rsvd1: u64,
172 pub vmsa: bool,
173 #[bits(47)]
174 _rsvd2: u64,
175}
176
177#[bitfield(u32)]
178#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
179pub struct SevIoAccessInfo {
180 pub read_access: bool,
181 #[bits(1)]
182 reserved1: u32,
183 pub string_access: bool,
184 pub rep_access: bool,
185 pub access_size8: bool,
186 pub access_size16: bool,
187 pub access_size32: bool,
188 pub address_size8: bool,
189 pub address_size16: bool,
190 pub address_size32: bool,
191 #[bits(3)]
192 pub effective_segment: u32,
193 #[bits(3)]
194 rsvd2: u32,
195 pub port: u16,
196}
197
198#[bitfield(u64)]
199#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
200pub struct SevNpfInfo {
201 pub present: bool,
202 pub is_write: bool,
203 pub user: bool,
204 pub reserved_bit_set: bool,
205 pub fetch: bool,
206 #[bits(1)]
207 rsvd5: u64,
208 pub shadow_stack: bool,
209 #[bits(24)]
210 rsvd7_31: u64,
211 pub rmp_failure: bool,
212 pub caused_by_gpa_access: bool,
213 pub caused_by_page_table_access: bool,
214 pub encrypted_access: bool,
215 pub rmp_size_mismatch: bool,
216 pub vmpl_violation: bool,
217 pub npt_supervisor_shadow_stack: bool,
218 #[bits(26)]
219 rsvd38_63: u64,
220}
221
222#[bitfield(u64)]
224#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
225pub struct SecureAvicControl {
226 pub secure_avic_en: bool,
227 pub allowed_nmi: bool,
228 #[bits(10)]
229 _rsvd: u64,
230 #[bits(52)]
231 pub guest_apic_backing_page_ptr: u64,
232}
233
234#[bitfield(u64)]
236pub struct SevAvicIncompleteIpiInfo1 {
237 pub icr_low: u32,
238 pub icr_high: u32,
239}
240
241open_enum::open_enum! {
242 pub enum SevAvicIpiFailure: u32 {
243 INVALID_TYPE = 0,
244 NOT_RUNNING = 1,
245 INVALID_TARGET = 2,
246 INVALID_BACKING_PAGE = 3,
247 INVALID_VECTOR = 4,
248 UNACCELERATED_IPI = 5,
249 }
250}
251
252impl SevAvicIpiFailure {
253 const fn into_bits(self) -> u32 {
254 self.0
255 }
256
257 const fn from_bits(bits: u32) -> Self {
258 Self(bits)
259 }
260}
261
262#[bitfield(u64)]
264pub struct SevAvicIncompleteIpiInfo2 {
265 #[bits(8)]
266 pub index: u32,
267 #[bits(24)]
268 _mbz: u32,
269 #[bits(32)]
270 pub failure: SevAvicIpiFailure,
271}
272
273open_enum::open_enum! {
274 pub enum SevAvicRegisterNumber: u32 {
275 APIC_ID = 0x2,
277 VERSION = 0x3,
279 TPR = 0x8,
281 APR = 0x9,
283 PPR = 0xA,
285 EOI = 0xB,
287 REMOTE_READ = 0xC,
289 LDR = 0xD,
291 DFR = 0xE,
293 SPURIOUS = 0xF,
295 ISR0 = 0x10,
297 ISR1 = 0x11,
298 ISR2 = 0x12,
299 ISR3 = 0x13,
300 ISR4 = 0x14,
301 ISR5 = 0x15,
302 ISR6 = 0x16,
303 ISR7 = 0x17,
304 TMR0 = 0x18,
306 TMR1 = 0x19,
307 TMR2 = 0x1A,
308 TMR3 = 0x1B,
309 TMR4 = 0x1C,
310 TMR5 = 0x1D,
311 TMR6 = 0x1E,
312 TMR7 = 0x1F,
313 IRR0 = 0x20,
315 IRR1 = 0x21,
316 IRR2 = 0x22,
317 IRR3 = 0x23,
318 IRR4 = 0x24,
319 IRR5 = 0x25,
320 IRR6 = 0x26,
321 IRR7 = 0x27,
322 ERROR = 0x28,
324 ICR_LOW = 0x30,
326 ICR_HIGH = 0x31,
328 TIMER_LVT = 0x32,
330 THERMAL_LVT = 0x33,
332 PERFMON_LVT = 0x34,
334 LINT0_LVT = 0x35,
336 LINT1_LVT = 0x36,
338 ERROR_LVT = 0x37,
340 INITIAL_COUNT = 0x38,
342 CURRENT_COUNT = 0x39,
344 DIVIDER = 0x3e,
346 SELF_IPI = 0x3f,
348 }
349}
350
351impl SevAvicRegisterNumber {
352 const fn into_bits(self) -> u32 {
353 self.0
354 }
355
356 const fn from_bits(bits: u32) -> Self {
357 Self(bits)
358 }
359}
360
361#[bitfield(u64)]
363pub struct SevAvicNoAccelInfo {
364 #[bits(4)]
365 _rsvd1: u64,
366 #[bits(8)]
367 pub apic_register_number: SevAvicRegisterNumber,
368 #[bits(20)]
369 _rsvd2: u64,
370 #[bits(1)]
371 pub write_access: bool,
372 #[bits(31)]
373 _rsvd3: u64,
374}
375
376#[repr(C)]
378#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
379pub struct SevVmsa {
380 pub es: SevSelector,
382 pub cs: SevSelector,
383 pub ss: SevSelector,
384 pub ds: SevSelector,
385 pub fs: SevSelector,
386 pub gs: SevSelector,
387
388 pub gdtr: SevSelector,
390 pub ldtr: SevSelector,
391 pub idtr: SevSelector,
392 pub tr: SevSelector,
393
394 pub pl0_ssp: u64,
396 pub pl1_ssp: u64,
397 pub pl2_ssp: u64,
398 pub pl3_ssp: u64,
399 pub u_cet: u64,
400
401 pub vmsa_reserved1: [u8; 2],
403
404 pub vmpl: u8,
406
407 pub cpl: u8,
409
410 pub vmsa_reserved2: u32,
412
413 pub efer: u64,
415
416 pub vmsa_reserved3: [u32; 26],
418
419 pub xss: u64,
421
422 pub cr4: u64,
424 pub cr3: u64,
425 pub cr0: u64,
426
427 pub dr7: u64,
429 pub dr6: u64,
430
431 pub rflags: u64,
433
434 pub rip: u64,
436
437 pub dr0: u64,
439 pub dr1: u64,
440 pub dr2: u64,
441 pub dr3: u64,
442
443 pub dr0_addr_mask: u64,
445 pub dr1_addr_mask: u64,
446 pub dr2_addr_mask: u64,
447 pub dr3_addr_mask: u64,
448
449 pub vmsa_reserved4: [u64; 3],
451
452 pub rsp: u64,
454
455 pub s_cet: u64,
457 pub ssp: u64,
458 pub interrupt_ssp_table_addr: u64,
459
460 pub rax: u64,
462
463 pub star: u64,
465 pub lstar: u64,
466 pub cstar: u64,
467 pub sfmask: u64,
468
469 pub kernel_gs_base: u64,
471
472 pub sysenter_cs: u64,
474 pub sysenter_esp: u64,
475 pub sysenter_eip: u64,
476
477 pub cr2: u64,
479
480 pub vmsa_reserved5: [u64; 4],
482
483 pub pat: u64,
485
486 pub dbgctl: u64,
488 pub last_branch_from_ip: u64,
489 pub last_branch_to_ip: u64,
490 pub last_excp_from_ip: u64,
491 pub last_excp_to_ip: u64,
492
493 pub vmsa_reserved6: [u64; 9],
495
496 pub spec_ctrl: u64,
498
499 pub pkru: u32,
501
502 pub tsc_aux: u32,
504
505 pub vmsa_reserved7: [u32; 4],
507
508 pub register_protection_nonce: u64,
509
510 pub rcx: u64,
512 pub rdx: u64,
513 pub rbx: u64,
514 pub secure_avic_control: SecureAvicControl,
515 pub rbp: u64,
516 pub rsi: u64,
517 pub rdi: u64,
518 pub r8: u64,
519 pub r9: u64,
520 pub r10: u64,
521 pub r11: u64,
522 pub r12: u64,
523 pub r13: u64,
524 pub r14: u64,
525 pub r15: u64,
526
527 pub vmsa_reserved9: [u64; 2],
529
530 pub exit_info1: u64,
532 pub exit_info2: u64,
533 pub exit_int_info: u64,
534
535 pub next_rip: u64,
537
538 pub sev_features: SevFeatures,
540
541 pub v_intr_cntrl: SevVirtualInterruptControl,
543
544 pub guest_error_code: u64,
546
547 pub virtual_tom: u64,
549
550 pub tlb_id: u64,
553 pub pcpu_id: u64,
554
555 pub event_inject: SevEventInjectInfo,
557
558 pub xcr0: u64,
560
561 pub xsave_valid_bitmap: [u8; 16],
563
564 pub x87dp: u64,
566 pub mxcsr: u32,
567 pub x87_ftw: u16,
568 pub x87_fsw: u16,
569 pub x87_fcw: u16,
570 pub x87_op: u16,
571 pub x87_ds: u16,
572 pub x87_cs: u16,
573 pub x87_rip: u64,
574
575 pub x87_registers: [u64; 10],
578
579 pub xmm_registers: [SevXmmRegister; 16],
581
582 pub ymm_registers: [SevXmmRegister; 16],
584}
585
586#[repr(C)]
587#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
588pub struct SevAvicIrrRegister {
594 pub value: u32,
595 pub allowed: u32,
596 _reserved: [u32; 2],
597}
598
599#[repr(C)]
600#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
601pub struct SevAvicPage {
604 pub reserved_0: [ApicRegisterValue; 2],
605 pub id: ApicRegisterValue,
606 pub version: ApicRegisterValue,
607 pub reserved_4: [ApicRegisterValue; 4],
608 pub tpr: ApicRegisterValue,
609 pub apr: ApicRegisterValue,
610 pub ppr: ApicRegisterValue,
611 pub eoi: ApicRegisterValue,
612 pub rrd: ApicRegisterValue,
613 pub ldr: ApicRegisterValue,
614 pub dfr: ApicRegisterValue,
615 pub svr: ApicRegisterValue,
616 pub isr: [ApicRegisterValue; 8],
617 pub tmr: [ApicRegisterValue; 8],
618 pub irr: [SevAvicIrrRegister; 8],
619 pub esr: ApicRegisterValue,
620 pub reserved_29: [ApicRegisterValue; 6],
621 pub lvt_cmci: ApicRegisterValue,
622 pub icr: [ApicRegisterValue; 2],
623 pub lvt_timer: ApicRegisterValue,
624 pub lvt_thermal: ApicRegisterValue,
625 pub lvt_pmc: ApicRegisterValue,
626 pub lvt_lint0: ApicRegisterValue,
627 pub lvt_lint1: ApicRegisterValue,
628 pub lvt_error: ApicRegisterValue,
629 pub timer_icr: ApicRegisterValue,
630 pub timer_ccr: ApicRegisterValue,
631 pub reserved_3a: [ApicRegisterValue; 4],
632 pub timer_dcr: ApicRegisterValue,
633 pub self_ipi: ApicRegisterValue,
634 pub eafr: ApicRegisterValue,
635 pub eacr: ApicRegisterValue,
636 pub seoi: ApicRegisterValue,
637 pub reserved_44: [ApicRegisterValue; 0x5],
638 pub ier: [ApicRegisterValue; 8],
639 pub ei_lv_tr: [ApicRegisterValue; 3],
640 pub reserved_54: [ApicRegisterValue; 0xad],
641}
642
643const_assert_eq!(size_of::<SevAvicPage>(), 4096);
644
645open_enum::open_enum! {
647 pub enum GhcbInfo: u64 {
648 NORMAL = 0x000,
649 SEV_INFO_RESPONSE = 0x001,
650 SEV_INFO_REQUEST = 0x002,
651 AP_JUMP_TABLE = 0x003,
652 CPUID_REQUEST = 0x004,
653 CPUID_RESPONSE = 0x005,
654 PREFERRED_REQUEST = 0x010,
655 PREFERRED_RESPONSE = 0x011,
656 REGISTER_REQUEST = 0x012,
657 REGISTER_RESPONSE = 0x013,
658 PAGE_STATE_CHANGE = 0x014,
659 PAGE_STATE_UPDATED = 0x015,
660 HYP_FEATURE_REQUEST = 0x080,
661 HYP_FEATURE_RESPONSE = 0x081,
662 SPECIAL_HYPERCALL = 0xF00,
663 SPECIAL_FAST_CALL = 0xF01,
664 HYPERCALL_OUTPUT = 0xF02,
665 SPECIAL_DBGPRINT = 0xF03,
666 SHUTDOWN_REQUEST = 0x100,
667 }
668}
669
670pub const GHCB_DATA_PAGE_STATE_PRIVATE: u64 = 0x001;
671pub const GHCB_DATA_PAGE_STATE_SHARED: u64 = 0x002;
672pub const GHCB_DATA_PAGE_STATE_PSMASH: u64 = 0x003;
673pub const GHCB_DATA_PAGE_STATE_UNSMASH: u64 = 0x004;
674pub const GHCB_DATA_PAGE_STATE_MASK: u64 = 0x00F;
675pub const GHCB_DATA_PAGE_STATE_LARGE_PAGE: u64 = 0x010;
676
677open_enum::open_enum! {
678 pub enum GhcbUsage: u32 {
679 BASE = 0,
680 HYPERCALL = 1,
681 VTL_RETURN = 2,
682 }
683}
684
685#[repr(C)]
688#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
689pub struct GhcbHypercallParameters {
690 pub output_gpa: u64,
691 pub input_control: u64,
692}
693
694pub const GHCB_PAGE_HYPERCALL_PARAMETERS_OFFSET: usize = 4072;
695pub const GHCB_PAGE_HYPERCALL_OUTPUT_OFFSET: usize = 4080;
696
697open_enum::open_enum! {
699 pub enum SevExitCode: u64 {
700 CR0_READ = 0x0,
701 CR1_READ = 0x1,
702 CR2_READ = 0x2,
703 CR3_READ = 0x3,
704 CR4_READ = 0x4,
705 CR5_READ = 0x5,
706 CR6_READ = 0x6,
707 CR7_READ = 0x7,
708 CR8_READ = 0x8,
709 CR9_READ = 0x9,
710 CR10_READ = 0xa,
711 CR11_READ = 0xb,
712 CR12_READ = 0xc,
713 CR13_READ = 0xd,
714 CR14_READ = 0xe,
715 CR15_READ = 0xf,
716 CR0_WRITE = 0x10,
717 CR1_WRITE = 0x11,
718 CR2_WRITE = 0x12,
719 CR3_WRITE = 0x13,
720 CR4_WRITE = 0x14,
721 CR5_WRITE = 0x15,
722 CR6_WRITE = 0x16,
723 CR7_WRITE = 0x17,
724 CR8_WRITE = 0x18,
725 CR9_WRITE = 0x19,
726 CR10_WRITE = 0x1a,
727 CR11_WRITE = 0x1b,
728 CR12_WRITE = 0x1c,
729 CR13_WRITE = 0x1d,
730 CR14_WRITE = 0x1e,
731 CR15_WRITE = 0x1f,
732 DR0_READ = 0x20,
733 DR1_READ = 0x21,
734 DR2_READ = 0x22,
735 DR3_READ = 0x23,
736 DR4_READ = 0x24,
737 DR5_READ = 0x25,
738 DR6_READ = 0x26,
739 DR7_READ = 0x27,
740 DR8_READ = 0x28,
741 DR9_READ = 0x29,
742 DR10_READ = 0x2a,
743 DR11_READ = 0x2b,
744 DR12_READ = 0x2c,
745 DR13_READ = 0x2d,
746 DR14_READ = 0x2e,
747 DR15_READ = 0x2f,
748 DR0_WRITE = 0x30,
749 DR1_WRITE = 0x31,
750 DR2_WRITE = 0x32,
751 DR3_WRITE = 0x33,
752 DR4_WRITE = 0x34,
753 DR5_WRITE = 0x35,
754 DR6_WRITE = 0x36,
755 DR7_WRITE = 0x37,
756 DR8_WRITE = 0x38,
757 DR9_WRITE = 0x39,
758 DR10_WRITE = 0x3a,
759 DR11_WRITE = 0x3b,
760 DR12_WRITE = 0x3c,
761 DR13_WRITE = 0x3d,
762 DR14_WRITE = 0x3e,
763 DR15_WRITE = 0x3f,
764 EXCP0 = 0x40,
765 EXCP_DB = 0x41,
766 EXCP2 = 0x42,
767 EXCP3 = 0x43,
768 EXCP4 = 0x44,
769 EXCP5 = 0x45,
770 EXCP6 = 0x46,
771 EXCP7 = 0x47,
772 EXCP8 = 0x48,
773 EXCP9 = 0x49,
774 EXCP10 = 0x4a,
775 EXCP11 = 0x4b,
776 EXCP12 = 0x4c,
777 EXCP13 = 0x4d,
778 EXCP14 = 0x4e,
779 EXCP15 = 0x4f,
780 EXCP16 = 0x50,
781 EXCP17 = 0x51,
782 EXCP18 = 0x52,
783 EXCP19 = 0x53,
784 EXCP20 = 0x54,
785 EXCP21 = 0x55,
786 EXCP22 = 0x56,
787 EXCP23 = 0x57,
788 EXCP24 = 0x58,
789 EXCP25 = 0x59,
790 EXCP26 = 0x5a,
791 EXCP27 = 0x5b,
792 EXCP28 = 0x5c,
793 EXCP29 = 0x5d,
794 EXCP30 = 0x5e,
795 EXCP31 = 0x5f,
796 INTR = 0x60,
797 NMI = 0x61,
798 SMI = 0x62,
799 INIT = 0x63,
800 VINTR = 0x64,
801 CR0_SEL_WRITE = 0x65,
802 IDTR_READ = 0x66,
803 GDTR_READ = 0x67,
804 LDTR_READ = 0x68,
805 TR_READ = 0x69,
806 IDTR_WRITE = 0x6a,
807 GDTR_WRITE = 0x6b,
808 LDTR_WRITE = 0x6c,
809 TR_WRITE = 0x6d,
810 RDTSC = 0x6e,
811 RDPMC = 0x6f,
812 PUSHF = 0x70,
813 POPF = 0x71,
814 CPUID = 0x72,
815 RSM = 0x73,
816 IRET = 0x74,
817 SWINT = 0x75,
818 INVD = 0x76,
819 PAUSE = 0x77,
820 HLT = 0x78,
821 INVLPG = 0x79,
822 INVLPGA = 0x7a,
823 IOIO = 0x7b,
824 MSR = 0x7c,
825 TASK_SWITCH = 0x7d,
826 FERR_FREEZE = 0x7e,
827 SHUTDOWN = 0x7f,
828 VMRUN = 0x80,
829 VMMCALL = 0x81,
830 VMLOAD = 0x82,
831 VMSAVE = 0x83,
832 STGI = 0x84,
833 CLGI = 0x85,
834 SKINIT = 0x86,
835 RDTSCP = 0x87,
836 ICEBP = 0x88,
837 WBINVD = 0x89,
838 MONITOR = 0x8a,
839 MWAIT = 0x8b,
840 MWAIT_CONDITIONAL = 0x8c,
841 XSETBV = 0x8d,
842 RDPRU = 0x8e,
843 EFER_WRITE_TRAP = 0x8f,
844 CR0_WRITE_TRAP = 0x90,
845 CR1_WRITE_TRAP = 0x91,
846 CR2_WRITE_TRAP = 0x92,
847 CR3_WRITE_TRAP = 0x93,
848 CR4_WRITE_TRAP = 0x94,
849 CR5_WRITE_TRAP = 0x95,
850 CR6_WRITE_TRAP = 0x96,
851 CR7_WRITE_TRAP = 0x97,
852 CR8_WRITE_TRAP = 0x98,
853 CR9_WRITE_TRAP = 0x99,
854 CR10_WRITE_TRAP = 0x9a,
855 CR11_WRITE_TRAP = 0x9b,
856 CR12_WRITE_TRAP = 0x9c,
857 CR13_WRITE_TRAP = 0x9d,
858 CR14_WRITE_TRAP = 0x9e,
859 CR15_WRITE_TRAP = 0x9f,
860 INVLPGB = 0xa0,
861 ILLEGAL_INVLPGB = 0xa1,
862 INVPCID = 0xa2,
863 BUSLOCK = 0xa5,
864 IDLE_HLT = 0xa6,
865 NPF = 0x400,
866 AVIC_INCOMPLETE_IPI = 0x401,
867 AVIC_NOACCEL = 0x402,
868 VMGEXIT = 0x403,
869 PAGE_NOT_VALIDATED = 0x404,
870
871 SNP_GUEST_REQUEST = 0x80000011,
873 SNP_EXTENDED_GUEST_REQUEST = 0x80000012,
874 HV_DOORBELL_PAGE = 0x80000014,
875
876 INVALID_VMCB = 0xffff_ffff_ffff_ffff,
878 VMSA_BUSY = 0xffff_ffff_ffff_fffe,
879 IDLE_REQUIRED = 0xffff_ffff_ffff_fffd,
880 INVALID_PMC = 0xffff_ffff_ffff_fffc,
881 }
882}
883
884#[bitfield(u64)]
885#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
886pub struct GhcbMsr {
887 #[bits(12)]
888 pub info: u64,
889 #[bits(40)]
890 pub pfn: u64,
891 #[bits(12)]
892 pub extra_data: u64,
893}
894
895#[repr(C)]
897#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Clone, Copy)]
898pub struct HvPspCpuidLeaf {
899 pub eax_in: u32,
900 pub ecx_in: u32,
901 pub xfem_in: u64,
902 pub xss_in: u64,
903 pub eax_out: u32,
904 pub ebx_out: u32,
905 pub ecx_out: u32,
906 pub edx_out: u32,
907 pub reserved_z: u64,
908}
909
910pub const HV_PSP_CPUID_LEAF_COUNT_MAX: usize = 64;
911
912#[repr(C)]
913#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Clone, Copy)]
914pub struct HvPspCpuidPage {
915 pub count: u32,
916 pub reserved_z1: u32,
917 pub reserved_z2: u64,
918 pub cpuid_leaf_info: [HvPspCpuidLeaf; HV_PSP_CPUID_LEAF_COUNT_MAX],
919 pub reserved_z3: [u64; 126],
920}
921
922#[repr(C)]
926#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes)]
927pub struct SnpPageInfo {
928 pub digest_current: [u8; 48],
930 pub contents: [u8; 48],
932 pub length: u16,
934 pub page_type: SnpPageType,
936 pub imi_page_bit: u8,
938 pub lower_vmpl_permissions: u32,
940 pub gpa: u64,
943}
944
945open_enum::open_enum! {
946 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
948 pub enum SnpPageType: u8 {
949 RESERVED = 0x0,
951 NORMAL = 0x1,
953 VMSA = 0x2,
955 ZERO = 0x3,
957 UNMEASURED = 0x4,
959 SECRETS = 0x5,
961 CPUID = 0x6,
963 }
964}
965
966#[repr(C)]
970#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes)]
971pub struct SnpPspIdBlock {
972 pub ld: [u8; 48],
974 pub family_id: [u8; 16],
976 pub image_id: [u8; 16],
978 pub version: u32,
980 pub guest_svn: u32,
982 pub policy: u64,
984}
985
986#[bitfield(u64)]
987#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
988pub struct SevStatusMsr {
989 pub sev_enabled: bool,
990 pub es_enabled: bool,
991 pub snp_enabled: bool,
992 pub vtom: bool,
993 pub reflect_vc: bool,
994 pub restrict_injection: bool,
995 pub alternate_injection: bool,
996 pub debug_swap: bool,
997 pub prevent_host_ibs: bool,
998 pub snp_btb_isolation: bool,
999 pub vmpl_sss: bool,
1000 pub secure_tsc: bool,
1001 pub vmgexit_param: bool,
1002 _rsvd3: bool,
1003 pub ibs_virt: bool,
1004 _rsvd5: bool,
1005 pub vmsa_reg_prot: bool,
1006 pub smt_prot: bool,
1007 pub secure_avic: bool,
1008 #[bits(4)]
1009 _reserved: u64,
1010 pub ibpb_on_entry: bool,
1011 #[bits(40)]
1012 _unused: u64,
1013}
1014
1015#[bitfield(u64)]
1016#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
1017pub struct SevInvlpgbRax {
1018 pub va_valid: bool,
1019 pub pcid_valid: bool,
1020 pub asid_valid: bool,
1021 pub global: bool,
1022 pub final_only: bool,
1023 pub nested: bool,
1024 #[bits(6)]
1025 reserved: u64,
1026 #[bits(52)]
1027 pub virtual_page_number: u64,
1028}
1029
1030#[bitfield(u32)]
1031#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
1032pub struct SevInvlpgbEdx {
1033 #[bits(16)]
1034 pub asid: u64,
1035 #[bits(12)]
1036 pub pcid: u64,
1037 #[bits(4)]
1038 reserved: u32,
1039}
1040
1041#[bitfield(u32)]
1042#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
1043pub struct SevInvlpgbEcx {
1044 #[bits(16)]
1045 pub additional_count: u64,
1046 #[bits(15)]
1047 reserved: u64,
1048 pub large_page: bool,
1049}
1050
1051#[bitfield(u64)]
1052pub struct MovCrxDrxInfo {
1053 #[bits(4)]
1054 pub gpr_number: u64,
1055 #[bits(59)]
1056 pub reserved: u64,
1057 pub mov_crx: bool,
1058}
1059
1060#[repr(C)]
1063#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1064pub struct SnpReportReq {
1065 pub user_data: [u8; 64],
1067 pub vmpl: u32,
1070 pub rsvd: [u8; 28],
1073}
1074
1075pub const SNP_REPORT_RESP_DATA_SIZE: usize =
1076 size_of::<u32>() + size_of::<u32>() + 24 + size_of::<SnpReport>();
1077
1078#[repr(C)]
1081#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1082pub struct SnpReportResp {
1083 pub status: u32,
1088 pub report_size: u32,
1090 pub _reserved0: [u8; 24],
1092 pub report: SnpReport,
1094}
1095
1096pub const SNP_REPORT_SIZE: usize = 0x4a0;
1098
1099pub const SNP_REPORT_DATA_SIZE: usize = 64;
1101
1102#[repr(C)]
1105#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1106pub struct SnpReport {
1107 pub version: u32,
1110 pub guest_svn: u32,
1112 pub policy: u64,
1114 pub family: u128,
1116 pub image_id: u128,
1118 pub vmpl: u32,
1121 pub signature_algo: u32,
1124 pub current_tcb: u64,
1126 pub platform_info: u64,
1128 pub flags: u32,
1130 pub _reserved0: u32,
1132 pub report_data: [u8; SNP_REPORT_DATA_SIZE],
1134 pub measurement: [u8; 48],
1137 pub host_data: [u8; 32],
1140 pub id_key_digest: [u8; 48],
1144 pub author_key_digest: [u8; 48],
1148 pub report_id: [u8; 32],
1150 pub report_id_ma: [u8; 32],
1153 pub reported_tcb: u64,
1156 pub _reserved1: [u8; 24],
1158 pub chip_id: [u8; 64],
1162 pub committed_tcb: u64,
1164 pub current_build: u8,
1166 pub current_minor: u8,
1168 pub current_major: u8,
1170 pub _reserved2: u8,
1172 pub committed_build: u8,
1174 pub committed_minor: u8,
1176 pub committed_major: u8,
1178 pub _reserved3: u8,
1180 pub launch_tcb: u64,
1183 pub _reserved4: [u8; 168],
1185 pub signature: [u8; 512],
1187}
1188
1189static_assertions::const_assert_eq!(SNP_REPORT_SIZE, size_of::<SnpReport>());
1190
1191#[repr(C)]
1194#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1195pub struct SnpDerivedKeyReq {
1196 pub root_key_select: u32,
1201 pub rsvd: u32,
1203 pub guest_field_select: u64,
1206 pub vmpl: u32,
1209 pub guest_svn: u32,
1212 pub tcb_version: u64,
1215}
1216
1217#[bitfield(u64)]
1220pub struct GuestFieldSelect {
1221 pub guest_policy: bool,
1223 pub image_id: bool,
1225 pub family_id: bool,
1227 pub measurement: bool,
1229 pub guest_svn: bool,
1231 pub tcb_version: bool,
1233 #[bits(58)]
1235 pub _reserved: u64,
1236}
1237
1238pub const SNP_DERIVED_KEY_SIZE: usize = 32;
1240
1241#[repr(C)]
1244#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1245pub struct SnpDerivedKeyResp {
1246 pub status: u32,
1251 pub _reserved: [u8; 28],
1253 pub derived_key: [u8; SNP_DERIVED_KEY_SIZE],
1255}
1256
1257static_assertions::const_assert_eq!(
1258 64,
1260 size_of::<SnpDerivedKeyResp>()
1261);
1262
1263#[cfg(test)]
1264mod tests {
1265 use super::*;
1266 use zerocopy::FromZeros;
1267
1268 #[test]
1271 fn secure_avic_control_default_is_zero() {
1272 let ctrl = SecureAvicControl::new();
1273 assert_eq!(ctrl.into_bits(), 0);
1274 assert_eq!(ctrl.secure_avic_en(), false);
1275 assert_eq!(ctrl.allowed_nmi(), false);
1276 assert_eq!(ctrl.guest_apic_backing_page_ptr(), 0);
1277 }
1278
1279 #[test]
1280 fn secure_avic_control_enable_bit() {
1281 let ctrl = SecureAvicControl::new().with_secure_avic_en(true);
1282 assert_eq!(ctrl.secure_avic_en(), true);
1283 assert_eq!(ctrl.into_bits() & 1, 1);
1284 }
1285
1286 #[test]
1287 fn secure_avic_control_allowed_nmi_bit() {
1288 let ctrl = SecureAvicControl::new().with_allowed_nmi(true);
1289 assert_eq!(ctrl.allowed_nmi(), true);
1290 assert_eq!(ctrl.into_bits() & 0b10, 0b10);
1291 }
1292
1293 #[test]
1294 fn secure_avic_control_page_ptr() {
1295 let pfn = 0xDEAD_BEEF_u64;
1297 let ctrl = SecureAvicControl::new()
1298 .with_secure_avic_en(true)
1299 .with_guest_apic_backing_page_ptr(pfn);
1300 assert_eq!(ctrl.guest_apic_backing_page_ptr(), pfn);
1301 assert_eq!(ctrl.secure_avic_en(), true);
1302 assert_eq!(ctrl.into_bits() >> 12, pfn);
1304 }
1305
1306 #[test]
1307 fn secure_avic_control_roundtrip() {
1308 let raw = 0xABCD_1234_5678_9001_u64;
1309 let ctrl = SecureAvicControl::from(raw);
1310 assert_eq!(ctrl.into_bits(), raw);
1311 }
1312
1313 #[test]
1316 fn no_accel_info_register_number_extraction() {
1317 let info = SevAvicNoAccelInfo::new().with_apic_register_number(SevAvicRegisterNumber::EOI);
1319 assert_eq!(info.apic_register_number(), SevAvicRegisterNumber::EOI);
1320 assert_eq!((info.into_bits() >> 4) & 0xFF, 0xB);
1322 }
1323
1324 #[test]
1325 fn no_accel_info_write_access_bit() {
1326 let info = SevAvicNoAccelInfo::new().with_write_access(true);
1328 assert!(info.write_access());
1329 assert_eq!(info.into_bits() & (1 << 32), 1 << 32);
1330
1331 let info_read = SevAvicNoAccelInfo::new().with_write_access(false);
1332 assert!(!info_read.write_access());
1333 }
1334
1335 #[test]
1336 fn no_accel_info_combined() {
1337 let info = SevAvicNoAccelInfo::new()
1338 .with_apic_register_number(SevAvicRegisterNumber::ICR_LOW)
1339 .with_write_access(true);
1340 assert_eq!(info.apic_register_number(), SevAvicRegisterNumber::ICR_LOW);
1341 assert!(info.write_access());
1342 }
1343
1344 #[test]
1345 fn no_accel_info_all_register_numbers_roundtrip() {
1346 let registers = [
1347 SevAvicRegisterNumber::APIC_ID,
1348 SevAvicRegisterNumber::VERSION,
1349 SevAvicRegisterNumber::TPR,
1350 SevAvicRegisterNumber::APR,
1351 SevAvicRegisterNumber::PPR,
1352 SevAvicRegisterNumber::EOI,
1353 SevAvicRegisterNumber::LDR,
1354 SevAvicRegisterNumber::DFR,
1355 SevAvicRegisterNumber::SPURIOUS,
1356 SevAvicRegisterNumber::ISR0,
1357 SevAvicRegisterNumber::ISR7,
1358 SevAvicRegisterNumber::TMR0,
1359 SevAvicRegisterNumber::TMR7,
1360 SevAvicRegisterNumber::IRR0,
1361 SevAvicRegisterNumber::IRR7,
1362 SevAvicRegisterNumber::ERROR,
1363 SevAvicRegisterNumber::ICR_LOW,
1364 SevAvicRegisterNumber::ICR_HIGH,
1365 SevAvicRegisterNumber::TIMER_LVT,
1366 SevAvicRegisterNumber::INITIAL_COUNT,
1367 SevAvicRegisterNumber::CURRENT_COUNT,
1368 SevAvicRegisterNumber::DIVIDER,
1369 SevAvicRegisterNumber::SELF_IPI,
1370 ];
1371 for reg in registers {
1372 let info = SevAvicNoAccelInfo::new().with_apic_register_number(reg);
1373 assert_eq!(
1374 info.apic_register_number(),
1375 reg,
1376 "register number roundtrip failed for {reg:#x?}"
1377 );
1378 }
1379 }
1380
1381 #[test]
1384 fn incomplete_ipi_info1_icr_fields() {
1385 let icr_low = 0x0004_10FFu32;
1386 let icr_high = 0x0200_0000u32;
1387 let info = SevAvicIncompleteIpiInfo1::new()
1388 .with_icr_low(icr_low)
1389 .with_icr_high(icr_high);
1390 assert_eq!(info.icr_low(), icr_low);
1391 assert_eq!(info.icr_high(), icr_high);
1392 assert_eq!(info.into_bits(), icr_low as u64 | ((icr_high as u64) << 32));
1393 }
1394
1395 #[test]
1396 fn incomplete_ipi_info2_fields() {
1397 let info = SevAvicIncompleteIpiInfo2::new()
1398 .with_index(42)
1399 .with_failure(SevAvicIpiFailure::NOT_RUNNING);
1400 assert_eq!(info.index(), 42);
1401 assert_eq!(info.failure(), SevAvicIpiFailure::NOT_RUNNING);
1402 }
1403
1404 #[test]
1405 fn incomplete_ipi_info2_all_failure_codes() {
1406 let failures = [
1407 SevAvicIpiFailure::INVALID_TYPE,
1408 SevAvicIpiFailure::NOT_RUNNING,
1409 SevAvicIpiFailure::INVALID_TARGET,
1410 SevAvicIpiFailure::INVALID_BACKING_PAGE,
1411 SevAvicIpiFailure::INVALID_VECTOR,
1412 SevAvicIpiFailure::UNACCELERATED_IPI,
1413 ];
1414 for failure in failures {
1415 let info = SevAvicIncompleteIpiInfo2::new().with_failure(failure);
1416 assert_eq!(
1417 info.failure(),
1418 failure,
1419 "failure code roundtrip failed for {failure:#x?}"
1420 );
1421 }
1422 }
1423
1424 #[test]
1427 fn sev_features_secure_avic_bit() {
1428 let features = SevFeatures::new().with_secure_avic(true);
1429 assert!(features.secure_avic());
1430 assert_ne!(features.into_bits() & (1 << 16), 0);
1432 }
1433
1434 #[test]
1435 fn sev_features_guest_intercept_control_bit() {
1436 let features = SevFeatures::new().with_guest_intercept_control(true);
1437 assert!(features.guest_intercept_control());
1438 assert_ne!(features.into_bits() & (1 << 13), 0);
1440 }
1441
1442 #[test]
1443 fn sev_features_secure_avic_with_no_alternate_injection() {
1444 let features = SevFeatures::new()
1447 .with_secure_avic(true)
1448 .with_guest_intercept_control(true)
1449 .with_alternate_injection(false);
1450 assert!(features.secure_avic());
1451 assert!(features.guest_intercept_control());
1452 assert!(!features.alternate_injection());
1453 }
1454
1455 #[test]
1456 fn sev_features_alternate_injection_without_secure_avic() {
1457 let features = SevFeatures::new()
1458 .with_alternate_injection(true)
1459 .with_secure_avic(false);
1460 assert!(features.alternate_injection());
1461 assert!(!features.secure_avic());
1462 }
1463
1464 #[test]
1467 fn sev_status_msr_secure_avic_bit() {
1468 let status = SevStatusMsr::new().with_secure_avic(true);
1469 assert!(status.secure_avic());
1470 assert_ne!(status.into_bits() & (1 << 18), 0);
1475 }
1476
1477 #[test]
1480 fn v_intr_cntrl_nmi_fields() {
1481 let ctrl = SevVirtualInterruptControl::new()
1482 .with_nmi(true)
1483 .with_nmi_mask(true)
1484 .with_nmi_enable(true);
1485 assert!(ctrl.nmi());
1486 assert!(ctrl.nmi_mask());
1487 assert!(ctrl.nmi_enable());
1488 }
1489
1490 #[test]
1493 fn sev_avic_page_size_is_4096() {
1494 assert_eq!(size_of::<SevAvicPage>(), 4096);
1496 }
1497
1498 #[test]
1499 fn sev_avic_irr_register_size() {
1500 assert_eq!(
1503 size_of::<SevAvicIrrRegister>(),
1504 size_of::<ApicRegisterValue>()
1505 );
1506 }
1507
1508 #[test]
1509 fn sev_avic_page_field_offsets() {
1510 let page = SevAvicPage::new_zeroed();
1513 let base = core::ptr::from_ref(&page) as usize;
1514
1515 let id_offset = core::ptr::from_ref(&page.id) as usize - base;
1517 assert_eq!(id_offset, 2 * 16, "APIC ID offset");
1518
1519 let version_offset = core::ptr::from_ref(&page.version) as usize - base;
1521 assert_eq!(version_offset, 3 * 16, "version offset");
1522
1523 let tpr_offset = core::ptr::from_ref(&page.tpr) as usize - base;
1525 assert_eq!(tpr_offset, 8 * 16, "TPR offset");
1526
1527 let isr_offset = core::ptr::from_ref(&page.isr) as usize - base;
1529 assert_eq!(isr_offset, 0x10 * 16, "ISR offset");
1530
1531 let tmr_offset = core::ptr::from_ref(&page.tmr) as usize - base;
1533 assert_eq!(tmr_offset, 0x18 * 16, "TMR offset");
1534
1535 let irr_offset = core::ptr::from_ref(&page.irr) as usize - base;
1537 assert_eq!(irr_offset, 0x20 * 16, "IRR offset");
1538
1539 let icr_offset = core::ptr::from_ref(&page.icr) as usize - base;
1541 assert_eq!(icr_offset, 0x30 * 16, "ICR offset");
1542 }
1543
1544 #[test]
1547 fn vmsa_secure_avic_control_at_rsp_offset() {
1548 let vmsa = SevVmsa::new_zeroed();
1551 let base = core::ptr::from_ref(&vmsa) as usize;
1552 let rbx_offset = core::ptr::from_ref(&vmsa.rbx) as usize - base;
1553 let savic_offset = core::ptr::from_ref(&vmsa.secure_avic_control) as usize - base;
1554 let rbp_offset = core::ptr::from_ref(&vmsa.rbp) as usize - base;
1555
1556 assert_eq!(savic_offset, rbx_offset + 8);
1558 assert_eq!(rbp_offset, savic_offset + 8);
1559 }
1560
1561 #[test]
1564 fn avic_register_number_matches_apic_register_enum() {
1565 use crate::apic::ApicRegister;
1568 assert_eq!(SevAvicRegisterNumber::APIC_ID.0, ApicRegister::ID.0 as u32);
1569 assert_eq!(
1570 SevAvicRegisterNumber::VERSION.0,
1571 ApicRegister::VERSION.0 as u32
1572 );
1573 assert_eq!(SevAvicRegisterNumber::TPR.0, ApicRegister::TPR.0 as u32);
1574 assert_eq!(SevAvicRegisterNumber::EOI.0, ApicRegister::EOI.0 as u32);
1575 assert_eq!(SevAvicRegisterNumber::LDR.0, ApicRegister::LDR.0 as u32);
1576 assert_eq!(
1577 SevAvicRegisterNumber::SPURIOUS.0,
1578 ApicRegister::SVR.0 as u32
1579 );
1580 assert_eq!(SevAvicRegisterNumber::ISR0.0, ApicRegister::ISR0.0 as u32);
1581 assert_eq!(SevAvicRegisterNumber::TMR0.0, ApicRegister::TMR0.0 as u32);
1582 assert_eq!(SevAvicRegisterNumber::IRR0.0, ApicRegister::IRR0.0 as u32);
1583 assert_eq!(SevAvicRegisterNumber::ERROR.0, ApicRegister::ESR.0 as u32);
1584 assert_eq!(
1585 SevAvicRegisterNumber::ICR_LOW.0,
1586 ApicRegister::ICR0.0 as u32
1587 );
1588 assert_eq!(
1589 SevAvicRegisterNumber::ICR_HIGH.0,
1590 ApicRegister::ICR1.0 as u32
1591 );
1592 assert_eq!(
1593 SevAvicRegisterNumber::TIMER_LVT.0,
1594 ApicRegister::LVT_TIMER.0 as u32
1595 );
1596 assert_eq!(
1597 SevAvicRegisterNumber::INITIAL_COUNT.0,
1598 ApicRegister::TIMER_ICR.0 as u32
1599 );
1600 assert_eq!(
1601 SevAvicRegisterNumber::CURRENT_COUNT.0,
1602 ApicRegister::TIMER_CCR.0 as u32
1603 );
1604 assert_eq!(
1605 SevAvicRegisterNumber::DIVIDER.0,
1606 ApicRegister::TIMER_DCR.0 as u32
1607 );
1608 assert_eq!(
1609 SevAvicRegisterNumber::SELF_IPI.0,
1610 ApicRegister::SELF_IPI.0 as u32
1611 );
1612 }
1613
1614 #[test]
1615 fn avic_register_to_x2apic_msr() {
1616 use crate::apic::X2APIC_MSR_BASE;
1618 let msr = X2APIC_MSR_BASE + SevAvicRegisterNumber::EOI.0;
1619 assert_eq!(msr, 0x80B); let msr = X2APIC_MSR_BASE + SevAvicRegisterNumber::ICR_LOW.0;
1622 assert_eq!(msr, 0x830); }
1624
1625 #[test]
1628 fn sev_exit_code_avic_values() {
1629 assert_eq!(SevExitCode::AVIC_INCOMPLETE_IPI.0, 0x401);
1630 assert_eq!(SevExitCode::AVIC_NOACCEL.0, 0x402);
1631 }
1632}