Skip to main content

hvdef/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Microsoft hypervisor definitions.
5
6#![expect(missing_docs)]
7#![forbid(unsafe_code)]
8#![no_std]
9
10pub mod save_restore;
11pub mod vbs;
12
13use bitfield_struct::bitfield;
14use core::fmt::Debug;
15use core::mem::size_of;
16use open_enum::open_enum;
17use static_assertions::const_assert;
18use zerocopy::FromBytes;
19use zerocopy::FromZeros;
20use zerocopy::Immutable;
21use zerocopy::IntoBytes;
22use zerocopy::KnownLayout;
23
24pub const HV_PAGE_SIZE: u64 = 4096;
25pub const HV_PAGE_SIZE_USIZE: usize = 4096;
26pub const HV_PAGE_SHIFT: u64 = 12;
27
28pub const HV_PARTITION_ID_SELF: u64 = u64::MAX;
29pub const HV_VP_INDEX_SELF: u32 = 0xfffffffe;
30pub const HV_ANY_VP: u32 = 0xffffffff;
31
32pub const HV_CPUID_FUNCTION_VERSION_AND_FEATURES: u32 = 0x00000001;
33pub const HV_CPUID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION: u32 = 0x40000000;
34pub const HV_CPUID_FUNCTION_HV_INTERFACE: u32 = 0x40000001;
35pub const HV_CPUID_FUNCTION_MS_HV_VERSION: u32 = 0x40000002;
36pub const HV_CPUID_FUNCTION_MS_HV_FEATURES: u32 = 0x40000003;
37pub const HV_CPUID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION: u32 = 0x40000004;
38pub const HV_CPUID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS: u32 = 0x40000005;
39pub const HV_CPUID_FUNCTION_MS_HV_HARDWARE_FEATURES: u32 = 0x40000006;
40pub const HV_CPUID_FUNCTION_MS_HV_NESTED_FEATURES: u32 = 0x4000000A;
41pub const HV_CPUID_FUNCTION_MS_HV_ISOLATION_CONFIGURATION: u32 = 0x4000000C;
42
43pub const VIRTUALIZATION_STACK_CPUID_VENDOR: u32 = 0x40000080;
44pub const VIRTUALIZATION_STACK_CPUID_INTERFACE: u32 = 0x40000081;
45pub const VIRTUALIZATION_STACK_CPUID_PROPERTIES: u32 = 0x40000082;
46
47/// The result of querying the VIRTUALIZATION_STACK_CPUID_PROPERTIES leaf.
48///
49/// The current partition is considered "portable": the virtualization stack may
50/// attempt to bring up the partition on another physical machine.
51pub const VS1_PARTITION_PROPERTIES_EAX_IS_PORTABLE: u32 = 0x000000001;
52/// The current partition has a synthetic debug device available to it.
53pub const VS1_PARTITION_PROPERTIES_EAX_DEBUG_DEVICE_PRESENT: u32 = 0x000000002;
54/// Extended I/O APIC RTEs are supported for the current partition.
55pub const VS1_PARTITION_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE: u32 = 0x000000004;
56/// Confidential VMBus is available.
57pub const VS1_PARTITION_PROPERTIES_EAX_CONFIDENTIAL_VMBUS_AVAILABLE: u32 = 0x000000008;
58
59/// SMCCC UID for the Microsoft Hypervisor.
60pub const VENDOR_HYP_UID_MS_HYPERVISOR: [u32; 4] = [0x4d32ba58, 0xcd244764, 0x8eef6c75, 0x16597024];
61
62#[bitfield(u64)]
63pub struct HvPartitionPrivilege {
64    // access to virtual msrs
65    pub access_vp_runtime_msr: bool,
66    pub access_partition_reference_counter: bool,
67    pub access_synic_msrs: bool,
68    pub access_synthetic_timer_msrs: bool,
69    pub access_apic_msrs: bool,
70    pub access_hypercall_msrs: bool,
71    pub access_vp_index: bool,
72    pub access_reset_msr: bool,
73    pub access_stats_msr: bool,
74    pub access_partition_reference_tsc: bool,
75    pub access_guest_idle_msr: bool,
76    pub access_frequency_msrs: bool,
77    pub access_debug_msrs: bool,
78    pub access_reenlightenment_ctrls: bool,
79    pub access_root_scheduler_msr: bool,
80    pub access_tsc_invariant_controls: bool,
81    _reserved1: u16,
82
83    // Access to hypercalls
84    pub create_partitions: bool,
85    pub access_partition_id: bool,
86    pub access_memory_pool: bool,
87    pub adjust_message_buffers: bool,
88    pub post_messages: bool,
89    pub signal_events: bool,
90    pub create_port: bool,
91    pub connect_port: bool,
92    pub access_stats: bool,
93    #[bits(2)]
94    _reserved2: u64,
95    pub debugging: bool,
96    pub cpu_management: bool,
97    pub configure_profiler: bool,
98    pub access_vp_exit_tracing: bool,
99    pub enable_extended_gva_ranges_flush_va_list: bool,
100    pub access_vsm: bool,
101    pub access_vp_registers: bool,
102    _unused_bit: bool,
103    pub fast_hypercall_output: bool,
104    pub enable_extended_hypercalls: bool,
105    pub start_virtual_processor: bool,
106    pub isolation: bool,
107    #[bits(9)]
108    _reserved3: u64,
109}
110
111/// Partition processor features (bank 0).
112///
113/// Each bit indicates whether the corresponding processor feature is enabled
114/// for a partition. When used in `mshv_create_partition_v2.pt_cpu_fbanks`,
115/// the sense is *inverted*: a set bit means the feature is **disabled**.
116#[bitfield(u64)]
117pub struct HvX64PartitionProcessorFeatures {
118    pub sse3_support: bool,
119    pub lahf_sahf_support: bool,
120    pub ssse3_support: bool,
121    pub sse4_1_support: bool,
122    pub sse4_2_support: bool,
123    pub sse4a_support: bool,
124    pub xop_support: bool,
125    pub pop_cnt_support: bool,
126    pub cmpxchg16b_support: bool,
127    pub altmovcr8_support: bool,
128    pub lzcnt_support: bool,
129    pub mis_align_sse_support: bool,
130    pub mmx_ext_support: bool,
131    pub amd3d_now_support: bool,
132    pub extended_amd3d_now_support: bool,
133    pub page_1gb_support: bool,
134    pub aes_support: bool,
135    pub pclmulqdq_support: bool,
136    pub pcid_support: bool,
137    pub fma4_support: bool,
138    pub f16c_support: bool,
139    pub rd_rand_support: bool,
140    pub rd_wr_fs_gs_support: bool,
141    pub smep_support: bool,
142    pub enhanced_fast_string_support: bool,
143    pub bmi1_support: bool,
144    pub bmi2_support: bool,
145    pub hle_support_deprecated: bool,
146    pub rtm_support_deprecated: bool,
147    pub movbe_support: bool,
148    pub npiep1_support: bool,
149    pub dep_x87_fpu_save_support: bool,
150    pub rd_seed_support: bool,
151    pub adx_support: bool,
152    pub intel_prefetch_support: bool,
153    pub smap_support: bool,
154    pub hle_support: bool,
155    pub rtm_support: bool,
156    pub rdtscp_support: bool,
157    pub clflushopt_support: bool,
158    pub clwb_support: bool,
159    pub sha_support: bool,
160    pub x87_pointers_saved_support: bool,
161    pub invpcid_support: bool,
162    pub ibrs_support: bool,
163    pub stibp_support: bool,
164    pub ibpb_support: bool,
165    pub unrestricted_guest_support: bool,
166    pub mdd_support: bool,
167    pub fast_short_rep_mov_support: bool,
168    pub l1d_cache_flush_support: bool,
169    pub rdcl_no_support: bool,
170    pub ibrs_all_support: bool,
171    pub skip_l1df_support: bool,
172    pub ssb_no_support: bool,
173    pub rsb_a_no_support: bool,
174    pub virt_spec_ctrl_support: bool,
175    pub rd_pid_support: bool,
176    pub umip_support: bool,
177    pub mbs_no_support: bool,
178    pub mb_clear_support: bool,
179    pub taa_no_support: bool,
180    pub tsx_ctrl_support: bool,
181    _reserved_bank0: bool,
182}
183
184/// Partition processor features (bank 1).
185#[bitfield(u64)]
186pub struct HvX64PartitionProcessorFeatures1 {
187    pub a_count_m_count_support: bool,
188    pub tsc_invariant_support: bool,
189    pub cl_zero_support: bool,
190    pub rdpru_support: bool,
191    pub la57_support: bool,
192    pub mbec_support: bool,
193    pub nested_virt_support: bool,
194    pub psfd_support: bool,
195    pub cet_ss_support: bool,
196    pub cet_ibt_support: bool,
197    pub vmx_exception_inject_support: bool,
198    pub enqcmd_support: bool,
199    pub umwait_tpause_support: bool,
200    pub movdiri_support: bool,
201    pub movdir64b_support: bool,
202    pub cldemote_support: bool,
203    pub serialize_support: bool,
204    pub tsc_deadline_tmr_support: bool,
205    pub tsc_adjust_support: bool,
206    pub fz_l_rep_movsb: bool,
207    pub fs_rep_stosb: bool,
208    pub fs_rep_cmpsb: bool,
209    pub tsx_ld_trk_support: bool,
210    pub vmx_ins_outs_exit_info_support: bool,
211    pub hlat_support: bool,
212    pub sbdr_ssdp_no_support: bool,
213    pub fbsdp_no_support: bool,
214    pub psdp_no_support: bool,
215    pub fb_clear_support: bool,
216    pub btc_no_support: bool,
217    pub ibpb_rsb_flush_support: bool,
218    pub stibp_always_on_support: bool,
219    pub perf_global_ctrl_support: bool,
220    pub npt_execute_only_support: bool,
221    pub npt_ad_flags_support: bool,
222    pub npt_1gb_page_support: bool,
223    pub amd_processor_topology_node_id_support: bool,
224    pub local_machine_check_support: bool,
225    pub extended_topology_leaf_fp256_amd_support: bool,
226    pub gds_no_support: bool,
227    pub cmpccxadd_support: bool,
228    pub tsc_aux_virtualization_support: bool,
229    pub rmp_query_support: bool,
230    pub bhi_no_support: bool,
231    pub bhi_dis_support: bool,
232    pub prefetch_i_support: bool,
233    pub sha512_support: bool,
234    pub mitigation_ctrl_support: bool,
235    pub rfds_no_support: bool,
236    pub rfds_clear_support: bool,
237    pub sm3_support: bool,
238    pub sm4_support: bool,
239    pub secure_avic_support: bool,
240    pub guest_intercept_ctrl_support: bool,
241    pub sbpb_support: bool,
242    pub ibpb_br_type_support: bool,
243    pub srso_no_support: bool,
244    pub srso_user_kernel_no_support: bool,
245    pub vrew_clear_support: bool,
246    pub tsa_l1_no_support: bool,
247    pub tsa_sq_no_support: bool,
248    pub lass_support: bool,
249    #[bits(2)]
250    _reserved_bank1: u8,
251}
252
253/// Partition processor XSAVE features.
254#[bitfield(u64)]
255pub struct HvX64PartitionProcessorXsaveFeatures {
256    pub xsave_support: bool,
257    pub xsaveopt_support: bool,
258    pub avx_support: bool,
259    pub avx2_support: bool,
260    pub fma_support: bool,
261    pub mpx_support: bool,
262    pub avx512_support: bool,
263    pub avx512_dq_support: bool,
264    pub avx512_cd_support: bool,
265    pub avx512_bw_support: bool,
266    pub avx512_vl_support: bool,
267    pub xsave_comp_support: bool,
268    pub xsave_supervisor_support: bool,
269    pub xcr1_support: bool,
270    pub avx512_bitalg_support: bool,
271    pub avx512_ifma_support: bool,
272    pub avx512_vbmi_support: bool,
273    pub avx512_vbmi2_support: bool,
274    pub avx512_vnni_support: bool,
275    pub gfni_support: bool,
276    pub vaes_support: bool,
277    pub avx512_vpopcntdq_support: bool,
278    pub vpclmulqdq_support: bool,
279    pub avx512_bf16_support: bool,
280    pub avx512_vp2_intersect_support: bool,
281    pub avx512_fp16_support: bool,
282    pub xfd_support: bool,
283    pub amx_tile_support: bool,
284    pub amx_bf16_support: bool,
285    pub amx_int8_support: bool,
286    pub avx_vnni_support: bool,
287    pub avx_ifma_support: bool,
288    pub avx_ne_convert_support: bool,
289    pub avx_vnni_int8_support: bool,
290    pub avx_vnni_int16_support: bool,
291    pub avx10_1_256_support: bool,
292    pub avx10_1_512_support: bool,
293    pub amx_fp16_support: bool,
294    #[bits(26)]
295    _reserved: u64,
296}
297
298/// Synthetic processor features that control which Hyper-V enlightenments
299/// are exposed to a guest partition.
300#[bitfield(u64)]
301pub struct HvPartitionSyntheticProcessorFeatures {
302    pub hypervisor_present: bool,
303    pub hv1: bool,
304    pub access_vp_run_time_reg: bool,
305    pub access_partition_reference_counter: bool,
306    pub access_synic_regs: bool,
307    pub access_synthetic_timer_regs: bool,
308    pub access_intr_ctrl_regs: bool,
309    pub access_hypercall_regs: bool,
310    pub access_vp_index: bool,
311    pub access_partition_reference_tsc: bool,
312    pub access_guest_idle_reg: bool,
313    pub access_frequency_regs: bool,
314    _reserved_z12: bool,
315    _reserved_z13: bool,
316    _reserved_z14: bool,
317    pub enable_extended_gva_ranges_for_flush_virtual_address_list: bool,
318    _reserved_z16: bool,
319    _reserved_z17: bool,
320    pub fast_hypercall_output: bool,
321    _reserved_z19: bool,
322    pub start_virtual_processor: bool,
323    _reserved_z21: bool,
324    pub direct_synthetic_timers: bool,
325    _reserved_z23: bool,
326    pub extended_processor_masks: bool,
327    pub tb_flush_hypercalls: bool,
328    pub synthetic_cluster_ipi: bool,
329    pub notify_long_spin_wait: bool,
330    pub query_numa_distance: bool,
331    pub signal_events: bool,
332    pub retarget_device_interrupt: bool,
333    pub restore_time: bool,
334    pub enlightened_vmcs: bool,
335    pub nested_debug_ctl: bool,
336    pub synthetic_time_unhalted_timer: bool,
337    pub idle_spec_ctrl: bool,
338    _reserved_z36: bool,
339    pub wake_vps: bool,
340    pub access_vp_regs: bool,
341    pub sync_context: bool,
342    pub management_vtl_synic_support: bool,
343    pub proxy_interrupt_doorbell_support: bool,
344    _reserved_z42: bool,
345    pub mmio_hypercalls: bool,
346    #[bits(20)]
347    _reserved: u64,
348}
349
350open_enum! {
351    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
352    pub enum HvPartitionIsolationType: u8 {
353        NONE = 0,
354        VBS = 1,
355        SNP = 2,
356        TDX = 3,
357        CCA = 4,
358    }
359}
360
361open_enum! {
362    /// Partition property codes.
363    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
364    pub enum HvPartitionPropertyCode: u32 {
365        #![expect(non_upper_case_globals)]
366
367        // Privilege properties
368        PrivilegeFlags                       = 0x00010000,
369        SyntheticProcFeatures                = 0x00010001,
370        AllowedParentUserModeHypercalls      = 0x00010002,
371
372        // Scheduling properties
373        Suspend                                = 0x00020000,
374        CpuReserve                             = 0x00020001,
375        CpuCap                                 = 0x00020002,
376        CpuWeight                              = 0x00020003,
377        CpuGroupId                             = 0x00020004,
378        HierarchicalIntegratedSchedulerEnabled = 0x00020005,
379
380        // Time properties
381        TimeFreeze                           = 0x00030003,
382        ApicFrequency                        = 0x00030004,
383        ReferenceTime                        = 0x00030005,
384
385        // Debugging properties
386        DebugChannelId                       = 0x00040000,
387        DebugChannelId0                      = 0x00040001,
388        DebugChannelId1                      = 0x00040002,
389        DebugChannelId2                      = 0x00040003,
390
391        // Resource properties
392        VirtualTlbPageCount                  = 0x00050000,
393        VsmConfig                            = 0x00050001,
394        ZeroMemoryOnReset                    = 0x00050002,
395        ProcessorsPerSocket                  = 0x00050003,
396        NestedTlbSize                        = 0x00050004,
397        GpaPageAccessTracking                = 0x00050005,
398        VsmPermissionsDirtySinceLastQuery    = 0x00050006,
399        SgxLaunchControlConfig               = 0x00050007,
400        DefaultSgxLaunchControl0             = 0x00050008,
401        DefaultSgxLaunchControl1             = 0x00050009,
402        DefaultSgxLaunchControl2             = 0x0005000A,
403        DefaultSgxLaunchControl3             = 0x0005000B,
404        IsolationState                       = 0x0005000C,
405        IsolationControl                     = 0x0005000D,
406        AllocationId                         = 0x0005000E,
407        MonitoringId                         = 0x0005000F,
408        ImplementedPhysicalAddressBits       = 0x00050010,
409        NonArchitecturalCoreSharing          = 0x00050011,
410        HypercallDoorbellPage                = 0x00050012,
411        CppcRequestValue                     = 0x00050013,
412        IsolationPolicy                      = 0x00050014,
413        DmaCapableDevices                    = 0x00050015,
414        ProcessorsPerL3                      = 0x00050016,
415        UnimplementedMsrAction               = 0x00050017,
416        AmdNodesPerSocket                    = 0x00050018,
417        ReferenceTscPageActive               = 0x00050019,
418        AutoEoiEnabled                       = 0x0005001A,
419        L3CacheWays                          = 0x0005001B,
420        IsolationType                        = 0x0005001C,
421        PerfmonMode                          = 0x0005001D,
422        DepositStatus                        = 0x0005001E,
423        Mirroring                            = 0x0005001F,
424        MirrorState                          = 0x00050020,
425        MgmtVtlMaxMemorySections             = 0x00050021,
426        SevVmgexitOffloads                   = 0x00050022,
427        PenalizeBusLock                      = 0x00050023,
428        TopologyApicIdOptIn                  = 0x00050024,
429        CppcResourcePrioritiesValue          = 0x00050025,
430        PartitionDiagBufferConfig            = 0x00050026,
431        GicdBaseAddress                      = 0x00050028,
432        GitsTranslaterBaseAddress            = 0x00050029,
433        GicLpiIntIdBits                      = 0x0005002A,
434        GicPpiOverflowInterruptFromCntv      = 0x0005002B,
435        GicPpiOverflowInterruptFromCntp      = 0x0005002C,
436        GicPpiPerformanceMonitorsInterrupt   = 0x0005002D,
437        GicPpiPmbirq                         = 0x0005002E,
438        TdMigrationStreamCount               = 0x0005002F,
439        AutoSuspend                          = 0x00050030,
440        SintReservedInterruptId              = 0x00050031,
441        GpaPinningEnabled                    = 0x00050032,
442        TdMigrationMaxStreamCount            = 0x00050033,
443        TdMigrationNumMemScanContext         = 0x00050034,
444        TdMigrationMaxMemScanRanges          = 0x00050035,
445
446        // Compatibility properties
447        ProcessorVendor                      = 0x00060000,
448        ProcessorFeaturesDeprecated          = 0x00060001,
449        ProcessorXsaveFeatures               = 0x00060002,
450        ProcessorCLFlushSize                 = 0x00060003,
451        EnlightenmentModifications           = 0x00060004,
452        CompatibilityVersion                 = 0x00060005,
453        PhysicalAddressWidth                 = 0x00060006,
454        XsaveStates                          = 0x00060007,
455        MaxXsaveDataSize                     = 0x00060008,
456        ProcessorClockFrequency              = 0x00060009,
457        ProcessorFeatures0                   = 0x0006000A,
458        ProcessorFeatures1                   = 0x0006000B,
459        ProcessorCtrEl0                      = 0x0006000C,
460        ProcessorDczidEl0                    = 0x0006000D,
461        ProcessorIchVtrEl2                   = 0x0006000E,
462        ProcessorIdAa64Dfr0El1               = 0x0006000F,
463        RootProcessorFeatures0               = 0x00060010,
464        RootProcessorFeatures1               = 0x00060011,
465        RootProcessorXsaveFeatures           = 0x00060012,
466        RootSyntheticProcFeatures            = 0x00060013,
467        PhysicalAddressSize                  = 0x00060014,
468        FeatureBankCount                     = 0x00060015,
469        ProcessorIdAa64Dfr1El1               = 0x00060016,
470        ProcessorCntfrqEl0                   = 0x00060017,
471        MaxSveVectorLength                   = 0x00060018,
472        MaxSmeStreamingVectorLength          = 0x00060019,
473
474        // Guest software properties
475        GuestOsId                            = 0x00070000,
476
477        // Nested virtualization properties
478        ProcessorVirtualizationFeatures      = 0x00080000,
479        MaxHardwareIsolatedGuests            = 0x00080001,
480        SnpEnabled                           = 0x00080002,
481        NestedVmxBasic                       = 0x00080003,
482        NestedVmxPinbasedCtls                = 0x00080004,
483        NestedVmxProcbasedCtls               = 0x00080005,
484        NestedVmxExitCtls                    = 0x00080006,
485        NestedVmxEntryCtls                   = 0x00080007,
486        NestedVmxMisc                        = 0x00080008,
487        NestedVmxCr0Fixed0                   = 0x00080009,
488        NestedVmxCr0Fixed1                   = 0x0008000A,
489        NestedVmxCr4Fixed0                   = 0x0008000B,
490        NestedVmxCr4Fixed1                   = 0x0008000C,
491        NestedVmxVmcsEnum                    = 0x0008000D,
492        NestedVmxProcbasedCtls2              = 0x0008000E,
493        NestedVmxEptVpidCap                  = 0x0008000F,
494        NestedVmxTruePinbasedCtls            = 0x00080010,
495        NestedVmxTrueProcbasedCtls           = 0x00080011,
496        NestedVmxTrueExitCtls                = 0x00080012,
497        NestedVmxTrueEntryCtls               = 0x00080013,
498        NestedVmxProcbasedCtls3              = 0x00080014,
499        NestedVmxExitCtls2                   = 0x00080015,
500        VhState                              = 0x00080100,
501        MaxHierarchicalPartitionCount        = 0x00080101,
502        MaxHierarchicalVpCount               = 0x00080102,
503        StateTransferMode                    = 0x00080103,
504        MigrationAbortCleanupCount           = 0x00080104,
505        TdComprehensiveReset                 = 0x00080105,
506
507        // Extended properties with larger property values
508        InheritedDeviceDomainReservedRegions = 0x00090000,
509        TdMrConfigId                         = 0x00090001,
510        TdMrOwner                            = 0x00090002,
511        TdMrOwnerConfig                      = 0x00090003,
512        VNUMATopologyConfig                  = 0x00090004,
513        RootVpSharedPages                    = 0x00090005,
514        VmmCapabilities                      = 0x00090007,
515        CompletePartitionIntercept           = 0x00090008,
516        AssignableSyntheticProcFeatures      = 0x00090009,
517        HwIsolationTdxSupported              = 0x0009000A,
518        HwIsolationSevSupported              = 0x0009000B,
519        MigrationTdInfoHash                  = 0x0009000C,
520        MigrationTdBindingSlot               = 0x0009000D,
521        DisabledProcessorFeaturesEx          = 0x0009000E,
522        RootProcessorFeaturesEx              = 0x0009000F,
523        EnabledProcessorFeaturesEx           = 0x00090010,
524        PmuEventTypes                        = 0x00090011,
525        TdComprehensiveConfigure             = 0x00090012,
526    }
527}
528
529open_enum! {
530    /// Processor vendor as returned by [`HvPartitionPropertyCode::ProcessorVendor`].
531    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
532    pub enum HvProcessorVendor: u32 {
533        AMD    = 0x0000,
534        INTEL  = 0x0001,
535        HYGON  = 0x0002,
536        ARM    = 0x0010,
537    }
538}
539
540#[bitfield(u128)]
541#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
542pub struct HvFeatures {
543    #[bits(64)]
544    pub privileges: HvPartitionPrivilege,
545
546    #[bits(4)]
547    pub max_supported_cstate: u32,
548    pub hpet_needed_for_c3_power_state_deprecated: bool,
549    pub invariant_mperf_available: bool,
550    pub supervisor_shadow_stack_available: bool,
551    pub arch_pmu_available: bool,
552    pub exception_trap_intercept_available: bool,
553    #[bits(23)]
554    reserved: u32,
555
556    pub mwait_available_deprecated: bool,
557    pub guest_debugging_available: bool,
558    pub performance_monitors_available: bool,
559    pub cpu_dynamic_partitioning_available: bool,
560    pub xmm_registers_for_fast_hypercall_available: bool,
561    pub guest_idle_available: bool,
562    pub hypervisor_sleep_state_support_available: bool,
563    pub numa_distance_query_available: bool,
564    pub frequency_regs_available: bool,
565    pub synthetic_machine_check_available: bool,
566    pub guest_crash_regs_available: bool,
567    pub debug_regs_available: bool,
568    pub npiep1_available: bool,
569    pub disable_hypervisor_available: bool,
570    pub extended_gva_ranges_for_flush_virtual_address_list_available: bool,
571    pub fast_hypercall_output_available: bool,
572    pub svm_features_available: bool,
573    pub sint_polling_mode_available: bool,
574    pub hypercall_msr_lock_available: bool,
575    pub direct_synthetic_timers: bool,
576    pub register_pat_available: bool,
577    pub register_bndcfgs_available: bool,
578    pub watchdog_timer_available: bool,
579    pub synthetic_time_unhalted_timer_available: bool,
580    pub device_domains_available: bool,    // HDK only.
581    pub s1_device_domains_available: bool, // HDK only.
582    pub lbr_available: bool,
583    pub ipt_available: bool,
584    pub cross_vtl_flush_available: bool,
585    pub idle_spec_ctrl_available: bool,
586    pub translate_gva_flags_available: bool,
587    pub apic_eoi_intercept_available: bool,
588}
589
590impl HvFeatures {
591    pub fn from_cpuid(cpuid: [u32; 4]) -> Self {
592        zerocopy::transmute!(cpuid)
593    }
594
595    pub fn into_cpuid(self) -> [u32; 4] {
596        zerocopy::transmute!(self)
597    }
598}
599
600#[bitfield(u128)]
601#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
602pub struct HvEnlightenmentInformation {
603    pub use_hypercall_for_address_space_switch: bool,
604    pub use_hypercall_for_local_flush: bool,
605    pub use_hypercall_for_remote_flush_and_local_flush_entire: bool,
606    pub use_apic_msrs: bool,
607    pub use_hv_register_for_reset: bool,
608    pub use_relaxed_timing: bool,
609    pub use_dma_remapping_deprecated: bool,
610    pub use_interrupt_remapping_deprecated: bool,
611    pub use_x2_apic_msrs: bool,
612    pub deprecate_auto_eoi: bool,
613    pub use_synthetic_cluster_ipi: bool,
614    pub use_ex_processor_masks: bool,
615    pub nested: bool,
616    pub use_int_for_mbec_system_calls: bool,
617    pub use_vmcs_enlightenments: bool,
618    pub use_synced_timeline: bool,
619    pub core_scheduler_requested: bool,
620    pub use_direct_local_flush_entire: bool,
621    pub no_non_architectural_core_sharing: bool,
622    pub use_x2_apic: bool,
623    pub restore_time_on_resume: bool,
624    pub use_hypercall_for_mmio_access: bool,
625    pub use_gpa_pinning_hypercall: bool,
626    pub wake_vps: bool,
627    _reserved: u8,
628    pub long_spin_wait_count: u32,
629    #[bits(7)]
630    pub implemented_physical_address_bits: u32,
631    #[bits(25)]
632    _reserved1: u32,
633    _reserved2: u32,
634}
635
636impl HvEnlightenmentInformation {
637    pub fn from_cpuid(cpuid: [u32; 4]) -> Self {
638        zerocopy::transmute!(cpuid)
639    }
640
641    pub fn into_cpuid(self) -> [u32; 4] {
642        zerocopy::transmute!(self)
643    }
644}
645
646/// The EAX result of the `HV_CPUID_FUNCTION_MS_HV_NESTED_FEATURES` (0x4000000A)
647/// cpuid leaf, describing the nested virtualization enlightenments the
648/// hypervisor offers to a nested (L1) hypervisor.
649#[bitfield(u32)]
650#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
651pub struct HvNestedVirtFeaturesEax {
652    pub enlightened_vmcs_version_low: u8,
653    pub enlightened_vmcs_version_high: u8,
654    _reserved16: bool,
655    pub nested_flush_virtual_hypercall: bool,
656    pub flush_guest_physical_hypercall: bool,
657    pub msr_bitmap: bool,
658    pub virtualization_exception: bool,
659    pub debug_ctl: bool,
660    pub enlightened_npt_tlb: bool,
661    #[bits(9)]
662    _reserved23: u32,
663}
664
665#[bitfield(u128)]
666pub struct HvHardwareFeatures {
667    pub apic_overlay_assist_in_use: bool,
668    pub msr_bitmaps_in_use: bool,
669    pub architectural_performance_counters_in_use: bool,
670    pub second_level_address_translation_in_use: bool,
671    pub dma_remapping_in_use: bool,
672    pub interrupt_remapping_in_use: bool,
673    pub memory_patrol_scrubber_present: bool,
674    pub dma_protection_in_use: bool,
675    pub hpet_requested: bool,
676    pub synthetic_timers_volatile: bool,
677    #[bits(4)]
678    pub hypervisor_level: u32,
679    pub physical_destination_mode_required: bool,
680    pub use_vmfunc_for_alias_map_switch: bool,
681    pub hv_register_for_memory_zeroing_supported: bool,
682    pub unrestricted_guest_supported: bool,
683    pub rdt_afeatures_supported: bool,
684    pub rdt_mfeatures_supported: bool,
685    pub child_perfmon_pmu_supported: bool,
686    pub child_perfmon_lbr_supported: bool,
687    pub child_perfmon_ipt_supported: bool,
688    pub apic_emulation_supported: bool,
689    pub child_x2_apic_recommended: bool,
690    pub hardware_watchdog_reserved: bool,
691    pub device_access_tracking_supported: bool,
692    pub hardware_gpa_access_tracking_supported: bool,
693    #[bits(4)]
694    _reserved: u32,
695
696    pub device_domain_input_width: u8,
697    #[bits(24)]
698    _reserved1: u32,
699    _reserved2: u32,
700    _reserved3: u32,
701}
702
703#[bitfield(u128)]
704pub struct HvIsolationConfiguration {
705    pub paravisor_present: bool,
706    #[bits(31)]
707    pub _reserved0: u32,
708
709    #[bits(4)]
710    pub isolation_type: u8,
711    _reserved11: bool,
712    pub shared_gpa_boundary_active: bool,
713    #[bits(6)]
714    pub shared_gpa_boundary_bits: u8,
715    #[bits(20)]
716    _reserved12: u32,
717    _reserved2: u32,
718    _reserved3: u32,
719}
720
721open_enum! {
722    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
723    pub enum HypercallCode: u16 {
724        #![expect(non_upper_case_globals)]
725
726        HvCallSwitchVirtualAddressSpace = 0x0001,
727        HvCallFlushVirtualAddressSpace = 0x0002,
728        HvCallFlushVirtualAddressList = 0x0003,
729        HvCallNotifyLongSpinWait = 0x0008,
730        HvCallInvokeHypervisorDebugger = 0x000a,
731        HvCallSendSyntheticClusterIpi = 0x000b,
732        HvCallModifyVtlProtectionMask = 0x000c,
733        HvCallEnablePartitionVtl = 0x000d,
734        HvCallEnableVpVtl = 0x000f,
735        HvCallVtlCall = 0x0011,
736        HvCallVtlReturn = 0x0012,
737        HvCallFlushVirtualAddressSpaceEx = 0x0013,
738        HvCallFlushVirtualAddressListEx = 0x0014,
739        HvCallSendSyntheticClusterIpiEx = 0x0015,
740        HvCallInstallIntercept = 0x004d,
741        HvCallGetVpRegisters = 0x0050,
742        HvCallSetVpRegisters = 0x0051,
743        HvCallTranslateVirtualAddress = 0x0052,
744        HvCallPostMessage = 0x005C,
745        HvCallSignalEvent = 0x005D,
746        HvCallOutputDebugCharacter = 0x0071,
747        HvCallGetSystemProperty = 0x007b,
748        HvCallRetargetDeviceInterrupt = 0x007e,
749        HvCallNotifyPartitionEvent = 0x0087,
750        HvCallRegisterInterceptResult = 0x0091,
751        HvCallAssertVirtualInterrupt = 0x0094,
752        HvCallStartVirtualProcessor = 0x0099,
753        HvCallGetVpIndexFromApicId = 0x009A,
754        HvCallTranslateVirtualAddressEx = 0x00AC,
755        HvCallCheckForIoIntercept = 0x00ad,
756        HvCallFlushGuestPhysicalAddressSpace = 0x00AF,
757        HvCallFlushGuestPhysicalAddressList = 0x00B0,
758        HvCallSignalEventDirect = 0x00C0,
759        HvCallPostMessageDirect = 0x00C1,
760        HvCallCheckSparseGpaPageVtlAccess = 0x00D4,
761        HvCallAcceptGpaPages = 0x00D9,
762        HvCallModifySparseGpaPageHostVisibility = 0x00DB,
763        HvCallGetVpCpuidValues = 0x00F4,
764        HvCallRestorePartitionTime = 0x0103,
765        HvCallMemoryMappedIoRead = 0x0106,
766        HvCallMemoryMappedIoWrite = 0x0107,
767        HvCallPinGpaPageRanges = 0x0112,
768        HvCallUnpinGpaPageRanges = 0x0113,
769        HvCallQuerySparseGpaPageHostVisibility = 0x011C,
770
771        // Extended hypercalls.
772        HvExtCallQueryCapabilities = 0x8001,
773
774        // VBS guest calls.
775        HvCallVbsVmCallReport = 0xC001,
776    }
777}
778
779pub const HV_X64_MSR_GUEST_OS_ID: u32 = 0x40000000;
780pub const HV_X64_MSR_HYPERCALL: u32 = 0x40000001;
781pub const HV_X64_MSR_VP_INDEX: u32 = 0x40000002;
782pub const HV_X64_MSR_TIME_REF_COUNT: u32 = 0x40000020;
783pub const HV_X64_MSR_REFERENCE_TSC: u32 = 0x40000021;
784pub const HV_X64_MSR_TSC_FREQUENCY: u32 = 0x40000022;
785pub const HV_X64_MSR_APIC_FREQUENCY: u32 = 0x40000023;
786pub const HV_X64_MSR_EOI: u32 = 0x40000070;
787pub const HV_X64_MSR_ICR: u32 = 0x40000071;
788pub const HV_X64_MSR_TPR: u32 = 0x40000072;
789pub const HV_X64_MSR_VP_ASSIST_PAGE: u32 = 0x40000073;
790pub const HV_X64_MSR_SCONTROL: u32 = 0x40000080;
791pub const HV_X64_MSR_SVERSION: u32 = 0x40000081;
792pub const HV_X64_MSR_SIEFP: u32 = 0x40000082;
793pub const HV_X64_MSR_SIMP: u32 = 0x40000083;
794pub const HV_X64_MSR_EOM: u32 = 0x40000084;
795pub const HV_X64_MSR_SINT0: u32 = 0x40000090;
796pub const HV_X64_MSR_SINT1: u32 = 0x40000091;
797pub const HV_X64_MSR_SINT2: u32 = 0x40000092;
798pub const HV_X64_MSR_SINT3: u32 = 0x40000093;
799pub const HV_X64_MSR_SINT4: u32 = 0x40000094;
800pub const HV_X64_MSR_SINT5: u32 = 0x40000095;
801pub const HV_X64_MSR_SINT6: u32 = 0x40000096;
802pub const HV_X64_MSR_SINT7: u32 = 0x40000097;
803pub const HV_X64_MSR_SINT8: u32 = 0x40000098;
804pub const HV_X64_MSR_SINT9: u32 = 0x40000099;
805pub const HV_X64_MSR_SINT10: u32 = 0x4000009a;
806pub const HV_X64_MSR_SINT11: u32 = 0x4000009b;
807pub const HV_X64_MSR_SINT12: u32 = 0x4000009c;
808pub const HV_X64_MSR_SINT13: u32 = 0x4000009d;
809pub const HV_X64_MSR_SINT14: u32 = 0x4000009e;
810pub const HV_X64_MSR_SINT15: u32 = 0x4000009f;
811pub const HV_X64_MSR_STIMER0_CONFIG: u32 = 0x400000b0;
812pub const HV_X64_MSR_STIMER0_COUNT: u32 = 0x400000b1;
813pub const HV_X64_MSR_STIMER1_CONFIG: u32 = 0x400000b2;
814pub const HV_X64_MSR_STIMER1_COUNT: u32 = 0x400000b3;
815pub const HV_X64_MSR_STIMER2_CONFIG: u32 = 0x400000b4;
816pub const HV_X64_MSR_STIMER2_COUNT: u32 = 0x400000b5;
817pub const HV_X64_MSR_STIMER3_CONFIG: u32 = 0x400000b6;
818pub const HV_X64_MSR_STIMER3_COUNT: u32 = 0x400000b7;
819pub const HV_X64_MSR_GUEST_IDLE: u32 = 0x400000F0;
820pub const HV_X64_MSR_GUEST_CRASH_P0: u32 = 0x40000100;
821pub const HV_X64_MSR_GUEST_CRASH_P1: u32 = 0x40000101;
822pub const HV_X64_MSR_GUEST_CRASH_P2: u32 = 0x40000102;
823pub const HV_X64_MSR_GUEST_CRASH_P3: u32 = 0x40000103;
824pub const HV_X64_MSR_GUEST_CRASH_P4: u32 = 0x40000104;
825pub const HV_X64_MSR_GUEST_CRASH_CTL: u32 = 0x40000105;
826
827pub const HV_X64_GUEST_CRASH_PARAMETER_MSRS: usize = 5;
828
829/// A hypervisor status code.
830///
831/// The non-success status codes are defined in [`HvError`].
832#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
833#[repr(transparent)]
834pub struct HvStatus(pub u16);
835
836impl HvStatus {
837    /// The success status code.
838    pub const SUCCESS: Self = Self(0);
839
840    /// Returns `Ok(())` if this is `HvStatus::SUCCESS`, otherwise returns an
841    /// `Err(err)` where `err` is the corresponding `HvError`.
842    pub fn result(self) -> HvResult<()> {
843        if let Ok(err) = self.0.try_into() {
844            Err(HvError(err))
845        } else {
846            Ok(())
847        }
848    }
849
850    /// Returns true if this is `HvStatus::SUCCESS`.
851    pub fn is_ok(self) -> bool {
852        self == Self::SUCCESS
853    }
854
855    /// Returns true if this is not `HvStatus::SUCCESS`.
856    pub fn is_err(self) -> bool {
857        self != Self::SUCCESS
858    }
859
860    const fn from_bits(bits: u16) -> Self {
861        Self(bits)
862    }
863
864    const fn into_bits(self) -> u16 {
865        self.0
866    }
867}
868
869impl From<Result<(), HvError>> for HvStatus {
870    fn from(err: Result<(), HvError>) -> Self {
871        err.err().map_or(Self::SUCCESS, |err| Self(err.0.get()))
872    }
873}
874
875impl Debug for HvStatus {
876    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
877        match self.result() {
878            Ok(()) => f.write_str("Success"),
879            Err(err) => Debug::fmt(&err, f),
880        }
881    }
882}
883
884/// An [`HvStatus`] value representing an error.
885//
886// DEVNOTE: use `NonZeroU16` to get a niche optimization, since 0 is reserved
887// for success.
888#[derive(Copy, Clone, PartialEq, Eq, IntoBytes, Immutable, KnownLayout)]
889#[repr(transparent)]
890pub struct HvError(core::num::NonZeroU16);
891
892impl From<core::num::NonZeroU16> for HvError {
893    fn from(err: core::num::NonZeroU16) -> Self {
894        Self(err)
895    }
896}
897
898impl Debug for HvError {
899    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
900        match self.debug_name() {
901            Some(name) => f.pad(name),
902            None => Debug::fmt(&self.0.get(), f),
903        }
904    }
905}
906
907impl core::fmt::Display for HvError {
908    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
909        match self.doc_str() {
910            Some(s) => f.write_str(s),
911            None => write!(f, "Hypervisor error {:#06x}", self.0),
912        }
913    }
914}
915
916impl core::error::Error for HvError {}
917
918macro_rules! hv_error {
919    ($ty:ty, $(#[doc = $doc:expr] $ident:ident = $val:expr),* $(,)?) => {
920
921        #[expect(non_upper_case_globals)]
922        impl $ty {
923            $(
924                #[doc = $doc]
925                pub const $ident: Self = Self(core::num::NonZeroU16::new($val).unwrap());
926            )*
927
928            fn debug_name(&self) -> Option<&'static str> {
929                Some(match self.0.get() {
930                    $(
931                        $val => stringify!($ident),
932                    )*
933                    _ => return None,
934                })
935            }
936
937            fn doc_str(&self) -> Option<&'static str> {
938                Some(match self.0.get() {
939                    $(
940                        $val => const { $doc.trim_ascii() },
941                    )*
942                    _ => return None,
943                })
944            }
945        }
946    };
947}
948
949// DEVNOTE: the doc comments here are also used as the runtime error strings.
950hv_error! {
951    HvError,
952    /// Invalid hypercall code
953    InvalidHypercallCode = 0x0002,
954    /// Invalid hypercall input
955    InvalidHypercallInput = 0x0003,
956    /// Invalid alignment
957    InvalidAlignment = 0x0004,
958    /// Invalid parameter
959    InvalidParameter = 0x0005,
960    /// Access denied
961    AccessDenied = 0x0006,
962    /// Invalid partition state
963    InvalidPartitionState = 0x0007,
964    /// Operation denied
965    OperationDenied = 0x0008,
966    /// Unknown property
967    UnknownProperty = 0x0009,
968    /// Property value out of range
969    PropertyValueOutOfRange = 0x000A,
970    /// Insufficient memory
971    InsufficientMemory = 0x000B,
972    /// Partition too deep
973    PartitionTooDeep = 0x000C,
974    /// Invalid partition ID
975    InvalidPartitionId = 0x000D,
976    /// Invalid VP index
977    InvalidVpIndex = 0x000E,
978    /// Not found
979    NotFound = 0x0010,
980    /// Invalid port ID
981    InvalidPortId = 0x0011,
982    /// Invalid connection ID
983    InvalidConnectionId = 0x0012,
984    /// Insufficient buffers
985    InsufficientBuffers = 0x0013,
986    /// Not acknowledged
987    NotAcknowledged = 0x0014,
988    /// Invalid VP state
989    InvalidVpState = 0x0015,
990    /// Acknowledged
991    Acknowledged = 0x0016,
992    /// Invalid save restore state
993    InvalidSaveRestoreState = 0x0017,
994    /// Invalid SynIC state
995    InvalidSynicState = 0x0018,
996    /// Object in use
997    ObjectInUse = 0x0019,
998    /// Invalid proximity domain info
999    InvalidProximityDomainInfo = 0x001A,
1000    /// No data
1001    NoData = 0x001B,
1002    /// Inactive
1003    Inactive = 0x001C,
1004    /// No resources
1005    NoResources = 0x001D,
1006    /// Feature unavailable
1007    FeatureUnavailable = 0x001E,
1008    /// Partial packet
1009    PartialPacket = 0x001F,
1010    /// Processor feature not supported
1011    ProcessorFeatureNotSupported = 0x0020,
1012    /// Processor cache line flush size incompatible
1013    ProcessorCacheLineFlushSizeIncompatible = 0x0030,
1014    /// Insufficient buffer
1015    InsufficientBuffer = 0x0033,
1016    /// Incompatible processor
1017    IncompatibleProcessor = 0x0037,
1018    /// Insufficient device domains
1019    InsufficientDeviceDomains = 0x0038,
1020    /// CPUID feature validation error
1021    CpuidFeatureValidationError = 0x003C,
1022    /// CPUID XSAVE feature validation error
1023    CpuidXsaveFeatureValidationError = 0x003D,
1024    /// Processor startup timeout
1025    ProcessorStartupTimeout = 0x003E,
1026    /// SMX enabled
1027    SmxEnabled = 0x003F,
1028    /// Invalid LP index
1029    InvalidLpIndex = 0x0041,
1030    /// Invalid register value
1031    InvalidRegisterValue = 0x0050,
1032    /// Invalid VTL state
1033    InvalidVtlState = 0x0051,
1034    /// NX not detected
1035    NxNotDetected = 0x0055,
1036    /// Invalid device ID
1037    InvalidDeviceId = 0x0057,
1038    /// Invalid device state
1039    InvalidDeviceState = 0x0058,
1040    /// Pending page requests
1041    PendingPageRequests = 0x0059,
1042    /// Page request invalid
1043    PageRequestInvalid = 0x0060,
1044    /// Key already exists
1045    KeyAlreadyExists = 0x0065,
1046    /// Device already in domain
1047    DeviceAlreadyInDomain = 0x0066,
1048    /// Invalid CPU group ID
1049    InvalidCpuGroupId = 0x006F,
1050    /// Invalid CPU group state
1051    InvalidCpuGroupState = 0x0070,
1052    /// Operation failed
1053    OperationFailed = 0x0071,
1054    /// Not allowed with nested virtualization active
1055    NotAllowedWithNestedVirtActive = 0x0072,
1056    /// Insufficient root memory
1057    InsufficientRootMemory = 0x0073,
1058    /// Event buffer already freed
1059    EventBufferAlreadyFreed = 0x0074,
1060    /// The specified timeout expired before the operation completed.
1061    Timeout = 0x0078,
1062    /// The VTL specified for the operation is already in an enabled state.
1063    VtlAlreadyEnabled = 0x0086,
1064    /// Unknown register name
1065    UnknownRegisterName = 0x0087,
1066}
1067
1068/// A useful result type for hypervisor operations.
1069pub type HvResult<T> = Result<T, HvError>;
1070
1071#[repr(u8)]
1072#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1073pub enum Vtl {
1074    Vtl0 = 0,
1075    Vtl1 = 1,
1076    Vtl2 = 2,
1077}
1078
1079impl TryFrom<u8> for Vtl {
1080    type Error = HvError;
1081
1082    fn try_from(value: u8) -> Result<Self, Self::Error> {
1083        Ok(match value {
1084            0 => Self::Vtl0,
1085            1 => Self::Vtl1,
1086            2 => Self::Vtl2,
1087            _ => return Err(HvError::InvalidParameter),
1088        })
1089    }
1090}
1091
1092impl From<Vtl> for u8 {
1093    fn from(value: Vtl) -> Self {
1094        value as u8
1095    }
1096}
1097
1098/// The contents of `HV_X64_MSR_GUEST_CRASH_CTL`
1099#[bitfield(u64)]
1100pub struct GuestCrashCtl {
1101    #[bits(58)]
1102    _reserved: u64,
1103    // ID of the pre-OS environment
1104    #[bits(3)]
1105    pub pre_os_id: u8,
1106    // Crash dump will not be captured
1107    #[bits(1)]
1108    pub no_crash_dump: bool,
1109    // `HV_X64_MSR_GUEST_CRASH_P3` is the GPA of the message,
1110    // `HV_X64_MSR_GUEST_CRASH_P4` is its length in bytes
1111    #[bits(1)]
1112    pub crash_message: bool,
1113    // Log contents of crash parameter system registers
1114    #[bits(1)]
1115    pub crash_notify: bool,
1116}
1117
1118#[repr(C, align(16))]
1119#[derive(Copy, Clone, PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
1120pub struct AlignedU128([u8; 16]);
1121
1122impl AlignedU128 {
1123    pub fn as_ne_bytes(&self) -> [u8; 16] {
1124        self.0
1125    }
1126
1127    pub fn from_ne_bytes(val: [u8; 16]) -> Self {
1128        Self(val)
1129    }
1130}
1131
1132impl Debug for AlignedU128 {
1133    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1134        Debug::fmt(&u128::from_ne_bytes(self.0), f)
1135    }
1136}
1137
1138impl From<u128> for AlignedU128 {
1139    fn from(v: u128) -> Self {
1140        Self(v.to_ne_bytes())
1141    }
1142}
1143
1144impl From<u64> for AlignedU128 {
1145    fn from(v: u64) -> Self {
1146        (v as u128).into()
1147    }
1148}
1149
1150impl From<u32> for AlignedU128 {
1151    fn from(v: u32) -> Self {
1152        (v as u128).into()
1153    }
1154}
1155
1156impl From<u16> for AlignedU128 {
1157    fn from(v: u16) -> Self {
1158        (v as u128).into()
1159    }
1160}
1161
1162impl From<u8> for AlignedU128 {
1163    fn from(v: u8) -> Self {
1164        (v as u128).into()
1165    }
1166}
1167
1168impl From<AlignedU128> for u128 {
1169    fn from(v: AlignedU128) -> Self {
1170        u128::from_ne_bytes(v.0)
1171    }
1172}
1173
1174open_enum! {
1175    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1176    pub enum HvMessageType: u32 {
1177        #![expect(non_upper_case_globals)]
1178
1179        HvMessageTypeNone = 0x00000000,
1180
1181        HvMessageTypeUnmappedGpa = 0x80000000,
1182        HvMessageTypeGpaIntercept = 0x80000001,
1183        HvMessageTypeUnacceptedGpa = 0x80000003,
1184        HvMessageTypeGpaAttributeIntercept = 0x80000004,
1185        HvMessageTypeEnablePartitionVtlIntercept = 0x80000005,
1186        HvMessageTypeTimerExpired = 0x80000010,
1187        HvMessageTypeInvalidVpRegisterValue = 0x80000020,
1188        HvMessageTypeUnrecoverableException = 0x80000021,
1189        HvMessageTypeUnsupportedFeature = 0x80000022,
1190        HvMessageTypeTlbPageSizeMismatch = 0x80000023,
1191        HvMessageTypeIommuFault = 0x80000024,
1192        HvMessageTypeEventLogBufferComplete = 0x80000040,
1193        HvMessageTypeHypercallIntercept = 0x80000050,
1194        HvMessageTypeSynicEventIntercept = 0x80000060,
1195        HvMessageTypeSynicSintIntercept = 0x80000061,
1196        HvMessageTypeSynicSintDeliverable = 0x80000062,
1197        HvMessageTypeAsyncCallCompletion = 0x80000070,
1198        HvMessageTypeX64IoPortIntercept = 0x80010000,
1199        HvMessageTypeMsrIntercept = 0x80010001,
1200        HvMessageTypeX64CpuidIntercept = 0x80010002,
1201        HvMessageTypeExceptionIntercept = 0x80010003,
1202        HvMessageTypeX64ApicEoi = 0x80010004,
1203        HvMessageTypeX64IommuPrq = 0x80010005,
1204        HvMessageTypeRegisterIntercept = 0x80010006,
1205        HvMessageTypeX64Halt = 0x80010007,
1206        HvMessageTypeX64InterruptionDeliverable = 0x80010008,
1207        HvMessageTypeX64SipiIntercept = 0x80010009,
1208        HvMessageTypeX64RdtscIntercept = 0x8001000a,
1209        HvMessageTypeX64ApicSmiIntercept = 0x8001000b,
1210        HvMessageTypeArm64ResetIntercept = 0x8001000c,
1211        HvMessageTypeX64ApicInitSipiIntercept = 0x8001000d,
1212        HvMessageTypeX64ApicWriteIntercept = 0x8001000e,
1213        HvMessageTypeX64ProxyInterruptIntercept = 0x8001000f,
1214        HvMessageTypeX64IsolationCtrlRegIntercept = 0x80010010,
1215        HvMessageTypeX64SnpGuestRequestIntercept = 0x80010011,
1216        HvMessageTypeX64ExceptionTrapIntercept = 0x80010012,
1217        HvMessageTypeX64SevVmgexitIntercept = 0x80010013,
1218    }
1219}
1220
1221impl Default for HvMessageType {
1222    fn default() -> Self {
1223        HvMessageType::HvMessageTypeNone
1224    }
1225}
1226
1227pub const HV_SYNIC_INTERCEPTION_SINT_INDEX: u8 = 0;
1228
1229pub const NUM_SINTS: usize = 16;
1230pub const NUM_TIMERS: usize = 4;
1231
1232#[repr(C)]
1233#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1234pub struct HvMessageHeader {
1235    pub typ: HvMessageType,
1236    pub len: u8,
1237    pub flags: HvMessageFlags,
1238    pub rsvd: u16,
1239    pub id: u64,
1240}
1241
1242#[bitfield(u8)]
1243#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1244pub struct HvMessageFlags {
1245    pub message_pending: bool,
1246    #[bits(7)]
1247    _reserved: u8,
1248}
1249
1250pub const HV_MESSAGE_SIZE: usize = size_of::<HvMessage>();
1251const_assert!(HV_MESSAGE_SIZE == 256);
1252pub const HV_MESSAGE_PAYLOAD_SIZE: usize = 240;
1253
1254#[repr(C, align(16))]
1255#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1256pub struct HvMessage {
1257    pub header: HvMessageHeader,
1258    pub payload_buffer: [u8; HV_MESSAGE_PAYLOAD_SIZE],
1259}
1260
1261impl Default for HvMessage {
1262    fn default() -> Self {
1263        Self {
1264            header: FromZeros::new_zeroed(),
1265            payload_buffer: [0; 240],
1266        }
1267    }
1268}
1269
1270impl HvMessage {
1271    /// Constructs a new message. `payload` must fit into the payload field (240
1272    /// bytes limit).
1273    pub fn new(typ: HvMessageType, id: u64, payload: &[u8]) -> Self {
1274        let mut msg = HvMessage {
1275            header: HvMessageHeader {
1276                typ,
1277                len: payload.len() as u8,
1278                flags: HvMessageFlags::new(),
1279                rsvd: 0,
1280                id,
1281            },
1282            payload_buffer: [0; 240],
1283        };
1284        msg.payload_buffer[..payload.len()].copy_from_slice(payload);
1285        msg
1286    }
1287
1288    pub fn payload(&self) -> &[u8] {
1289        &self.payload_buffer[..self.header.len as usize]
1290    }
1291
1292    pub fn as_message<T: MessagePayload>(&self) -> &T {
1293        // Ensure invariants are met.
1294        let () = T::CHECK;
1295        T::ref_from_prefix(&self.payload_buffer).unwrap().0
1296    }
1297
1298    pub fn as_message_mut<T: MessagePayload>(&mut self) -> &T {
1299        // Ensure invariants are met.
1300        let () = T::CHECK;
1301        T::mut_from_prefix(&mut self.payload_buffer).unwrap().0
1302    }
1303}
1304
1305pub trait MessagePayload: KnownLayout + Immutable + IntoBytes + FromBytes + Sized {
1306    /// Used to ensure this trait is only implemented on messages of the proper
1307    /// size and alignment.
1308    #[doc(hidden)]
1309    const CHECK: () = {
1310        assert!(size_of::<Self>() <= HV_MESSAGE_PAYLOAD_SIZE);
1311        assert!(align_of::<Self>() <= align_of::<HvMessage>());
1312    };
1313}
1314
1315#[repr(C)]
1316#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1317pub struct TimerMessagePayload {
1318    pub timer_index: u32,
1319    pub reserved: u32,
1320    pub expiration_time: u64,
1321    pub delivery_time: u64,
1322}
1323
1324pub mod hypercall {
1325    use super::*;
1326    use core::ops::RangeInclusive;
1327    use zerocopy::Unalign;
1328
1329    /// The hypercall input value.
1330    #[bitfield(u64)]
1331    pub struct Control {
1332        /// The hypercall code.
1333        pub code: u16,
1334        /// If this hypercall is a fast hypercall.
1335        pub fast: bool,
1336        /// The variable header size, in qwords.
1337        #[bits(10)]
1338        pub variable_header_size: usize,
1339        #[bits(4)]
1340        _rsvd0: u8,
1341        /// Specifies that the hypercall should be handled by the L0 hypervisor in a nested environment.
1342        pub nested: bool,
1343        /// The element count for rep hypercalls.
1344        #[bits(12)]
1345        pub rep_count: usize,
1346        #[bits(4)]
1347        _rsvd1: u8,
1348        /// The first element to start processing in a rep hypercall.
1349        #[bits(12)]
1350        pub rep_start: usize,
1351        #[bits(4)]
1352        _rsvd2: u8,
1353    }
1354
1355    /// The hypercall output value returned to the guest.
1356    #[bitfield(u64)]
1357    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1358    #[must_use]
1359    pub struct HypercallOutput {
1360        #[bits(16)]
1361        pub call_status: HvStatus,
1362        pub rsvd: u16,
1363        #[bits(12)]
1364        pub elements_processed: usize,
1365        #[bits(20)]
1366        pub rsvd2: u32,
1367    }
1368
1369    impl From<HvError> for HypercallOutput {
1370        fn from(e: HvError) -> Self {
1371            Self::new().with_call_status(Err(e).into())
1372        }
1373    }
1374
1375    impl HypercallOutput {
1376        /// A success output with zero elements processed.
1377        pub const SUCCESS: Self = Self::new();
1378
1379        pub fn result(&self) -> Result<(), HvError> {
1380            self.call_status().result()
1381        }
1382    }
1383
1384    #[repr(C)]
1385    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1386    pub struct HvRegisterAssoc {
1387        pub name: HvRegisterName,
1388        pub pad: [u32; 3],
1389        pub value: HvRegisterValue,
1390    }
1391
1392    impl<N: Into<HvRegisterName>, T: Into<HvRegisterValue>> From<(N, T)> for HvRegisterAssoc {
1393        fn from((name, value): (N, T)) -> Self {
1394            Self {
1395                name: name.into(),
1396                pad: [0; 3],
1397                value: value.into(),
1398            }
1399        }
1400    }
1401
1402    impl<N: Copy + Into<HvRegisterName>, T: Copy + Into<HvRegisterValue>> From<&(N, T)>
1403        for HvRegisterAssoc
1404    {
1405        fn from(&(name, value): &(N, T)) -> Self {
1406            Self {
1407                name: name.into(),
1408                pad: [0; 3],
1409                value: value.into(),
1410            }
1411        }
1412    }
1413
1414    #[bitfield(u64)]
1415    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1416    pub struct MsrHypercallContents {
1417        pub enable: bool,
1418        pub locked: bool,
1419        #[bits(10)]
1420        pub reserved_p: u64,
1421        #[bits(52)]
1422        pub gpn: u64,
1423    }
1424
1425    #[repr(C, align(8))]
1426    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1427    pub struct PostMessage {
1428        pub connection_id: u32,
1429        pub padding: u32,
1430        pub message_type: u32,
1431        pub payload_size: u32,
1432        pub payload: [u8; 240],
1433    }
1434
1435    #[repr(C, align(8))]
1436    #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1437    pub struct SignalEvent {
1438        pub connection_id: u32,
1439        pub flag_number: u16,
1440        pub rsvd: u16,
1441    }
1442
1443    #[repr(C)]
1444    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1445    pub struct PostMessageDirect {
1446        pub partition_id: u64,
1447        pub vp_index: u32,
1448        pub vtl: u8,
1449        pub padding0: [u8; 3],
1450        pub sint: u8,
1451        pub padding1: [u8; 3],
1452        pub message: Unalign<HvMessage>,
1453        pub padding2: u32,
1454    }
1455
1456    #[repr(C)]
1457    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1458    pub struct SignalEventDirect {
1459        pub target_partition: u64,
1460        pub target_vp: u32,
1461        pub target_vtl: u8,
1462        pub target_sint: u8,
1463        pub flag_number: u16,
1464    }
1465
1466    #[repr(C)]
1467    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1468    pub struct SignalEventDirectOutput {
1469        pub newly_signaled: u8,
1470        pub rsvd: [u8; 7],
1471    }
1472
1473    #[repr(C)]
1474    #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1475    pub struct InterruptEntry {
1476        pub source: HvInterruptSource,
1477        pub rsvd: u32,
1478        pub data: [u32; 2],
1479    }
1480
1481    open_enum! {
1482        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1483        pub enum HvInterruptSource: u32 {
1484            MSI = 1,
1485            IO_APIC = 2,
1486        }
1487    }
1488
1489    #[repr(C)]
1490    #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1491    pub struct InterruptTarget {
1492        pub vector: u32,
1493        pub flags: HvInterruptTargetFlags,
1494        pub mask_or_format: u64,
1495    }
1496
1497    #[bitfield(u32)]
1498    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1499    pub struct HvInterruptTargetFlags {
1500        pub multicast: bool,
1501        pub processor_set: bool,
1502        pub proxy_redirect: bool,
1503        #[bits(29)]
1504        pub reserved: u32,
1505    }
1506
1507    pub const HV_DEVICE_INTERRUPT_TARGET_MULTICAST: u32 = 1;
1508    pub const HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET: u32 = 2;
1509    pub const HV_DEVICE_INTERRUPT_TARGET_PROXY_REDIRECT: u32 = 4;
1510
1511    pub const HV_GENERIC_SET_SPARSE_4K: u64 = 0;
1512    pub const HV_GENERIC_SET_ALL: u64 = 1;
1513
1514    #[repr(C)]
1515    #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1516    pub struct RetargetDeviceInterrupt {
1517        pub partition_id: u64,
1518        pub device_id: u64,
1519        pub entry: InterruptEntry,
1520        pub rsvd: u64,
1521        pub target_header: InterruptTarget,
1522    }
1523
1524    #[bitfield(u8)]
1525    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1526    pub struct HvInputVtl {
1527        #[bits(4)]
1528        pub target_vtl_value: u8,
1529        pub use_target_vtl: bool,
1530        #[bits(3)]
1531        pub reserved: u8,
1532    }
1533
1534    impl From<Vtl> for HvInputVtl {
1535        fn from(value: Vtl) -> Self {
1536            Self::from(Some(value))
1537        }
1538    }
1539
1540    impl From<Option<Vtl>> for HvInputVtl {
1541        fn from(value: Option<Vtl>) -> Self {
1542            Self::new()
1543                .with_use_target_vtl(value.is_some())
1544                .with_target_vtl_value(value.map_or(0, Into::into))
1545        }
1546    }
1547
1548    impl HvInputVtl {
1549        /// None = target current vtl
1550        pub fn target_vtl(&self) -> Result<Option<Vtl>, HvError> {
1551            if self.reserved() != 0 {
1552                return Err(HvError::InvalidParameter);
1553            }
1554            if self.use_target_vtl() {
1555                Ok(Some(self.target_vtl_value().try_into()?))
1556            } else {
1557                Ok(None)
1558            }
1559        }
1560
1561        pub const CURRENT_VTL: Self = Self::new();
1562    }
1563
1564    #[repr(C)]
1565    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1566    pub struct GetSetVpRegisters {
1567        pub partition_id: u64,
1568        pub vp_index: u32,
1569        pub target_vtl: HvInputVtl,
1570        pub rsvd: [u8; 3],
1571    }
1572
1573    open_enum::open_enum! {
1574        #[derive(Default)]
1575        pub enum HvGuestOsMicrosoftIds: u8 {
1576            UNDEFINED = 0x00,
1577            MSDOS = 0x01,
1578            WINDOWS_3X = 0x02,
1579            WINDOWS_9X = 0x03,
1580            WINDOWS_NT = 0x04,
1581            WINDOWS_CE = 0x05,
1582        }
1583    }
1584
1585    #[bitfield(u64)]
1586    pub struct HvGuestOsMicrosoft {
1587        #[bits(40)]
1588        _rsvd: u64,
1589        #[bits(8)]
1590        pub os_id: u8,
1591        // The top bit must be zero and the least significant 15 bits holds the value of the vendor id.
1592        #[bits(16)]
1593        pub vendor_id: u16,
1594    }
1595
1596    open_enum::open_enum! {
1597        #[derive(Default)]
1598        pub enum HvGuestOsOpenSourceType: u8 {
1599            UNDEFINED = 0x00,
1600            LINUX = 0x01,
1601            FREEBSD = 0x02,
1602            XEN = 0x03,
1603            ILLUMOS = 0x04,
1604        }
1605    }
1606
1607    #[bitfield(u64)]
1608    pub struct HvGuestOsOpenSource {
1609        #[bits(16)]
1610        pub build_no: u16,
1611        #[bits(32)]
1612        pub version: u32,
1613        #[bits(8)]
1614        pub os_id: u8,
1615        #[bits(7)]
1616        pub os_type: u8,
1617        #[bits(1)]
1618        pub is_open_source: bool,
1619    }
1620
1621    #[bitfield(u64)]
1622    pub struct HvGuestOsId {
1623        #[bits(63)]
1624        _rsvd: u64,
1625        is_open_source: bool,
1626    }
1627
1628    impl HvGuestOsId {
1629        pub fn microsoft(&self) -> Option<HvGuestOsMicrosoft> {
1630            (!self.is_open_source()).then(|| HvGuestOsMicrosoft::from(u64::from(*self)))
1631        }
1632
1633        pub fn open_source(&self) -> Option<HvGuestOsOpenSource> {
1634            (self.is_open_source()).then(|| HvGuestOsOpenSource::from(u64::from(*self)))
1635        }
1636
1637        pub fn as_u64(&self) -> u64 {
1638            self.0
1639        }
1640    }
1641
1642    pub const HV_INTERCEPT_ACCESS_MASK_NONE: u32 = 0x00;
1643    pub const HV_INTERCEPT_ACCESS_MASK_READ: u32 = 0x01;
1644    pub const HV_INTERCEPT_ACCESS_MASK_WRITE: u32 = 0x02;
1645    pub const HV_INTERCEPT_ACCESS_MASK_READ_WRITE: u32 =
1646        HV_INTERCEPT_ACCESS_MASK_READ | HV_INTERCEPT_ACCESS_MASK_WRITE;
1647    pub const HV_INTERCEPT_ACCESS_MASK_EXECUTE: u32 = 0x04;
1648
1649    open_enum::open_enum! {
1650        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1651        pub enum HvInterceptType: u32 {
1652            #![expect(non_upper_case_globals)]
1653            HvInterceptTypeX64IoPort = 0x00000000,
1654            HvInterceptTypeX64Msr = 0x00000001,
1655            HvInterceptTypeX64Cpuid = 0x00000002,
1656            HvInterceptTypeException = 0x00000003,
1657            HvInterceptTypeHypercall = 0x00000008,
1658            HvInterceptTypeUnknownSynicConnection = 0x0000000D,
1659            HvInterceptTypeX64ApicEoi = 0x0000000E,
1660            HvInterceptTypeRetargetInterruptWithUnknownDeviceId = 0x0000000F,
1661            HvInterceptTypeX64IoPortRange = 0x00000011,
1662        }
1663    }
1664
1665    #[repr(transparent)]
1666    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
1667    pub struct HvInterceptParameters(u64);
1668
1669    impl HvInterceptParameters {
1670        pub fn new_io_port(port: u16) -> Self {
1671            Self(port as u64)
1672        }
1673
1674        pub fn new_io_port_range(ports: RangeInclusive<u16>) -> Self {
1675            let base = *ports.start() as u64;
1676            let end = *ports.end() as u64;
1677            Self(base | (end << 16))
1678        }
1679
1680        pub fn new_exception(vector: u16) -> Self {
1681            Self(vector as u64)
1682        }
1683
1684        pub fn io_port(&self) -> u16 {
1685            self.0 as u16
1686        }
1687
1688        pub fn io_port_range(&self) -> RangeInclusive<u16> {
1689            let base = self.0 as u16;
1690            let end = (self.0 >> 16) as u16;
1691            base..=end
1692        }
1693
1694        pub fn cpuid_index(&self) -> u32 {
1695            self.0 as u32
1696        }
1697
1698        pub fn exception(&self) -> u16 {
1699            self.0 as u16
1700        }
1701    }
1702
1703    #[repr(C)]
1704    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
1705    pub struct InstallIntercept {
1706        pub partition_id: u64,
1707        pub access_type_mask: u32,
1708        pub intercept_type: HvInterceptType,
1709        pub intercept_parameters: HvInterceptParameters,
1710    }
1711
1712    /// Input for [`HypercallCode::HvCallRegisterInterceptResult`] with CPUID intercept type.
1713    #[repr(C)]
1714    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
1715    pub struct RegisterInterceptResultCpuid {
1716        pub partition_id: u64,
1717        pub vp_index: u32,
1718        pub intercept_type: HvInterceptType,
1719        pub parameters: HvRegisterX64CpuidResultParameters,
1720        /// Explicit tail padding (struct alignment is 8 due to partition_id).
1721        pub _reserved: u32,
1722    }
1723
1724    /// CPUID intercept result parameters.
1725    #[repr(C)]
1726    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
1727    pub struct HvRegisterX64CpuidResultParameters {
1728        pub input: HvRegisterX64CpuidResultParametersInput,
1729        pub result: HvRegisterX64CpuidResultParametersOutput,
1730    }
1731
1732    /// Input portion of CPUID intercept result parameters.
1733    #[repr(C)]
1734    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
1735    pub struct HvRegisterX64CpuidResultParametersInput {
1736        pub eax: u32,
1737        pub ecx: u32,
1738        pub subleaf_specific: u8,
1739        pub always_override: u8,
1740        pub padding: u16,
1741    }
1742
1743    /// Output portion of CPUID intercept result parameters.
1744    #[repr(C)]
1745    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
1746    pub struct HvRegisterX64CpuidResultParametersOutput {
1747        pub eax: u32,
1748        pub eax_mask: u32,
1749        pub ebx: u32,
1750        pub ebx_mask: u32,
1751        pub ecx: u32,
1752        pub ecx_mask: u32,
1753        pub edx: u32,
1754        pub edx_mask: u32,
1755    }
1756
1757    #[repr(C)]
1758    #[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, Debug)]
1759    pub struct AssertVirtualInterrupt {
1760        pub partition_id: u64,
1761        pub interrupt_control: HvInterruptControl,
1762        pub destination_address: u64,
1763        pub requested_vector: u32,
1764        pub target_vtl: u8,
1765        pub rsvd0: u8,
1766        pub rsvd1: u16,
1767    }
1768
1769    #[repr(C)]
1770    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1771    pub struct StartVirtualProcessorX64 {
1772        pub partition_id: u64,
1773        pub vp_index: u32,
1774        pub target_vtl: u8,
1775        pub rsvd0: u8,
1776        pub rsvd1: u16,
1777        pub vp_context: InitialVpContextX64,
1778    }
1779
1780    #[repr(C)]
1781    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1782    pub struct InitialVpContextX64 {
1783        pub rip: u64,
1784        pub rsp: u64,
1785        pub rflags: u64,
1786        pub cs: HvX64SegmentRegister,
1787        pub ds: HvX64SegmentRegister,
1788        pub es: HvX64SegmentRegister,
1789        pub fs: HvX64SegmentRegister,
1790        pub gs: HvX64SegmentRegister,
1791        pub ss: HvX64SegmentRegister,
1792        pub tr: HvX64SegmentRegister,
1793        pub ldtr: HvX64SegmentRegister,
1794        pub idtr: HvX64TableRegister,
1795        pub gdtr: HvX64TableRegister,
1796        pub efer: u64,
1797        pub cr0: u64,
1798        pub cr3: u64,
1799        pub cr4: u64,
1800        pub msr_cr_pat: u64,
1801    }
1802
1803    #[repr(C)]
1804    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1805    pub struct StartVirtualProcessorArm64 {
1806        pub partition_id: u64,
1807        pub vp_index: u32,
1808        pub target_vtl: u8,
1809        pub rsvd0: u8,
1810        pub rsvd1: u16,
1811        pub vp_context: InitialVpContextArm64,
1812    }
1813
1814    #[repr(C)]
1815    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1816    pub struct InitialVpContextArm64 {
1817        pub pc: u64,
1818        pub sp_elh: u64,
1819        pub sctlr_el1: u64,
1820        pub mair_el1: u64,
1821        pub tcr_el1: u64,
1822        pub vbar_el1: u64,
1823        pub ttbr0_el1: u64,
1824        pub ttbr1_el1: u64,
1825        pub x18: u64,
1826    }
1827
1828    impl InitialVpContextX64 {
1829        pub fn as_hv_register_assocs(&self) -> impl Iterator<Item = HvRegisterAssoc> + '_ {
1830            let regs = [
1831                (HvX64RegisterName::Rip, HvRegisterValue::from(self.rip)).into(),
1832                (HvX64RegisterName::Rsp, HvRegisterValue::from(self.rsp)).into(),
1833                (
1834                    HvX64RegisterName::Rflags,
1835                    HvRegisterValue::from(self.rflags),
1836                )
1837                    .into(),
1838                (HvX64RegisterName::Cs, HvRegisterValue::from(self.cs)).into(),
1839                (HvX64RegisterName::Ds, HvRegisterValue::from(self.ds)).into(),
1840                (HvX64RegisterName::Es, HvRegisterValue::from(self.es)).into(),
1841                (HvX64RegisterName::Fs, HvRegisterValue::from(self.fs)).into(),
1842                (HvX64RegisterName::Gs, HvRegisterValue::from(self.gs)).into(),
1843                (HvX64RegisterName::Ss, HvRegisterValue::from(self.ss)).into(),
1844                (HvX64RegisterName::Tr, HvRegisterValue::from(self.tr)).into(),
1845                (HvX64RegisterName::Ldtr, HvRegisterValue::from(self.ldtr)).into(),
1846                (HvX64RegisterName::Idtr, HvRegisterValue::from(self.idtr)).into(),
1847                (HvX64RegisterName::Gdtr, HvRegisterValue::from(self.gdtr)).into(),
1848                (HvX64RegisterName::Efer, HvRegisterValue::from(self.efer)).into(),
1849                (HvX64RegisterName::Cr0, HvRegisterValue::from(self.cr0)).into(),
1850                (HvX64RegisterName::Cr3, HvRegisterValue::from(self.cr3)).into(),
1851                (HvX64RegisterName::Cr4, HvRegisterValue::from(self.cr4)).into(),
1852                (
1853                    HvX64RegisterName::Pat,
1854                    HvRegisterValue::from(self.msr_cr_pat),
1855                )
1856                    .into(),
1857            ];
1858            regs.into_iter()
1859        }
1860    }
1861
1862    #[bitfield(u64)]
1863    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1864    pub struct TranslateGvaControlFlagsX64 {
1865        /// Request data read access
1866        pub validate_read: bool,
1867        /// Request data write access
1868        pub validate_write: bool,
1869        /// Request instruction fetch access.
1870        pub validate_execute: bool,
1871        /// Don't enforce any checks related to access mode (supervisor vs. user; SMEP and SMAP are treated
1872        /// as disabled).
1873        pub privilege_exempt: bool,
1874        /// Set the appropriate page table bits (i.e. access/dirty bit)
1875        pub set_page_table_bits: bool,
1876        /// Lock the TLB
1877        pub tlb_flush_inhibit: bool,
1878        /// Treat the access as a supervisor mode access irrespective of current mode.
1879        pub supervisor_access: bool,
1880        /// Treat the access as a user mode access irrespective of current mode.
1881        pub user_access: bool,
1882        /// Enforce the SMAP restriction on supervisor data access to user mode addresses if CR4.SMAP=1
1883        /// irrespective of current EFLAGS.AC i.e. the behavior for "implicit supervisor-mode accesses"
1884        /// (e.g. to the GDT, etc.) and when EFLAGS.AC=0. Does nothing if CR4.SMAP=0.
1885        pub enforce_smap: bool,
1886        /// Don't enforce the SMAP restriction on supervisor data access to user mode addresses irrespective
1887        /// of current EFLAGS.AC i.e. the behavior when EFLAGS.AC=1.
1888        pub override_smap: bool,
1889        /// Treat the access as a shadow stack access.
1890        pub shadow_stack: bool,
1891        #[bits(45)]
1892        _unused: u64,
1893        /// Target vtl
1894        input_vtl_value: u8,
1895    }
1896
1897    impl TranslateGvaControlFlagsX64 {
1898        pub fn input_vtl(&self) -> HvInputVtl {
1899            self.input_vtl_value().into()
1900        }
1901
1902        pub fn with_input_vtl(self, input_vtl: HvInputVtl) -> Self {
1903            self.with_input_vtl_value(input_vtl.into())
1904        }
1905
1906        pub fn set_input_vtl(&mut self, input_vtl: HvInputVtl) {
1907            self.set_input_vtl_value(input_vtl.into())
1908        }
1909    }
1910
1911    #[bitfield(u64)]
1912    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1913    pub struct TranslateGvaControlFlagsArm64 {
1914        /// Request data read access
1915        pub validate_read: bool,
1916        /// Request data write access
1917        pub validate_write: bool,
1918        /// Request instruction fetch access.
1919        pub validate_execute: bool,
1920        _reserved0: bool,
1921        /// Set the appropriate page table bits (i.e. access/dirty bit)
1922        pub set_page_table_bits: bool,
1923        /// Lock the TLB
1924        pub tlb_flush_inhibit: bool,
1925        /// Treat the access as a supervisor mode access irrespective of current mode.
1926        pub supervisor_access: bool,
1927        /// Treat the access as a user mode access irrespective of current mode.
1928        pub user_access: bool,
1929        /// Restrict supervisor data access to user mode addresses irrespective of current PSTATE.PAN i.e.
1930        /// the behavior when PSTATE.PAN=1.
1931        pub pan_set: bool,
1932        /// Don't restrict supervisor data access to user mode addresses irrespective of current PSTATE.PAN
1933        /// i.e. the behavior when PSTATE.PAN=0.
1934        pub pan_clear: bool,
1935        #[bits(46)]
1936        _unused: u64,
1937        /// Target vtl
1938        #[bits(8)]
1939        input_vtl_value: u8,
1940    }
1941
1942    impl TranslateGvaControlFlagsArm64 {
1943        pub fn input_vtl(&self) -> HvInputVtl {
1944            self.input_vtl_value().into()
1945        }
1946
1947        pub fn with_input_vtl(self, input_vtl: HvInputVtl) -> Self {
1948            self.with_input_vtl_value(input_vtl.into())
1949        }
1950
1951        pub fn set_input_vtl(&mut self, input_vtl: HvInputVtl) {
1952            self.set_input_vtl_value(input_vtl.into())
1953        }
1954    }
1955
1956    #[repr(C)]
1957    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1958    pub struct TranslateVirtualAddressX64 {
1959        pub partition_id: u64,
1960        pub vp_index: u32,
1961        // NOTE: This reserved field is not in the OS headers, but is required due to alignment. Confirmed via debugger.
1962        pub reserved: u32,
1963        pub control_flags: TranslateGvaControlFlagsX64,
1964        pub gva_page: u64,
1965    }
1966
1967    #[repr(C)]
1968    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1969    pub struct TranslateVirtualAddressArm64 {
1970        pub partition_id: u64,
1971        pub vp_index: u32,
1972        // NOTE: This reserved field is not in the OS headers, but is required due to alignment. Confirmed via debugger.
1973        pub reserved: u32,
1974        pub control_flags: TranslateGvaControlFlagsArm64,
1975        pub gva_page: u64,
1976    }
1977
1978    open_enum::open_enum! {
1979        pub enum TranslateGvaResultCode: u32 {
1980            SUCCESS = 0,
1981
1982            // Translation Failures
1983            PAGE_NOT_PRESENT = 1,
1984            PRIVILEGE_VIOLATION = 2,
1985            INVALID_PAGE_TABLE_FLAGS = 3,
1986
1987            // GPA access failures
1988            GPA_UNMAPPED = 4,
1989            GPA_NO_READ_ACCESS = 5,
1990            GPA_NO_WRITE_ACCESS = 6,
1991            GPA_ILLEGAL_OVERLAY_ACCESS = 7,
1992
1993            /// Intercept of the memory access by either
1994            /// - a higher VTL
1995            /// - a nested hypervisor (due to a violation of the nested page table)
1996            INTERCEPT = 8,
1997
1998            GPA_UNACCEPTED = 9,
1999        }
2000    }
2001
2002    #[bitfield(u64)]
2003    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2004    pub struct TranslateGvaResult {
2005        pub result_code: u32,
2006        pub cache_type: u8,
2007        pub overlay_page: bool,
2008        #[bits(23)]
2009        pub reserved: u32,
2010    }
2011
2012    #[repr(C)]
2013    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2014    pub struct TranslateVirtualAddressOutput {
2015        pub translation_result: TranslateGvaResult,
2016        pub gpa_page: u64,
2017    }
2018
2019    #[repr(C)]
2020    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2021    pub struct TranslateGvaResultExX64 {
2022        pub result: TranslateGvaResult,
2023        pub reserved: u64,
2024        pub event_info: HvX64PendingEvent,
2025    }
2026
2027    const_assert!(size_of::<TranslateGvaResultExX64>() == 0x30);
2028
2029    #[repr(C)]
2030    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2031    pub struct TranslateGvaResultExArm64 {
2032        pub result: TranslateGvaResult,
2033    }
2034
2035    const_assert!(size_of::<TranslateGvaResultExArm64>() == 0x8);
2036
2037    #[repr(C)]
2038    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2039    pub struct TranslateVirtualAddressExOutputX64 {
2040        pub translation_result: TranslateGvaResultExX64,
2041        pub gpa_page: u64,
2042        // NOTE: This reserved field is not in the OS headers, but is required due to alignment. Confirmed via debugger.
2043        pub reserved: u64,
2044    }
2045
2046    const_assert!(size_of::<TranslateVirtualAddressExOutputX64>() == 0x40);
2047
2048    #[repr(C)]
2049    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2050    pub struct TranslateVirtualAddressExOutputArm64 {
2051        pub translation_result: TranslateGvaResultExArm64,
2052        pub gpa_page: u64,
2053    }
2054
2055    const_assert!(size_of::<TranslateVirtualAddressExOutputArm64>() == 0x10);
2056
2057    #[repr(C)]
2058    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2059    pub struct GetVpIndexFromApicId {
2060        pub partition_id: u64,
2061        pub target_vtl: u8,
2062        pub reserved: [u8; 7],
2063    }
2064
2065    #[repr(C)]
2066    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2067    pub struct EnableVpVtlX64 {
2068        pub partition_id: u64,
2069        pub vp_index: u32,
2070        pub target_vtl: u8,
2071        pub reserved: [u8; 3],
2072        pub vp_vtl_context: InitialVpContextX64,
2073    }
2074
2075    #[repr(C)]
2076    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2077    pub struct EnableVpVtlArm64 {
2078        pub partition_id: u64,
2079        pub vp_index: u32,
2080        pub target_vtl: u8,
2081        pub reserved: [u8; 3],
2082        pub vp_vtl_context: InitialVpContextArm64,
2083    }
2084
2085    #[repr(C)]
2086    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2087    pub struct ModifyVtlProtectionMask {
2088        pub partition_id: u64,
2089        pub map_flags: HvMapGpaFlags,
2090        pub target_vtl: HvInputVtl,
2091        pub reserved: [u8; 3],
2092    }
2093
2094    #[repr(C)]
2095    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2096    pub struct CheckSparseGpaPageVtlAccess {
2097        pub partition_id: u64,
2098        pub target_vtl: HvInputVtl,
2099        pub desired_access: u8,
2100        pub reserved0: u16,
2101        pub reserved1: u32,
2102    }
2103    const_assert!(size_of::<CheckSparseGpaPageVtlAccess>() == 0x10);
2104
2105    #[bitfield(u64)]
2106    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2107    pub struct CheckSparseGpaPageVtlAccessOutput {
2108        pub result_code: u8,
2109        pub denied_access: u8,
2110        #[bits(4)]
2111        pub intercepting_vtl: u32,
2112        #[bits(12)]
2113        _reserved0: u32,
2114        _reserved1: u32,
2115    }
2116    const_assert!(size_of::<CheckSparseGpaPageVtlAccessOutput>() == 0x8);
2117
2118    open_enum::open_enum! {
2119        pub enum CheckGpaPageVtlAccessResultCode: u32 {
2120            SUCCESS = 0,
2121            MEMORY_INTERCEPT = 1,
2122        }
2123    }
2124
2125    /// The number of VTLs for which permissions can be specified in a VTL permission set.
2126    pub const HV_VTL_PERMISSION_SET_SIZE: usize = 2;
2127
2128    #[repr(C)]
2129    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2130    pub struct VtlPermissionSet {
2131        /// VTL permissions for the GPA page, starting from VTL 1.
2132        pub vtl_permission_from_1: [u16; HV_VTL_PERMISSION_SET_SIZE],
2133    }
2134
2135    open_enum::open_enum! {
2136        pub enum AcceptMemoryType: u32 {
2137            ANY = 0,
2138            RAM = 1,
2139        }
2140    }
2141
2142    open_enum! {
2143        /// Host visibility used in hypercall inputs.
2144        ///
2145        /// NOTE: While this is a 2 bit set with the lower bit representing host
2146        /// read access and upper bit representing host write access, hardware
2147        /// platforms do not support that form of isolation. Only support
2148        /// private or full shared in this definition.
2149        #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2150        pub enum HostVisibilityType: u8 {
2151            PRIVATE = 0,
2152            SHARED = 3,
2153        }
2154    }
2155
2156    // Used by bitfield-struct implicitly.
2157    impl HostVisibilityType {
2158        const fn from_bits(value: u8) -> Self {
2159            Self(value)
2160        }
2161
2162        const fn into_bits(value: Self) -> u8 {
2163            value.0
2164        }
2165    }
2166
2167    /// Attributes for accepting pages. See [`AcceptGpaPages`]
2168    #[bitfield(u32)]
2169    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2170    pub struct AcceptPagesAttributes {
2171        #[bits(6)]
2172        /// Supplies the expected memory type [`AcceptMemoryType`].
2173        pub memory_type: u32,
2174        #[bits(2)]
2175        /// Supplies the initial host visibility (exclusive, shared read-only, shared read-write).
2176        pub host_visibility: HostVisibilityType,
2177        #[bits(3)]
2178        /// Supplies the set of VTLs for which initial VTL permissions will be set.
2179        pub vtl_set: u32,
2180        #[bits(21)]
2181        _reserved: u32,
2182    }
2183
2184    #[repr(C)]
2185    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2186    pub struct AcceptGpaPages {
2187        /// Supplies the partition ID of the partition this request is for.
2188        pub partition_id: u64,
2189        /// Supplies attributes of the pages being accepted, such as whether
2190        /// they should be made host visible.
2191        pub page_attributes: AcceptPagesAttributes,
2192        /// Supplies the set of initial VTL permissions.
2193        pub vtl_permission_set: VtlPermissionSet,
2194        /// Supplies the GPA page number of the first page to modify.
2195        pub gpa_page_base: u64,
2196    }
2197    const_assert!(size_of::<AcceptGpaPages>() == 0x18);
2198
2199    /// Attributes for unaccepting pages. See [`UnacceptGpaPages`]
2200    #[bitfield(u32)]
2201    pub struct UnacceptPagesAttributes {
2202        #[bits(3)]
2203        pub vtl_set: u32,
2204        #[bits(29)]
2205        _reserved: u32,
2206    }
2207
2208    #[repr(C)]
2209    pub struct UnacceptGpaPages {
2210        /// Supplies the partition ID of the partition this request is for.
2211        pub partition_id: u64,
2212        /// Supplies the set of VTLs for which VTL permissions will be checked.
2213        pub page_attributes: UnacceptPagesAttributes,
2214        ///  Supplies the set of VTL permissions to check against.
2215        pub vtl_permission_set: VtlPermissionSet,
2216        /// Supplies the GPA page number of the first page to modify.
2217        pub gpa_page_base: u64,
2218    }
2219    const_assert!(size_of::<UnacceptGpaPages>() == 0x18);
2220
2221    #[bitfield(u32)]
2222    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2223    pub struct ModifyHostVisibility {
2224        #[bits(2)]
2225        pub host_visibility: HostVisibilityType,
2226        #[bits(30)]
2227        _reserved: u32,
2228    }
2229
2230    #[repr(C)]
2231    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2232    pub struct ModifySparsePageVisibility {
2233        pub partition_id: u64,
2234        pub host_visibility: ModifyHostVisibility,
2235        pub reserved: u32,
2236    }
2237
2238    /// Layout of the `ModifySparsePageVisibility` hypercall on internal Hyper-V
2239    /// builds. To be removed, used for SEV-TIO bringup.
2240    #[bitfield(u32)]
2241    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2242    pub struct ModifyHostVisibilityWithImmutability {
2243        #[bits(2)]
2244        pub host_visibility: HostVisibilityType,
2245        pub immutability: bool,
2246        #[bits(29)]
2247        _reserved: u32,
2248    }
2249
2250    /// Layout for the `ModifySparsePageVisibility` hypercall on internal
2251    /// Hyper-V builds. To be removed, used for SEV-TIO bringup.
2252    #[repr(C)]
2253    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2254    pub struct ModifySparsePageVisibilityWithImmutability {
2255        pub partition_id: u64,
2256        pub host_visibility: ModifyHostVisibilityWithImmutability,
2257        pub reserved: u32,
2258    }
2259
2260    #[repr(C)]
2261    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2262    pub struct QuerySparsePageVisibility {
2263        pub partition_id: u64,
2264    }
2265
2266    pub const VBS_VM_REPORT_DATA_SIZE: usize = 64;
2267    pub const VBS_VM_MAX_REPORT_SIZE: usize = 2048;
2268
2269    #[repr(C)]
2270    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2271    pub struct VbsVmCallReport {
2272        pub report_data: [u8; VBS_VM_REPORT_DATA_SIZE],
2273    }
2274
2275    #[repr(C)]
2276    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2277    pub struct VbsVmCallReportOutput {
2278        pub report: [u8; VBS_VM_MAX_REPORT_SIZE],
2279    }
2280
2281    #[bitfield(u8)]
2282    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2283    pub struct EnablePartitionVtlFlags {
2284        pub enable_mbec: bool,
2285        pub enable_supervisor_shadow_stack: bool,
2286        pub enable_hardware_hvpt: bool,
2287        #[bits(5)]
2288        pub reserved: u8,
2289    }
2290
2291    #[repr(C)]
2292    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2293    pub struct EnablePartitionVtl {
2294        pub partition_id: u64,
2295        pub target_vtl: u8,
2296        pub flags: EnablePartitionVtlFlags,
2297        pub reserved_z0: u16,
2298        pub reserved_z1: u32,
2299    }
2300
2301    #[repr(C)]
2302    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2303    pub struct FlushVirtualAddressSpace {
2304        pub address_space: u64,
2305        pub flags: HvFlushFlags,
2306        pub processor_mask: u64,
2307    }
2308
2309    #[repr(C)]
2310    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2311    pub struct FlushVirtualAddressSpaceEx {
2312        pub address_space: u64,
2313        pub flags: HvFlushFlags,
2314        pub vp_set_format: u64,
2315        pub vp_set_valid_banks_mask: u64,
2316        // Followed by the variable-sized part of an HvVpSet
2317    }
2318
2319    #[repr(C)]
2320    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2321    pub struct PinUnpinGpaPageRangesHeader {
2322        pub reserved: u64,
2323    }
2324
2325    #[repr(C)]
2326    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2327    pub struct SendSyntheticClusterIpi {
2328        pub vector: u32,
2329        pub target_vtl: HvInputVtl,
2330        pub flags: u8,
2331        pub reserved: u16,
2332        pub processor_mask: u64,
2333    }
2334
2335    #[repr(C)]
2336    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2337    pub struct SendSyntheticClusterIpiEx {
2338        pub vector: u32,
2339        pub target_vtl: HvInputVtl,
2340        pub flags: u8,
2341        pub reserved: u16,
2342        pub vp_set_format: u64,
2343        pub vp_set_valid_banks_mask: u64,
2344        // Followed by the variable-sized part of an HvVpSet
2345    }
2346
2347    #[bitfield(u64)]
2348    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2349    pub struct HvFlushFlags {
2350        pub all_processors: bool,
2351        pub all_virtual_address_spaces: bool,
2352        pub non_global_mappings_only: bool,
2353        pub use_extended_range_format: bool,
2354        pub use_target_vtl: bool,
2355
2356        #[bits(3)]
2357        _reserved: u8,
2358
2359        pub target_vtl0: bool,
2360        pub target_vtl1: bool,
2361
2362        #[bits(54)]
2363        _reserved2: u64,
2364    }
2365
2366    #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2367    #[repr(transparent)]
2368    pub struct HvGvaRange(pub u64);
2369
2370    impl From<u64> for HvGvaRange {
2371        fn from(value: u64) -> Self {
2372            Self(value)
2373        }
2374    }
2375
2376    impl From<HvGvaRange> for u64 {
2377        fn from(value: HvGvaRange) -> Self {
2378            value.0
2379        }
2380    }
2381
2382    impl HvGvaRange {
2383        pub fn as_simple(self) -> HvGvaRangeSimple {
2384            HvGvaRangeSimple(self.0)
2385        }
2386
2387        pub fn as_extended(self) -> HvGvaRangeExtended {
2388            HvGvaRangeExtended(self.0)
2389        }
2390
2391        pub fn as_extended_large_page(self) -> HvGvaRangeExtendedLargePage {
2392            HvGvaRangeExtendedLargePage(self.0)
2393        }
2394    }
2395
2396    #[bitfield(u64)]
2397    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2398    pub struct HvGvaRangeSimple {
2399        /// The number of pages beyond one.
2400        #[bits(12)]
2401        pub additional_pages: u64,
2402        /// The top 52 most significant bits of the guest virtual address.
2403        #[bits(52)]
2404        pub gva_page_number: u64,
2405    }
2406
2407    #[bitfield(u64)]
2408    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2409    pub struct HvGvaRangeExtended {
2410        /// The number of pages beyond one.
2411        #[bits(11)]
2412        pub additional_pages: u64,
2413        /// Is page size greater than 4 KB.
2414        pub large_page: bool,
2415        /// The top 52 most significant bits of the guest virtual address when `large_page`` is clear.
2416        #[bits(52)]
2417        pub gva_page_number: u64,
2418    }
2419
2420    #[bitfield(u64)]
2421    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2422    pub struct HvGvaRangeExtendedLargePage {
2423        /// The number of pages beyond one.
2424        #[bits(11)]
2425        pub additional_pages: u64,
2426        /// Is page size greater than 4 KB.
2427        pub large_page: bool,
2428        /// The page size when `large_page`` is set.
2429        /// false: 2 MB
2430        /// true: 1 GB
2431        pub page_size: bool,
2432        #[bits(8)]
2433        _reserved: u64,
2434        /// The top 43 most significant bits of the guest virtual address when `large_page`` is set.
2435        #[bits(43)]
2436        pub gva_large_page_number: u64,
2437    }
2438
2439    #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2440    #[repr(transparent)]
2441    pub struct HvGpaRange(pub u64);
2442
2443    impl HvGpaRange {
2444        pub fn as_simple(self) -> HvGpaRangeSimple {
2445            HvGpaRangeSimple(self.0)
2446        }
2447
2448        pub fn as_extended(self) -> HvGpaRangeExtended {
2449            HvGpaRangeExtended(self.0)
2450        }
2451
2452        pub fn as_extended_large_page(self) -> HvGpaRangeExtendedLargePage {
2453            HvGpaRangeExtendedLargePage(self.0)
2454        }
2455    }
2456
2457    #[bitfield(u64)]
2458    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2459    pub struct HvGpaRangeSimple {
2460        /// The number of pages beyond one.
2461        #[bits(12)]
2462        pub additional_pages: u64,
2463        /// The top 52 most significant bits of the guest physical address.
2464        #[bits(52)]
2465        pub gpa_page_number: u64,
2466    }
2467
2468    #[bitfield(u64)]
2469    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2470    pub struct HvGpaRangeExtended {
2471        /// The number of pages beyond one.
2472        #[bits(11)]
2473        pub additional_pages: u64,
2474        /// Is page size greater than 4 KB.
2475        pub large_page: bool,
2476        /// The top 52 most significant bits of the guest physical address when `large_page`` is clear.
2477        #[bits(52)]
2478        pub gpa_page_number: u64,
2479    }
2480
2481    #[bitfield(u64)]
2482    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2483    pub struct HvGpaRangeExtendedLargePage {
2484        /// The number of pages beyond one.
2485        #[bits(11)]
2486        pub additional_pages: u64,
2487        /// Is page size greater than 4 KB.
2488        pub large_page: bool,
2489        /// The page size when `large_page`` is set.
2490        /// false: 2 MB
2491        /// true: 1 GB
2492        pub page_size: bool,
2493        #[bits(8)]
2494        _reserved: u64,
2495        /// The top 43 most significant bits of the guest physical address when `large_page`` is set.
2496        #[bits(43)]
2497        pub gpa_large_page_number: u64,
2498    }
2499
2500    pub const HV_HYPERCALL_MMIO_MAX_DATA_LENGTH: usize = 64;
2501
2502    #[repr(C)]
2503    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2504    pub struct MemoryMappedIoRead {
2505        pub gpa: u64,
2506        pub access_width: u32,
2507        pub reserved_z0: u32,
2508    }
2509
2510    #[repr(C)]
2511    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2512    pub struct MemoryMappedIoReadOutput {
2513        pub data: [u8; HV_HYPERCALL_MMIO_MAX_DATA_LENGTH],
2514    }
2515
2516    #[repr(C)]
2517    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2518    pub struct MemoryMappedIoWrite {
2519        pub gpa: u64,
2520        pub access_width: u32,
2521        pub reserved_z0: u32,
2522        pub data: [u8; HV_HYPERCALL_MMIO_MAX_DATA_LENGTH],
2523    }
2524
2525    #[repr(C)]
2526    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2527    pub struct RestorePartitionTime {
2528        pub partition_id: u64,
2529        pub tsc_sequence: u32,
2530        pub reserved: u32,
2531        pub reference_time_in_100_ns: u64,
2532        pub tsc: u64,
2533    }
2534}
2535
2536macro_rules! registers {
2537    ($name:ident {
2538        $(
2539            $(#[$vattr:meta])*
2540            $variant:ident = $value:expr
2541        ),*
2542        $(,)?
2543    }) => {
2544        open_enum! {
2545    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2546            pub enum $name: u32 {
2547        #![expect(non_upper_case_globals)]
2548                $($variant = $value,)*
2549                InstructionEmulationHints = 0x00000002,
2550                InternalActivityState = 0x00000004,
2551
2552        // Guest Crash Registers
2553                GuestCrashP0  = 0x00000210,
2554                GuestCrashP1  = 0x00000211,
2555                GuestCrashP2  = 0x00000212,
2556                GuestCrashP3  = 0x00000213,
2557                GuestCrashP4  = 0x00000214,
2558                GuestCrashCtl = 0x00000215,
2559
2560                PendingInterruption = 0x00010002,
2561                InterruptState = 0x00010003,
2562                PendingEvent0 = 0x00010004,
2563                PendingEvent1 = 0x00010005,
2564                DeliverabilityNotifications = 0x00010006,
2565
2566                GicrBaseGpa = 0x00063000,
2567
2568                VpRuntime = 0x00090000,
2569                GuestOsId = 0x00090002,
2570                VpIndex = 0x00090003,
2571                TimeRefCount = 0x00090004,
2572                CpuManagementVersion = 0x00090007,
2573                VpAssistPage = 0x00090013,
2574                VpRootSignalCount = 0x00090014,
2575                ReferenceTsc = 0x00090017,
2576                VpConfig = 0x00090018,
2577                Ghcb = 0x00090019,
2578                ReferenceTscSequence = 0x0009001A,
2579                GuestSchedulerEvent = 0x0009001B,
2580
2581                Sint0 = 0x000A0000,
2582                Sint1 = 0x000A0001,
2583                Sint2 = 0x000A0002,
2584                Sint3 = 0x000A0003,
2585                Sint4 = 0x000A0004,
2586                Sint5 = 0x000A0005,
2587                Sint6 = 0x000A0006,
2588                Sint7 = 0x000A0007,
2589                Sint8 = 0x000A0008,
2590                Sint9 = 0x000A0009,
2591                Sint10 = 0x000A000A,
2592                Sint11 = 0x000A000B,
2593                Sint12 = 0x000A000C,
2594                Sint13 = 0x000A000D,
2595                Sint14 = 0x000A000E,
2596                Sint15 = 0x000A000F,
2597                Scontrol = 0x000A0010,
2598                Sversion = 0x000A0011,
2599                Sifp = 0x000A0012,
2600                Sipp = 0x000A0013,
2601                Eom = 0x000A0014,
2602                Sirbp = 0x000A0015,
2603
2604                Stimer0Config = 0x000B0000,
2605                Stimer0Count = 0x000B0001,
2606                Stimer1Config = 0x000B0002,
2607                Stimer1Count = 0x000B0003,
2608                Stimer2Config = 0x000B0004,
2609                Stimer2Count = 0x000B0005,
2610                Stimer3Config = 0x000B0006,
2611                Stimer3Count = 0x000B0007,
2612                StimeUnhaltedTimerConfig = 0x000B0100,
2613                StimeUnhaltedTimerCount = 0x000B0101,
2614
2615                VsmCodePageOffsets = 0x000D0002,
2616                VsmVpStatus = 0x000D0003,
2617                VsmPartitionStatus = 0x000D0004,
2618                VsmVina = 0x000D0005,
2619                VsmCapabilities = 0x000D0006,
2620                VsmPartitionConfig = 0x000D0007,
2621                GuestVsmPartitionConfig = 0x000D0008,
2622                VsmVpSecureConfigVtl0 = 0x000D0010,
2623                VsmVpSecureConfigVtl1 = 0x000D0011,
2624                VsmVpSecureConfigVtl2 = 0x000D0012,
2625                VsmVpSecureConfigVtl3 = 0x000D0013,
2626                VsmVpSecureConfigVtl4 = 0x000D0014,
2627                VsmVpSecureConfigVtl5 = 0x000D0015,
2628                VsmVpSecureConfigVtl6 = 0x000D0016,
2629                VsmVpSecureConfigVtl7 = 0x000D0017,
2630                VsmVpSecureConfigVtl8 = 0x000D0018,
2631                VsmVpSecureConfigVtl9 = 0x000D0019,
2632                VsmVpSecureConfigVtl10 = 0x000D001A,
2633                VsmVpSecureConfigVtl11 = 0x000D001B,
2634                VsmVpSecureConfigVtl12 = 0x000D001C,
2635                VsmVpSecureConfigVtl13 = 0x000D001D,
2636                VsmVpSecureConfigVtl14 = 0x000D001E,
2637                VsmVpWaitForTlbLock = 0x000D0020,
2638            }
2639        }
2640
2641        impl From<HvRegisterName> for $name {
2642            fn from(name: HvRegisterName) -> Self {
2643                Self(name.0)
2644            }
2645        }
2646
2647        impl From<$name> for HvRegisterName {
2648            fn from(name: $name) -> Self {
2649                Self(name.0)
2650            }
2651        }
2652    };
2653}
2654
2655/// A hypervisor register for any architecture.
2656///
2657/// This exists only to pass registers through layers where the architecture
2658/// type has been lost. In general, you should use the arch-specific registers.
2659#[repr(C)]
2660#[derive(Debug, Copy, Clone, PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
2661pub struct HvRegisterName(pub u32);
2662
2663registers! {
2664    // Typed enum for registers that are shared across architectures.
2665    HvAllArchRegisterName {}
2666}
2667
2668impl From<HvAllArchRegisterName> for HvX64RegisterName {
2669    fn from(name: HvAllArchRegisterName) -> Self {
2670        Self(name.0)
2671    }
2672}
2673
2674impl From<HvAllArchRegisterName> for HvArm64RegisterName {
2675    fn from(name: HvAllArchRegisterName) -> Self {
2676        Self(name.0)
2677    }
2678}
2679
2680registers! {
2681    HvX64RegisterName {
2682        // X64 User-Mode Registers
2683        Rax = 0x00020000,
2684        Rcx = 0x00020001,
2685        Rdx = 0x00020002,
2686        Rbx = 0x00020003,
2687        Rsp = 0x00020004,
2688        Rbp = 0x00020005,
2689        Rsi = 0x00020006,
2690        Rdi = 0x00020007,
2691        R8 = 0x00020008,
2692        R9 = 0x00020009,
2693        R10 = 0x0002000a,
2694        R11 = 0x0002000b,
2695        R12 = 0x0002000c,
2696        R13 = 0x0002000d,
2697        R14 = 0x0002000e,
2698        R15 = 0x0002000f,
2699        Rip = 0x00020010,
2700        Rflags = 0x00020011,
2701
2702        // X64 Floating Point and Vector Registers
2703        Xmm0 = 0x00030000,
2704        Xmm1 = 0x00030001,
2705        Xmm2 = 0x00030002,
2706        Xmm3 = 0x00030003,
2707        Xmm4 = 0x00030004,
2708        Xmm5 = 0x00030005,
2709        Xmm6 = 0x00030006,
2710        Xmm7 = 0x00030007,
2711        Xmm8 = 0x00030008,
2712        Xmm9 = 0x00030009,
2713        Xmm10 = 0x0003000A,
2714        Xmm11 = 0x0003000B,
2715        Xmm12 = 0x0003000C,
2716        Xmm13 = 0x0003000D,
2717        Xmm14 = 0x0003000E,
2718        Xmm15 = 0x0003000F,
2719        FpMmx0 = 0x00030010,
2720        FpMmx1 = 0x00030011,
2721        FpMmx2 = 0x00030012,
2722        FpMmx3 = 0x00030013,
2723        FpMmx4 = 0x00030014,
2724        FpMmx5 = 0x00030015,
2725        FpMmx6 = 0x00030016,
2726        FpMmx7 = 0x00030017,
2727        FpControlStatus = 0x00030018,
2728        XmmControlStatus = 0x00030019,
2729
2730        // X64 Control Registers
2731        Cr0 = 0x00040000,
2732        Cr2 = 0x00040001,
2733        Cr3 = 0x00040002,
2734        Cr4 = 0x00040003,
2735        Cr8 = 0x00040004,
2736        Xfem = 0x00040005,
2737        // X64 Intermediate Control Registers
2738        IntermediateCr0 = 0x00041000,
2739        IntermediateCr3 = 0x00041002,
2740        IntermediateCr4 = 0x00041003,
2741        IntermediateCr8 = 0x00041004,
2742        // X64 Debug Registers
2743        Dr0 = 0x00050000,
2744        Dr1 = 0x00050001,
2745        Dr2 = 0x00050002,
2746        Dr3 = 0x00050003,
2747        Dr6 = 0x00050004,
2748        Dr7 = 0x00050005,
2749        // X64 Segment Registers
2750        Es = 0x00060000,
2751        Cs = 0x00060001,
2752        Ss = 0x00060002,
2753        Ds = 0x00060003,
2754        Fs = 0x00060004,
2755        Gs = 0x00060005,
2756        Ldtr = 0x00060006,
2757        Tr = 0x00060007,
2758        // X64 Table Registers
2759        Idtr = 0x00070000,
2760        Gdtr = 0x00070001,
2761        // X64 Virtualized MSRs
2762        Tsc = 0x00080000,
2763        Efer = 0x00080001,
2764        KernelGsBase = 0x00080002,
2765        ApicBase = 0x00080003,
2766        Pat = 0x00080004,
2767        SysenterCs = 0x00080005,
2768        SysenterEip = 0x00080006,
2769        SysenterEsp = 0x00080007,
2770        Star = 0x00080008,
2771        Lstar = 0x00080009,
2772        Cstar = 0x0008000a,
2773        Sfmask = 0x0008000b,
2774        InitialApicId = 0x0008000c,
2775        // X64 Cache control MSRs
2776        MsrMtrrCap = 0x0008000d,
2777        MsrMtrrDefType = 0x0008000e,
2778        MsrMtrrPhysBase0 = 0x00080010,
2779        MsrMtrrPhysBase1 = 0x00080011,
2780        MsrMtrrPhysBase2 = 0x00080012,
2781        MsrMtrrPhysBase3 = 0x00080013,
2782        MsrMtrrPhysBase4 = 0x00080014,
2783        MsrMtrrPhysBase5 = 0x00080015,
2784        MsrMtrrPhysBase6 = 0x00080016,
2785        MsrMtrrPhysBase7 = 0x00080017,
2786        MsrMtrrPhysBase8 = 0x00080018,
2787        MsrMtrrPhysBase9 = 0x00080019,
2788        MsrMtrrPhysBaseA = 0x0008001a,
2789        MsrMtrrPhysBaseB = 0x0008001b,
2790        MsrMtrrPhysBaseC = 0x0008001c,
2791        MsrMtrrPhysBaseD = 0x0008001d,
2792        MsrMtrrPhysBaseE = 0x0008001e,
2793        MsrMtrrPhysBaseF = 0x0008001f,
2794        MsrMtrrPhysMask0 = 0x00080040,
2795        MsrMtrrPhysMask1 = 0x00080041,
2796        MsrMtrrPhysMask2 = 0x00080042,
2797        MsrMtrrPhysMask3 = 0x00080043,
2798        MsrMtrrPhysMask4 = 0x00080044,
2799        MsrMtrrPhysMask5 = 0x00080045,
2800        MsrMtrrPhysMask6 = 0x00080046,
2801        MsrMtrrPhysMask7 = 0x00080047,
2802        MsrMtrrPhysMask8 = 0x00080048,
2803        MsrMtrrPhysMask9 = 0x00080049,
2804        MsrMtrrPhysMaskA = 0x0008004a,
2805        MsrMtrrPhysMaskB = 0x0008004b,
2806        MsrMtrrPhysMaskC = 0x0008004c,
2807        MsrMtrrPhysMaskD = 0x0008004d,
2808        MsrMtrrPhysMaskE = 0x0008004e,
2809        MsrMtrrPhysMaskF = 0x0008004f,
2810        MsrMtrrFix64k00000 = 0x00080070,
2811        MsrMtrrFix16k80000 = 0x00080071,
2812        MsrMtrrFix16kA0000 = 0x00080072,
2813        MsrMtrrFix4kC0000 = 0x00080073,
2814        MsrMtrrFix4kC8000 = 0x00080074,
2815        MsrMtrrFix4kD0000 = 0x00080075,
2816        MsrMtrrFix4kD8000 = 0x00080076,
2817        MsrMtrrFix4kE0000 = 0x00080077,
2818        MsrMtrrFix4kE8000 = 0x00080078,
2819        MsrMtrrFix4kF0000 = 0x00080079,
2820        MsrMtrrFix4kF8000 = 0x0008007a,
2821
2822        TscAux = 0x0008007B,
2823        Bndcfgs = 0x0008007C,
2824        DebugCtl = 0x0008007D,
2825        MCount = 0x0008007E,
2826        ACount = 0x0008007F,
2827
2828        SgxLaunchControl0 = 0x00080080,
2829        SgxLaunchControl1 = 0x00080081,
2830        SgxLaunchControl2 = 0x00080082,
2831        SgxLaunchControl3 = 0x00080083,
2832        SpecCtrl = 0x00080084,
2833        PredCmd = 0x00080085,
2834        VirtSpecCtrl = 0x00080086,
2835        TscVirtualOffset = 0x00080087,
2836        TsxCtrl = 0x00080088,
2837        MsrMcUpdatePatchLevel = 0x00080089,
2838        Available1 = 0x0008008A,
2839        Xss = 0x0008008B,
2840        UCet = 0x0008008C,
2841        SCet = 0x0008008D,
2842        Ssp = 0x0008008E,
2843        Pl0Ssp = 0x0008008F,
2844        Pl1Ssp = 0x00080090,
2845        Pl2Ssp = 0x00080091,
2846        Pl3Ssp = 0x00080092,
2847        InterruptSspTableAddr = 0x00080093,
2848        TscVirtualMultiplier = 0x00080094,
2849        TscDeadline = 0x00080095,
2850        TscAdjust = 0x00080096,
2851        Pasid = 0x00080097,
2852        UmwaitControl = 0x00080098,
2853        Xfd = 0x00080099,
2854        XfdErr = 0x0008009A,
2855
2856        // X64 Apic registers. These match the equivalent x2APIC MSR offsets.
2857        ApicId = 0x00084802,
2858        ApicVersion = 0x00084803,
2859        ApicTpr = 0x00084808,
2860        ApicPpr = 0x0008480a,
2861        ApicEoi = 0x0008480b,
2862        ApicLdr = 0x0008480d,
2863        ApicSpurious = 0x0008480f,
2864        ApicIsr0 = 0x00084810,
2865        ApicIsr1 = 0x00084811,
2866        ApicIsr2 = 0x00084812,
2867        ApicIsr3 = 0x00084813,
2868        ApicIsr4 = 0x00084814,
2869        ApicIsr5 = 0x00084815,
2870        ApicIsr6 = 0x00084816,
2871        ApicIsr7 = 0x00084817,
2872        ApicTmr0 = 0x00084818,
2873        ApicTmr1 = 0x00084819,
2874        ApicTmr2 = 0x0008481a,
2875        ApicTmr3 = 0x0008481b,
2876        ApicTmr4 = 0x0008481c,
2877        ApicTmr5 = 0x0008481d,
2878        ApicTmr6 = 0x0008481e,
2879        ApicTmr7 = 0x0008481f,
2880        ApicIrr0 = 0x00084820,
2881        ApicIrr1 = 0x00084821,
2882        ApicIrr2 = 0x00084822,
2883        ApicIrr3 = 0x00084823,
2884        ApicIrr4 = 0x00084824,
2885        ApicIrr5 = 0x00084825,
2886        ApicIrr6 = 0x00084826,
2887        ApicIrr7 = 0x00084827,
2888        ApicEse = 0x00084828,
2889        ApicIcr = 0x00084830,
2890        ApicLvtTimer = 0x00084832,
2891        ApicLvtThermal = 0x00084833,
2892        ApicLvtPerfmon = 0x00084834,
2893        ApicLvtLint0 = 0x00084835,
2894        ApicLvtLint1 = 0x00084836,
2895        ApicLvtError = 0x00084837,
2896        ApicInitCount = 0x00084838,
2897        ApicCurrentCount = 0x00084839,
2898        ApicDivide = 0x0008483e,
2899        ApicSelfIpi = 0x0008483f,
2900
2901        Hypercall = 0x00090001,
2902        RegisterPage = 0x0009001C,
2903
2904        // Partition Timer Assist Registers
2905        EmulatedTimerPeriod = 0x00090030,
2906        EmulatedTimerControl = 0x00090031,
2907        PmTimerAssist = 0x00090032,
2908
2909        // AMD SEV configuration MSRs
2910        SevControl = 0x00090040,
2911        SevGhcbGpa = 0x00090041,
2912        SevDoorbellGpa = 0x00090042,
2913        SevAvicGpa = 0x00090043,
2914
2915        CrInterceptControl = 0x000E0000,
2916        CrInterceptCr0Mask = 0x000E0001,
2917        CrInterceptCr4Mask = 0x000E0002,
2918        CrInterceptIa32MiscEnableMask = 0x000E0003,
2919    }
2920}
2921
2922registers! {
2923    HvArm64RegisterName {
2924        HypervisorVersion = 0x00000100,
2925        PrivilegesAndFeaturesInfo = 0x00000200,
2926        FeaturesInfo = 0x00000201,
2927        ImplementationLimitsInfo = 0x00000202,
2928        HardwareFeaturesInfo = 0x00000203,
2929        CpuManagementFeaturesInfo = 0x00000204,
2930        PasidFeaturesInfo = 0x00000205,
2931        SkipLevelFeaturesInfo = 0x00000206,
2932        NestedVirtFeaturesInfo = 0x00000207,
2933        IptFeaturesInfo = 0x00000208,
2934        IsolationConfiguration = 0x00000209,
2935
2936        X0 = 0x00020000,
2937        X1 = 0x00020001,
2938        X2 = 0x00020002,
2939        X3 = 0x00020003,
2940        X4 = 0x00020004,
2941        X5 = 0x00020005,
2942        X6 = 0x00020006,
2943        X7 = 0x00020007,
2944        X8 = 0x00020008,
2945        X9 = 0x00020009,
2946        X10 = 0x0002000A,
2947        X11 = 0x0002000B,
2948        X12 = 0x0002000C,
2949        X13 = 0x0002000D,
2950        X14 = 0x0002000E,
2951        X15 = 0x0002000F,
2952        X16 = 0x00020010,
2953        X17 = 0x00020011,
2954        X18 = 0x00020012,
2955        X19 = 0x00020013,
2956        X20 = 0x00020014,
2957        X21 = 0x00020015,
2958        X22 = 0x00020016,
2959        X23 = 0x00020017,
2960        X24 = 0x00020018,
2961        X25 = 0x00020019,
2962        X26 = 0x0002001A,
2963        X27 = 0x0002001B,
2964        X28 = 0x0002001C,
2965        XFp = 0x0002001D,
2966        XLr = 0x0002001E,
2967        XSp = 0x0002001F, // alias for either El0/x depending on Cpsr.SPSel
2968        XSpEl0 = 0x00020020,
2969        XSpElx = 0x00020021,
2970        XPc = 0x00020022,
2971        Cpsr = 0x00020023,
2972        SpsrEl2 = 0x00021002,
2973
2974        MpidrEl1 = 0x00040001,
2975        SctlrEl1 = 0x00040002,
2976        Ttbr0El1 = 0x00040005,
2977        Ttbr1El1 = 0x00040006,
2978        TcrEl1 = 0x00040007,
2979        EsrEl1 = 0x00040008,
2980        FarEl1 = 0x00040009,
2981        MairEl1 = 0x0004000b,
2982        VbarEl1 = 0x0004000c,
2983        ElrEl1 = 0x00040015,
2984    }
2985}
2986
2987#[repr(C)]
2988#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoBytes, Immutable, KnownLayout, FromBytes)]
2989pub struct HvRegisterValue(pub AlignedU128);
2990
2991impl HvRegisterValue {
2992    pub fn as_u128(&self) -> u128 {
2993        self.0.into()
2994    }
2995
2996    pub fn as_u64(&self) -> u64 {
2997        self.as_u128() as u64
2998    }
2999
3000    pub fn as_u32(&self) -> u32 {
3001        self.as_u128() as u32
3002    }
3003
3004    pub fn as_u16(&self) -> u16 {
3005        self.as_u128() as u16
3006    }
3007
3008    pub fn as_u8(&self) -> u8 {
3009        self.as_u128() as u8
3010    }
3011
3012    pub fn as_table(&self) -> HvX64TableRegister {
3013        HvX64TableRegister::read_from_prefix(self.as_bytes())
3014            .unwrap()
3015            .0 // TODO: zerocopy: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
3016    }
3017
3018    pub fn as_segment(&self) -> HvX64SegmentRegister {
3019        HvX64SegmentRegister::read_from_prefix(self.as_bytes())
3020            .unwrap()
3021            .0 // TODO: zerocopy: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
3022    }
3023}
3024
3025impl From<u8> for HvRegisterValue {
3026    fn from(val: u8) -> Self {
3027        (val as u128).into()
3028    }
3029}
3030
3031impl From<u16> for HvRegisterValue {
3032    fn from(val: u16) -> Self {
3033        (val as u128).into()
3034    }
3035}
3036
3037impl From<u32> for HvRegisterValue {
3038    fn from(val: u32) -> Self {
3039        (val as u128).into()
3040    }
3041}
3042
3043impl From<u64> for HvRegisterValue {
3044    fn from(val: u64) -> Self {
3045        (val as u128).into()
3046    }
3047}
3048
3049impl From<u128> for HvRegisterValue {
3050    fn from(val: u128) -> Self {
3051        Self(val.into())
3052    }
3053}
3054
3055#[repr(C)]
3056#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoBytes, Immutable, KnownLayout, FromBytes)]
3057pub struct HvX64TableRegister {
3058    pub pad: [u16; 3],
3059    pub limit: u16,
3060    pub base: u64,
3061}
3062
3063impl From<HvX64TableRegister> for HvRegisterValue {
3064    fn from(val: HvX64TableRegister) -> Self {
3065        Self::read_from_prefix(val.as_bytes()).unwrap().0 // TODO: zerocopy: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
3066    }
3067}
3068
3069impl From<HvRegisterValue> for HvX64TableRegister {
3070    fn from(val: HvRegisterValue) -> Self {
3071        Self::read_from_prefix(val.as_bytes()).unwrap().0 // TODO: zerocopy: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
3072    }
3073}
3074
3075#[repr(C)]
3076#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoBytes, Immutable, KnownLayout, FromBytes)]
3077pub struct HvX64SegmentRegister {
3078    pub base: u64,
3079    pub limit: u32,
3080    pub selector: u16,
3081    pub attributes: u16,
3082}
3083
3084impl From<HvX64SegmentRegister> for HvRegisterValue {
3085    fn from(val: HvX64SegmentRegister) -> Self {
3086        Self::read_from_prefix(val.as_bytes()).unwrap().0 // TODO: zerocopy: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
3087    }
3088}
3089
3090impl From<HvRegisterValue> for HvX64SegmentRegister {
3091    fn from(val: HvRegisterValue) -> Self {
3092        Self::read_from_prefix(val.as_bytes()).unwrap().0 // TODO: zerocopy: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
3093    }
3094}
3095
3096#[bitfield(u64)]
3097#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
3098pub struct HvDeliverabilityNotificationsRegister {
3099    /// x86_64 only.
3100    pub nmi_notification: bool,
3101    /// x86_64 only.
3102    pub interrupt_notification: bool,
3103    /// x86_64 only.
3104    #[bits(4)]
3105    /// Only used on x86_64.
3106    pub interrupt_priority: u8,
3107    #[bits(42)]
3108    pub reserved: u64,
3109    pub sints: u16,
3110}
3111
3112open_enum! {
3113    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3114    pub enum HvVtlEntryReason: u32 {
3115        /// This reason is reserved and is not used.
3116        RESERVED = 0,
3117
3118        /// Indicates entry due to a VTL call from a lower VTL.
3119        VTL_CALL = 1,
3120
3121        /// Indicates entry due to an interrupt targeted to the VTL.
3122        INTERRUPT = 2,
3123
3124        // Indicates an entry due to an intercept delivered via the intercept page.
3125        INTERCEPT = 3,
3126    }
3127}
3128
3129#[repr(C)]
3130#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3131pub struct HvVpVtlControl {
3132    //
3133    // The hypervisor updates the entry reason with an indication as to why the
3134    // VTL was entered on the virtual processor.
3135    //
3136    pub entry_reason: HvVtlEntryReason,
3137
3138    /// This flag determines whether the VINA interrupt line is asserted.
3139    pub vina_status: u8,
3140    pub reserved_z0: u8,
3141    pub reserved_z1: u16,
3142
3143    /// A guest updates the VtlReturn* fields to provide the register values to
3144    /// restore on VTL return.  The specific register values that are restored
3145    /// will vary based on whether the VTL is 32-bit or 64-bit: rax and rcx or
3146    /// eax, ecx, and edx.
3147    pub registers: [u64; 2],
3148}
3149
3150#[bitfield(u64)]
3151#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3152pub struct HvRegisterVsmVina {
3153    pub vector: u8,
3154    pub enabled: bool,
3155    pub auto_reset: bool,
3156    pub auto_eoi: bool,
3157    #[bits(53)]
3158    pub reserved: u64,
3159}
3160
3161#[repr(C)]
3162#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3163pub struct HvVpAssistPage {
3164    /// APIC assist for optimized EOI processing.
3165    pub apic_assist: u32,
3166    pub reserved_z0: u32,
3167
3168    /// VP-VTL control information
3169    pub vtl_control: HvVpVtlControl,
3170
3171    pub nested_enlightenments_control: u64,
3172    pub enlighten_vm_entry: u8,
3173    pub reserved_z1: [u8; 7],
3174    pub current_nested_vmcs: u64,
3175    pub synthetic_time_unhalted_timer_expired: u8,
3176    pub reserved_z2: [u8; 7],
3177    pub virtualization_fault_information: [u8; 40],
3178    pub reserved_z3: u64,
3179    pub intercept_message: HvMessage,
3180    pub vtl_return_actions: [u8; 256],
3181}
3182
3183#[repr(C)]
3184#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3185pub struct HvVpAssistPageActionSignalEvent {
3186    pub action_type: u64,
3187    pub target_vp: u32,
3188    pub target_vtl: u8,
3189    pub target_sint: u8,
3190    pub flag_number: u16,
3191}
3192
3193open_enum! {
3194    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3195    pub enum HvInterceptAccessType: u8 {
3196        READ = 0,
3197        WRITE = 1,
3198        EXECUTE = 2,
3199    }
3200}
3201
3202#[bitfield(u16)]
3203#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3204pub struct HvX64VpExecutionState {
3205    #[bits(2)]
3206    pub cpl: u8,
3207    pub cr0_pe: bool,
3208    pub cr0_am: bool,
3209    pub efer_lma: bool,
3210    pub debug_active: bool,
3211    pub interruption_pending: bool,
3212    #[bits(4)]
3213    pub vtl: u8,
3214    pub enclave_mode: bool,
3215    pub interrupt_shadow: bool,
3216    pub virtualization_fault_active: bool,
3217    #[bits(2)]
3218    pub reserved: u8,
3219}
3220
3221#[bitfield(u16)]
3222#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3223pub struct HvArm64VpExecutionState {
3224    #[bits(2)]
3225    pub cpl: u8,
3226    pub debug_active: bool,
3227    pub interruption_pending: bool,
3228    #[bits(4)]
3229    pub vtl: u8,
3230    pub virtualization_fault_active: bool,
3231    #[bits(7)]
3232    pub reserved: u8,
3233}
3234
3235#[repr(C)]
3236#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
3237pub struct HvX64InterceptMessageHeader {
3238    pub vp_index: u32,
3239    pub instruction_length_and_cr8: u8,
3240    pub intercept_access_type: HvInterceptAccessType,
3241    pub execution_state: HvX64VpExecutionState,
3242    pub cs_segment: HvX64SegmentRegister,
3243    pub rip: u64,
3244    pub rflags: u64,
3245}
3246
3247impl MessagePayload for HvX64InterceptMessageHeader {}
3248
3249impl HvX64InterceptMessageHeader {
3250    pub fn instruction_len(&self) -> u8 {
3251        self.instruction_length_and_cr8 & 0xf
3252    }
3253
3254    pub fn cr8(&self) -> u8 {
3255        self.instruction_length_and_cr8 >> 4
3256    }
3257}
3258
3259#[repr(C)]
3260#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
3261pub struct HvArm64InterceptMessageHeader {
3262    pub vp_index: u32,
3263    pub instruction_length: u8,
3264    pub intercept_access_type: HvInterceptAccessType,
3265    pub execution_state: HvArm64VpExecutionState,
3266    pub pc: u64,
3267    pub cspr: u64,
3268}
3269const_assert!(size_of::<HvArm64InterceptMessageHeader>() == 0x18);
3270
3271impl MessagePayload for HvArm64InterceptMessageHeader {}
3272
3273#[repr(transparent)]
3274#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
3275pub struct HvX64IoPortAccessInfo(pub u8);
3276
3277impl HvX64IoPortAccessInfo {
3278    pub fn new(access_size: u8, string_op: bool, rep_prefix: bool) -> Self {
3279        let mut info = access_size & 0x7;
3280
3281        if string_op {
3282            info |= 0x8;
3283        }
3284
3285        if rep_prefix {
3286            info |= 0x10;
3287        }
3288
3289        Self(info)
3290    }
3291
3292    pub fn access_size(&self) -> u8 {
3293        self.0 & 0x7
3294    }
3295
3296    pub fn string_op(&self) -> bool {
3297        self.0 & 0x8 != 0
3298    }
3299
3300    pub fn rep_prefix(&self) -> bool {
3301        self.0 & 0x10 != 0
3302    }
3303}
3304
3305#[repr(C)]
3306#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3307pub struct HvX64IoPortInterceptMessage {
3308    pub header: HvX64InterceptMessageHeader,
3309    pub port_number: u16,
3310    pub access_info: HvX64IoPortAccessInfo,
3311    pub instruction_byte_count: u8,
3312    pub reserved: u32,
3313    pub rax: u64,
3314    pub instruction_bytes: [u8; 16],
3315    pub ds_segment: HvX64SegmentRegister,
3316    pub es_segment: HvX64SegmentRegister,
3317    pub rcx: u64,
3318    pub rsi: u64,
3319    pub rdi: u64,
3320}
3321
3322impl MessagePayload for HvX64IoPortInterceptMessage {}
3323
3324#[bitfield(u8)]
3325#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3326pub struct HvX64MemoryAccessInfo {
3327    pub gva_valid: bool,
3328    pub gva_gpa_valid: bool,
3329    pub hypercall_output_pending: bool,
3330    pub tlb_locked: bool,
3331    pub supervisor_shadow_stack: bool,
3332    #[bits(3)]
3333    pub reserved1: u8,
3334}
3335
3336#[bitfield(u8)]
3337#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3338pub struct HvArm64MemoryAccessInfo {
3339    pub gva_valid: bool,
3340    pub gva_gpa_valid: bool,
3341    pub hypercall_output_pending: bool,
3342    #[bits(5)]
3343    pub reserved1: u8,
3344}
3345
3346open_enum! {
3347    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3348    pub enum HvCacheType: u32 {
3349        #![expect(non_upper_case_globals)]
3350        HvCacheTypeUncached = 0,
3351        HvCacheTypeWriteCombining = 1,
3352        HvCacheTypeWriteThrough = 4,
3353        HvCacheTypeWriteProtected = 5,
3354        HvCacheTypeWriteBack = 6,
3355    }
3356}
3357
3358#[repr(C)]
3359#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3360pub struct HvX64MemoryInterceptMessage {
3361    pub header: HvX64InterceptMessageHeader,
3362    pub cache_type: HvCacheType,
3363    pub instruction_byte_count: u8,
3364    pub memory_access_info: HvX64MemoryAccessInfo,
3365    pub tpr_priority: u8,
3366    pub reserved: u8,
3367    pub guest_virtual_address: u64,
3368    pub guest_physical_address: u64,
3369    pub instruction_bytes: [u8; 16],
3370}
3371
3372impl MessagePayload for HvX64MemoryInterceptMessage {}
3373const_assert!(size_of::<HvX64MemoryInterceptMessage>() == 0x50);
3374
3375#[repr(C)]
3376#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3377pub struct HvArm64MemoryInterceptMessage {
3378    pub header: HvArm64InterceptMessageHeader,
3379    pub cache_type: HvCacheType,
3380    pub instruction_byte_count: u8,
3381    pub memory_access_info: HvArm64MemoryAccessInfo,
3382    pub reserved1: u16,
3383    pub instruction_bytes: [u8; 4],
3384    pub reserved2: u32,
3385    pub guest_virtual_address: u64,
3386    pub guest_physical_address: u64,
3387    pub syndrome: u64,
3388}
3389
3390impl MessagePayload for HvArm64MemoryInterceptMessage {}
3391const_assert!(size_of::<HvArm64MemoryInterceptMessage>() == 0x40);
3392
3393#[repr(C)]
3394#[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
3395pub struct HvArm64MmioInterceptMessage {
3396    pub header: HvArm64InterceptMessageHeader,
3397    pub guest_physical_address: u64,
3398    pub access_size: u32,
3399    pub data: [u8; 32],
3400    pub padding: u32,
3401}
3402
3403impl MessagePayload for HvArm64MmioInterceptMessage {}
3404const_assert!(size_of::<HvArm64MmioInterceptMessage>() == 0x48);
3405
3406#[repr(C)]
3407#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3408pub struct HvX64MsrInterceptMessage {
3409    pub header: HvX64InterceptMessageHeader,
3410    pub msr_number: u32,
3411    pub reserved: u32,
3412    pub rdx: u64,
3413    pub rax: u64,
3414}
3415
3416impl MessagePayload for HvX64MsrInterceptMessage {}
3417
3418#[repr(C)]
3419#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3420pub struct HvX64SipiInterceptMessage {
3421    pub header: HvX64InterceptMessageHeader,
3422    pub target_vp_index: u32,
3423    pub vector: u32,
3424}
3425
3426impl MessagePayload for HvX64SipiInterceptMessage {}
3427
3428#[repr(C)]
3429#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3430pub struct HvX64SynicSintDeliverableMessage {
3431    pub header: HvX64InterceptMessageHeader,
3432    pub deliverable_sints: u16,
3433    pub rsvd1: u16,
3434    pub rsvd2: u32,
3435}
3436
3437impl MessagePayload for HvX64SynicSintDeliverableMessage {}
3438
3439#[repr(C)]
3440#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3441pub struct HvArm64SynicSintDeliverableMessage {
3442    pub header: HvArm64InterceptMessageHeader,
3443    pub deliverable_sints: u16,
3444    pub rsvd1: u16,
3445    pub rsvd2: u32,
3446}
3447
3448impl MessagePayload for HvArm64SynicSintDeliverableMessage {}
3449
3450#[repr(C)]
3451#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3452pub struct HvX64InterruptionDeliverableMessage {
3453    pub header: HvX64InterceptMessageHeader,
3454    pub deliverable_type: HvX64PendingInterruptionType,
3455    pub rsvd: [u8; 3],
3456    pub rsvd2: u32,
3457}
3458
3459impl MessagePayload for HvX64InterruptionDeliverableMessage {}
3460
3461open_enum! {
3462    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3463    pub enum HvX64PendingInterruptionType: u8 {
3464        HV_X64_PENDING_INTERRUPT = 0,
3465        HV_X64_PENDING_NMI = 2,
3466        HV_X64_PENDING_EXCEPTION = 3,
3467        HV_X64_PENDING_SOFTWARE_INTERRUPT = 4,
3468        HV_X64_PENDING_PRIVILEGED_SOFTWARE_EXCEPTION = 5,
3469        HV_X64_PENDING_SOFTWARE_EXCEPTION = 6,
3470    }
3471}
3472
3473#[repr(C)]
3474#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
3475pub struct HvX64HypercallInterceptMessage {
3476    pub header: HvX64InterceptMessageHeader,
3477    pub rax: u64,
3478    pub rbx: u64,
3479    pub rcx: u64,
3480    pub rdx: u64,
3481    pub r8: u64,
3482    pub rsi: u64,
3483    pub rdi: u64,
3484    pub xmm_registers: [AlignedU128; 6],
3485    pub flags: HvHypercallInterceptMessageFlags,
3486    pub rsvd2: [u32; 3],
3487}
3488
3489impl MessagePayload for HvX64HypercallInterceptMessage {}
3490
3491#[repr(C)]
3492#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
3493pub struct HvArm64HypercallInterceptMessage {
3494    pub header: HvArm64InterceptMessageHeader,
3495    pub immediate: u16,
3496    pub reserved: u16,
3497    pub flags: HvHypercallInterceptMessageFlags,
3498    pub x: [u64; 18],
3499}
3500
3501impl MessagePayload for HvArm64HypercallInterceptMessage {}
3502
3503#[bitfield(u32)]
3504#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3505pub struct HvHypercallInterceptMessageFlags {
3506    pub is_isolated: bool,
3507    #[bits(31)]
3508    _reserved: u32,
3509}
3510
3511#[repr(C)]
3512#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3513pub struct HvX64CpuidInterceptMessage {
3514    pub header: HvX64InterceptMessageHeader,
3515    pub rax: u64,
3516    pub rcx: u64,
3517    pub rdx: u64,
3518    pub rbx: u64,
3519    pub default_result_rax: u64,
3520    pub default_result_rcx: u64,
3521    pub default_result_rdx: u64,
3522    pub default_result_rbx: u64,
3523}
3524
3525impl MessagePayload for HvX64CpuidInterceptMessage {}
3526
3527#[bitfield(u8)]
3528#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3529pub struct HvX64ExceptionInfo {
3530    pub error_code_valid: bool,
3531    pub software_exception: bool,
3532    #[bits(6)]
3533    reserved: u8,
3534}
3535
3536#[repr(C)]
3537#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3538pub struct HvX64ExceptionInterceptMessage {
3539    pub header: HvX64InterceptMessageHeader,
3540    pub vector: u16,
3541    pub exception_info: HvX64ExceptionInfo,
3542    pub instruction_byte_count: u8,
3543    pub error_code: u32,
3544    pub exception_parameter: u64,
3545    pub reserved: u64,
3546    pub instruction_bytes: [u8; 16],
3547    pub ds_segment: HvX64SegmentRegister,
3548    pub ss_segment: HvX64SegmentRegister,
3549    pub rax: u64,
3550    pub rcx: u64,
3551    pub rdx: u64,
3552    pub rbx: u64,
3553    pub rsp: u64,
3554    pub rbp: u64,
3555    pub rsi: u64,
3556    pub rdi: u64,
3557    pub r8: u64,
3558    pub r9: u64,
3559    pub r10: u64,
3560    pub r11: u64,
3561    pub r12: u64,
3562    pub r13: u64,
3563    pub r14: u64,
3564    pub r15: u64,
3565}
3566
3567impl MessagePayload for HvX64ExceptionInterceptMessage {}
3568
3569#[repr(C)]
3570#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3571pub struct HvInvalidVpRegisterMessage {
3572    pub vp_index: u32,
3573    pub reserved: u32,
3574}
3575
3576impl MessagePayload for HvInvalidVpRegisterMessage {}
3577
3578#[repr(C)]
3579#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3580pub struct HvX64ApicEoiMessage {
3581    pub vp_index: u32,
3582    pub interrupt_vector: u32,
3583}
3584
3585impl MessagePayload for HvX64ApicEoiMessage {}
3586
3587#[repr(C)]
3588#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3589pub struct HvX64UnrecoverableExceptionMessage {
3590    pub header: HvX64InterceptMessageHeader,
3591}
3592
3593impl MessagePayload for HvX64UnrecoverableExceptionMessage {}
3594
3595#[repr(C)]
3596#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3597pub struct HvX64HaltMessage {
3598    pub header: HvX64InterceptMessageHeader,
3599}
3600
3601impl MessagePayload for HvX64HaltMessage {}
3602
3603#[repr(C)]
3604#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
3605pub struct HvArm64ResetInterceptMessage {
3606    pub header: HvArm64InterceptMessageHeader,
3607    pub reset_type: HvArm64ResetType,
3608    pub reset_code: u32,
3609}
3610
3611impl MessagePayload for HvArm64ResetInterceptMessage {}
3612
3613open_enum! {
3614    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3615    pub enum HvArm64ResetType: u32 {
3616        POWER_OFF = 0,
3617        REBOOT = 1,
3618        SYSTEM_RESET = 2,
3619        HIBERNATE = 3,
3620    }
3621}
3622
3623#[bitfield(u8)]
3624#[derive(IntoBytes, Immutable, FromBytes)]
3625pub struct HvX64RegisterInterceptMessageFlags {
3626    pub is_memory_op: bool,
3627    #[bits(7)]
3628    _rsvd: u8,
3629}
3630
3631#[repr(C)]
3632#[derive(IntoBytes, Immutable, FromBytes)]
3633pub struct HvX64RegisterInterceptMessage {
3634    pub header: HvX64InterceptMessageHeader,
3635    pub flags: HvX64RegisterInterceptMessageFlags,
3636    pub rsvd: u8,
3637    pub rsvd2: u16,
3638    pub register_name: HvX64RegisterName,
3639    pub access_info: HvX64RegisterAccessInfo,
3640}
3641
3642#[repr(transparent)]
3643#[derive(IntoBytes, Immutable, FromBytes)]
3644pub struct HvX64RegisterAccessInfo(u128);
3645
3646impl HvX64RegisterAccessInfo {
3647    pub fn new_source_value(source_value: HvRegisterValue) -> Self {
3648        Self(source_value.as_u128())
3649    }
3650}
3651
3652open_enum! {
3653    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3654    pub enum HvInterruptType : u32  {
3655        #![expect(non_upper_case_globals)]
3656        HvArm64InterruptTypeFixed = 0x0000,
3657        HvX64InterruptTypeFixed = 0x0000,
3658        HvX64InterruptTypeLowestPriority = 0x0001,
3659        HvX64InterruptTypeSmi = 0x0002,
3660        HvX64InterruptTypeRemoteRead = 0x0003,
3661        HvX64InterruptTypeNmi = 0x0004,
3662        HvX64InterruptTypeInit = 0x0005,
3663        HvX64InterruptTypeSipi = 0x0006,
3664        HvX64InterruptTypeExtInt = 0x0007,
3665        HvX64InterruptTypeLocalInt0 = 0x0008,
3666        HvX64InterruptTypeLocalInt1 = 0x0009,
3667    }
3668}
3669
3670/// The declaration uses the fact the bits for the different
3671/// architectures don't intersect. When (if ever) they do,
3672/// will need to come up with a more elaborate abstraction.
3673/// The other possible downside is the lack of the compile-time
3674/// checks as adding that will require `guest_arch` support and
3675/// a large refactoring. To sum up, choosing expediency.
3676#[bitfield(u64)]
3677#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3678pub struct HvInterruptControl {
3679    interrupt_type_value: u32,
3680    pub x86_level_triggered: bool,
3681    pub x86_logical_destination_mode: bool,
3682    pub arm64_asserted: bool,
3683    #[bits(29)]
3684    pub unused: u32,
3685}
3686
3687impl HvInterruptControl {
3688    pub fn interrupt_type(&self) -> HvInterruptType {
3689        HvInterruptType(self.interrupt_type_value())
3690    }
3691
3692    pub fn set_interrupt_type(&mut self, ty: HvInterruptType) {
3693        self.set_interrupt_type_value(ty.0)
3694    }
3695
3696    pub fn with_interrupt_type(self, ty: HvInterruptType) -> Self {
3697        self.with_interrupt_type_value(ty.0)
3698    }
3699}
3700
3701#[bitfield(u64)]
3702pub struct HvRegisterVsmCapabilities {
3703    pub dr6_shared: bool,
3704    pub mbec_vtl_mask: u16,
3705    pub deny_lower_vtl_startup: bool,
3706    pub supervisor_shadow_stack: bool,
3707    pub hardware_hvpt_available: bool,
3708    pub software_hvpt_available: bool,
3709    #[bits(6)]
3710    pub hardware_hvpt_range_bits: u8,
3711    pub intercept_page_available: bool,
3712    pub return_action_available: bool,
3713    /// If the VTL0 view of memory is mapped to the high address space, which is
3714    /// the highest legal physical address bit.
3715    ///
3716    /// Only available in VTL2.
3717    pub vtl0_alias_map_available: bool,
3718    /// If the [`HvRegisterVsmPartitionConfig`] register has support for
3719    /// `intercept_not_present`.
3720    ///
3721    /// Only available in VTL2.
3722    pub intercept_not_present_available: bool,
3723    pub install_intercept_ex: bool,
3724    /// Only available in VTL2.
3725    pub intercept_system_reset_available: bool,
3726    #[bits(1)]
3727    pub reserved1: u8,
3728    pub proxy_interrupt_redirect_available: bool,
3729    #[bits(29)]
3730    pub reserved2: u64,
3731}
3732
3733#[bitfield(u64)]
3734pub struct HvRegisterVsmPartitionConfig {
3735    pub enable_vtl_protection: bool,
3736    #[bits(4)]
3737    pub default_vtl_protection_mask: u8,
3738    pub zero_memory_on_reset: bool,
3739    pub deny_lower_vtl_startup: bool,
3740    pub intercept_acceptance: bool,
3741    pub intercept_enable_vtl_protection: bool,
3742    pub intercept_vp_startup: bool,
3743    pub intercept_cpuid_unimplemented: bool,
3744    pub intercept_unrecoverable_exception: bool,
3745    pub intercept_page: bool,
3746    pub intercept_restore_partition_time: bool,
3747    /// The hypervisor will send all unmapped GPA intercepts to VTL2 rather than
3748    /// the host.
3749    pub intercept_not_present: bool,
3750    pub intercept_system_reset: bool,
3751    #[bits(48)]
3752    pub reserved: u64,
3753}
3754
3755#[bitfield(u64)]
3756pub struct HvRegisterVsmPartitionStatus {
3757    #[bits(16)]
3758    pub enabled_vtl_set: u16,
3759    #[bits(4)]
3760    pub maximum_vtl: u8,
3761    #[bits(16)]
3762    pub mbec_enabled_vtl_set: u16,
3763    #[bits(4)]
3764    pub supervisor_shadow_stack_enabled_vtl_set: u8,
3765    #[bits(24)]
3766    pub reserved: u64,
3767}
3768
3769open_enum! {
3770    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3771    pub enum HvSnpInterruptInjection : u8  {
3772        #![allow(non_upper_case_globals)]
3773        HvSnpRestricted = 0x0,
3774        HvSnpNormal = 0x1,
3775        HvSnpAlternate = 0x2,
3776        HvSnpSecureAvic = 0x3,
3777    }
3778}
3779
3780// Support for bitfield structures.
3781impl HvSnpInterruptInjection {
3782    const fn from_bits(val: u8) -> Self {
3783        HvSnpInterruptInjection(val)
3784    }
3785
3786    const fn into_bits(self) -> u8 {
3787        self.0
3788    }
3789}
3790
3791#[bitfield(u64)]
3792pub struct HvRegisterGuestVsmPartitionConfig {
3793    #[bits(4)]
3794    pub maximum_vtl: u8,
3795    #[bits(2)]
3796    pub vtl0_interrupt_injection: HvSnpInterruptInjection,
3797    #[bits(2)]
3798    pub vtl1_interrupt_injection: HvSnpInterruptInjection,
3799    #[bits(56)]
3800    pub reserved: u64,
3801}
3802
3803#[bitfield(u64)]
3804pub struct HvRegisterVsmVpStatus {
3805    #[bits(4)]
3806    pub active_vtl: u8,
3807    pub active_mbec_enabled: bool,
3808    #[bits(11)]
3809    pub reserved_mbz0: u16,
3810    #[bits(16)]
3811    pub enabled_vtl_set: u16,
3812    #[bits(32)]
3813    pub reserved_mbz1: u32,
3814}
3815
3816#[bitfield(u64)]
3817pub struct HvRegisterVsmCodePageOffsets {
3818    #[bits(12)]
3819    pub call_offset: u16,
3820    #[bits(12)]
3821    pub return_offset: u16,
3822    #[bits(40)]
3823    pub reserved: u64,
3824}
3825
3826#[repr(C)]
3827#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3828pub struct HvStimerState {
3829    pub undelivered_message_pending: u32,
3830    pub reserved: u32,
3831    pub config: u64,
3832    pub count: u64,
3833    pub adjustment: u64,
3834    pub undelivered_expiration_time: u64,
3835}
3836
3837#[repr(C)]
3838#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3839pub struct HvSyntheticTimersState {
3840    pub timers: [HvStimerState; 4],
3841    pub reserved: [u64; 5],
3842}
3843
3844#[bitfield(u64)]
3845pub struct HvInternalActivityRegister {
3846    pub startup_suspend: bool,
3847    pub halt_suspend: bool,
3848    pub idle_suspend: bool,
3849    #[bits(61)]
3850    pub reserved: u64,
3851}
3852
3853#[bitfield(u64)]
3854pub struct HvSynicSint {
3855    pub vector: u8,
3856    _reserved: u8,
3857    pub masked: bool,
3858    pub auto_eoi: bool,
3859    pub polling: bool,
3860    _reserved2: bool,
3861    pub proxy: bool,
3862    #[bits(43)]
3863    _reserved2: u64,
3864}
3865
3866#[bitfield(u64)]
3867pub struct HvSynicScontrol {
3868    pub enabled: bool,
3869    #[bits(63)]
3870    _reserved: u64,
3871}
3872
3873#[bitfield(u64)]
3874pub struct HvSynicSimpSiefp {
3875    pub enabled: bool,
3876    #[bits(11)]
3877    _reserved: u64,
3878    #[bits(52)]
3879    pub base_gpn: u64,
3880}
3881
3882#[bitfield(u64)]
3883pub struct HvSynicStimerConfig {
3884    pub enabled: bool,
3885    pub periodic: bool,
3886    pub lazy: bool,
3887    pub auto_enable: bool,
3888    // Note: On ARM64 the top 3 bits of apic_vector are reserved.
3889    pub apic_vector: u8,
3890    pub direct_mode: bool,
3891    #[bits(3)]
3892    pub _reserved1: u8,
3893    #[bits(4)]
3894    pub sint: u8,
3895    #[bits(44)]
3896    pub _reserved2: u64,
3897}
3898
3899pub const HV_X64_PENDING_EVENT_EXCEPTION: u8 = 0;
3900pub const HV_X64_PENDING_EVENT_MEMORY_INTERCEPT: u8 = 1;
3901pub const HV_X64_PENDING_EVENT_NESTED_MEMORY_INTERCEPT: u8 = 2;
3902pub const HV_X64_PENDING_EVENT_VIRTUALIZATION_FAULT: u8 = 3;
3903pub const HV_X64_PENDING_EVENT_HYPERCALL_OUTPUT: u8 = 4;
3904pub const HV_X64_PENDING_EVENT_EXT_INT: u8 = 5;
3905pub const HV_X64_PENDING_EVENT_SHADOW_IPT: u8 = 6;
3906
3907// Provides information about an exception.
3908#[bitfield(u128)]
3909pub struct HvX64PendingExceptionEvent {
3910    pub event_pending: bool,
3911    #[bits(3)]
3912    pub event_type: u8,
3913    #[bits(4)]
3914    pub reserved0: u8,
3915
3916    pub deliver_error_code: bool,
3917    #[bits(7)]
3918    pub reserved1: u8,
3919    pub vector: u16,
3920    pub error_code: u32,
3921    pub exception_parameter: u64,
3922}
3923
3924/// Provides information about a virtualization fault.
3925#[bitfield(u128)]
3926pub struct HvX64PendingVirtualizationFaultEvent {
3927    pub event_pending: bool,
3928    #[bits(3)]
3929    pub event_type: u8,
3930    #[bits(4)]
3931    pub reserved0: u8,
3932
3933    pub reserved1: u8,
3934    pub parameter0: u16,
3935    pub code: u32,
3936    pub parameter1: u64,
3937}
3938
3939/// Part of [`HvX64PendingEventMemoryIntercept`]
3940#[bitfield(u8)]
3941#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3942pub struct HvX64PendingEventMemoryInterceptPendingEventHeader {
3943    pub event_pending: bool,
3944    #[bits(3)]
3945    pub event_type: u8,
3946    #[bits(4)]
3947    _reserved0: u8,
3948}
3949
3950/// Part of [`HvX64PendingEventMemoryIntercept`]
3951#[bitfield(u8)]
3952#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3953pub struct HvX64PendingEventMemoryInterceptAccessFlags {
3954    /// Indicates if the guest linear address is valid.
3955    pub guest_linear_address_valid: bool,
3956    /// Indicates that the memory intercept was caused by an access to a guest physical address
3957    /// (instead of a page table as part of a page table walk).
3958    pub caused_by_gpa_access: bool,
3959    #[bits(6)]
3960    _reserved1: u8,
3961}
3962
3963/// Provides information about a memory intercept.
3964#[repr(C)]
3965#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3966pub struct HvX64PendingEventMemoryIntercept {
3967    pub event_header: HvX64PendingEventMemoryInterceptPendingEventHeader,
3968    /// VTL at which the memory intercept is targeted.
3969    /// Note: This field must be in Reg0.
3970    pub target_vtl: u8,
3971    /// Type of the memory access.
3972    pub access_type: HvInterceptAccessType,
3973    pub access_flags: HvX64PendingEventMemoryInterceptAccessFlags,
3974    pub _reserved2: u32,
3975    /// The guest linear address that caused the fault.
3976    pub guest_linear_address: u64,
3977    /// The guest physical address that caused the memory intercept.
3978    pub guest_physical_address: u64,
3979    pub _reserved3: u64,
3980}
3981const_assert!(size_of::<HvX64PendingEventMemoryIntercept>() == 0x20);
3982
3983//
3984// Provides information about pending hypercall output.
3985//
3986#[bitfield(u128)]
3987pub struct HvX64PendingHypercallOutputEvent {
3988    pub event_pending: bool,
3989    #[bits(3)]
3990    pub event_type: u8,
3991    #[bits(4)]
3992    pub reserved0: u8,
3993
3994    // Whether the hypercall has been retired.
3995    pub retired: bool,
3996
3997    #[bits(23)]
3998    pub reserved1: u32,
3999
4000    // Indicates the number of bytes to be written starting from OutputGpa.
4001    pub output_size: u32,
4002
4003    // Indicates the output GPA, which is not required to be page-aligned.
4004    pub output_gpa: u64,
4005}
4006
4007// Provides information about a directly asserted ExtInt.
4008#[bitfield(u128)]
4009pub struct HvX64PendingExtIntEvent {
4010    pub event_pending: bool,
4011    #[bits(3)]
4012    pub event_type: u8,
4013    #[bits(4)]
4014    pub reserved0: u8,
4015    pub vector: u8,
4016    #[bits(48)]
4017    pub reserved1: u64,
4018    pub reserved2: u64,
4019}
4020
4021// Provides information about pending IPT shadowing.
4022#[bitfield(u128)]
4023pub struct HvX64PendingShadowIptEvent {
4024    pub event_pending: bool,
4025    #[bits(4)]
4026    pub event_type: u8,
4027    #[bits(59)]
4028    pub reserved0: u64,
4029
4030    pub reserved1: u64,
4031}
4032
4033#[bitfield(u128)]
4034#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4035pub struct HvX64PendingEventReg0 {
4036    pub event_pending: bool,
4037    #[bits(3)]
4038    pub event_type: u8,
4039    #[bits(4)]
4040    pub reserved: u8,
4041    #[bits(120)]
4042    pub data: u128,
4043}
4044
4045#[repr(C)]
4046#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4047pub struct HvX64PendingEvent {
4048    pub reg_0: HvX64PendingEventReg0,
4049    pub reg_1: AlignedU128,
4050}
4051const_assert!(size_of::<HvX64PendingEvent>() == 0x20);
4052
4053impl From<HvX64PendingExceptionEvent> for HvX64PendingEvent {
4054    fn from(exception_event: HvX64PendingExceptionEvent) -> Self {
4055        HvX64PendingEvent {
4056            reg_0: HvX64PendingEventReg0::from(u128::from(exception_event)),
4057            reg_1: 0u128.into(),
4058        }
4059    }
4060}
4061
4062#[bitfield(u64)]
4063#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4064pub struct HvX64PendingInterruptionRegister {
4065    pub interruption_pending: bool,
4066    #[bits(3)]
4067    pub interruption_type: u8,
4068    pub deliver_error_code: bool,
4069    #[bits(4)]
4070    pub instruction_length: u8,
4071    pub nested_event: bool,
4072    #[bits(6)]
4073    pub reserved: u8,
4074    pub interruption_vector: u16,
4075    pub error_code: u32,
4076}
4077
4078#[bitfield(u64)]
4079#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4080pub struct HvX64InterruptStateRegister {
4081    pub interrupt_shadow: bool,
4082    pub nmi_masked: bool,
4083    #[bits(62)]
4084    pub reserved: u64,
4085}
4086
4087#[bitfield(u64)]
4088#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4089pub struct HvInstructionEmulatorHintsRegister {
4090    /// Indicates whether any secure VTL is enabled for the partition.
4091    pub partition_secure_vtl_enabled: bool,
4092    /// Indicates whether kernel or user execute control architecturally
4093    /// applies to execute accesses.
4094    pub mbec_user_execute_control: bool,
4095    #[bits(62)]
4096    pub _padding: u64,
4097}
4098
4099open_enum! {
4100    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4101    pub enum HvAarch64PendingEventType: u8 {
4102        EXCEPTION = 0,
4103        SYNTHETIC_EXCEPTION = 1,
4104        HYPERCALL_OUTPUT = 2,
4105    }
4106}
4107
4108// Support for bitfield structures.
4109impl HvAarch64PendingEventType {
4110    const fn from_bits(val: u8) -> Self {
4111        HvAarch64PendingEventType(val)
4112    }
4113
4114    const fn into_bits(self) -> u8 {
4115        self.0
4116    }
4117}
4118
4119#[bitfield[u8]]
4120#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4121pub struct HvAarch64PendingEventHeader {
4122    #[bits(1)]
4123    pub event_pending: bool,
4124    #[bits(3)]
4125    pub event_type: HvAarch64PendingEventType,
4126    #[bits(4)]
4127    pub reserved: u8,
4128}
4129
4130#[repr(C)]
4131#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4132pub struct HvAarch64PendingExceptionEvent {
4133    pub header: HvAarch64PendingEventHeader,
4134    pub _padding: [u8; 7],
4135    pub syndrome: u64,
4136    pub fault_address: u64,
4137}
4138
4139#[bitfield[u8]]
4140#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4141pub struct HvAarch64PendingHypercallOutputEventFlags {
4142    #[bits(1)]
4143    pub retired: u8,
4144    #[bits(7)]
4145    pub reserved: u8,
4146}
4147
4148#[repr(C)]
4149#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4150pub struct HvAarch64PendingHypercallOutputEvent {
4151    pub header: HvAarch64PendingEventHeader,
4152    pub flags: HvAarch64PendingHypercallOutputEventFlags,
4153    pub reserved: u16,
4154    pub output_size: u32,
4155    pub output_gpa: u64,
4156}
4157
4158#[repr(C)]
4159#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4160pub struct HvAarch64PendingEvent {
4161    pub header: HvAarch64PendingEventHeader,
4162    pub event_data: [u8; 15],
4163    pub _padding: [u64; 2],
4164}
4165
4166#[bitfield(u32)]
4167#[derive(PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
4168pub struct HvMapGpaFlags {
4169    pub readable: bool,
4170    pub writable: bool,
4171    pub kernel_executable: bool,
4172    pub user_executable: bool,
4173    pub supervisor_shadow_stack: bool,
4174    pub paging_writability: bool,
4175    pub verify_paging_writability: bool,
4176    #[bits(8)]
4177    _padding0: u32,
4178    pub adjustable: bool,
4179    #[bits(16)]
4180    _padding1: u32,
4181}
4182
4183/// [`HvMapGpaFlags`] with no permissions set
4184pub const HV_MAP_GPA_PERMISSIONS_NONE: HvMapGpaFlags = HvMapGpaFlags::new();
4185pub const HV_MAP_GPA_PERMISSIONS_ALL: HvMapGpaFlags = HvMapGpaFlags::new()
4186    .with_readable(true)
4187    .with_writable(true)
4188    .with_kernel_executable(true)
4189    .with_user_executable(true);
4190
4191#[repr(C)]
4192#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4193pub struct HvMonitorPage {
4194    pub trigger_state: HvMonitorTriggerState,
4195    pub reserved1: u32,
4196    pub trigger_group: [HvMonitorTriggerGroup; 4],
4197    pub reserved2: [u64; 3],
4198    pub next_check_time: [[u32; 32]; 4],
4199    pub latency: [[u16; 32]; 4],
4200    pub reserved3: [u64; 32],
4201    pub parameter: [[HvMonitorParameter; 32]; 4],
4202    pub reserved4: [u8; 1984],
4203}
4204
4205#[repr(C)]
4206#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4207pub struct HvMonitorPageSmall {
4208    pub trigger_state: HvMonitorTriggerState,
4209    pub reserved1: u32,
4210    pub trigger_group: [HvMonitorTriggerGroup; 4],
4211}
4212
4213#[repr(C)]
4214#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4215pub struct HvMonitorTriggerGroup {
4216    pub pending: u32,
4217    pub armed: u32,
4218}
4219
4220#[repr(C)]
4221#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4222pub struct HvMonitorParameter {
4223    pub connection_id: u32,
4224    pub flag_number: u16,
4225    pub reserved: u16,
4226}
4227
4228#[bitfield(u32)]
4229#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4230pub struct HvMonitorTriggerState {
4231    #[bits(4)]
4232    pub group_enable: u32,
4233    #[bits(28)]
4234    pub reserved: u32,
4235}
4236
4237#[bitfield(u64)]
4238#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4239pub struct HvPmTimerInfo {
4240    #[bits(16)]
4241    pub port: u16,
4242    #[bits(1)]
4243    pub width_24: bool,
4244    #[bits(1)]
4245    pub enabled: bool,
4246    #[bits(14)]
4247    pub reserved1: u32,
4248    #[bits(32)]
4249    pub reserved2: u32,
4250}
4251
4252#[bitfield(u64)]
4253#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4254pub struct HvX64RegisterSevControl {
4255    pub enable_encrypted_state: bool,
4256    #[bits(11)]
4257    _rsvd1: u64,
4258    #[bits(52)]
4259    pub vmsa_gpa_page_number: u64,
4260}
4261
4262#[bitfield(u64)]
4263#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4264pub struct HvX64RegisterSevAvic {
4265    pub enable_secure_apic: bool,
4266    #[bits(11)]
4267    _rsvd1: u64,
4268    #[bits(52)]
4269    pub avic_gpa_page_number: u64,
4270}
4271
4272#[bitfield(u64)]
4273#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4274pub struct HvRegisterReferenceTsc {
4275    pub enable: bool,
4276    #[bits(11)]
4277    pub reserved_p: u64,
4278    #[bits(52)]
4279    pub gpn: u64,
4280}
4281
4282#[repr(C)]
4283#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4284pub struct HvReferenceTscPage {
4285    pub tsc_sequence: u32,
4286    pub reserved1: u32,
4287    pub tsc_scale: u64,
4288    pub tsc_offset: i64,
4289    pub timeline_bias: u64,
4290    pub tsc_multiplier: u64,
4291    pub reserved2: [u64; 507],
4292}
4293
4294pub const HV_REFERENCE_TSC_SEQUENCE_INVALID: u32 = 0;
4295
4296#[bitfield(u64)]
4297#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4298pub struct HvX64VmgexitInterceptMessageFlags {
4299    pub ghcb_page_valid: bool,
4300    pub ghcb_request_error: bool,
4301    #[bits(62)]
4302    _reserved: u64,
4303}
4304
4305#[repr(C)]
4306#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4307pub struct HvX64VmgexitInterceptMessageGhcbPageStandard {
4308    pub ghcb_protocol_version: u16,
4309    _reserved: [u16; 3],
4310    pub sw_exit_code: u64,
4311    pub sw_exit_info1: u64,
4312    pub sw_exit_info2: u64,
4313    pub sw_scratch: u64,
4314}
4315
4316#[repr(C)]
4317#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4318pub struct HvX64VmgexitInterceptMessageGhcbPage {
4319    pub ghcb_usage: u32,
4320    _reserved: u32,
4321    pub standard: HvX64VmgexitInterceptMessageGhcbPageStandard,
4322}
4323
4324#[repr(C)]
4325#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4326pub struct HvX64VmgexitInterceptMessage {
4327    pub header: HvX64InterceptMessageHeader,
4328    pub ghcb_msr: u64,
4329    pub flags: HvX64VmgexitInterceptMessageFlags,
4330    pub ghcb_page: HvX64VmgexitInterceptMessageGhcbPage,
4331}
4332
4333impl MessagePayload for HvX64VmgexitInterceptMessage {}
4334
4335#[bitfield(u32)]
4336#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4337pub struct HvX64GpaAttributeInterceptMessageFlags {
4338    #[bits(5)]
4339    pub range_count: u32,
4340    pub adjust: bool,
4341    #[bits(2)]
4342    pub host_visibility: u32,
4343    #[bits(6)]
4344    pub memory_type: u32,
4345    #[bits(18)]
4346    _reserved: u32,
4347}
4348
4349#[repr(C)]
4350#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4351pub struct HvX64GpaAttributeInterceptMessage {
4352    pub vp_index: u32,
4353    pub flags: HvX64GpaAttributeInterceptMessageFlags,
4354    pub ranges: [hypercall::HvGpaRange; 29],
4355}
4356
4357impl MessagePayload for HvX64GpaAttributeInterceptMessage {}
4358const_assert!(size_of::<HvX64GpaAttributeInterceptMessage>() == HV_MESSAGE_PAYLOAD_SIZE);
4359
4360#[bitfield(u64)]
4361pub struct HvRegisterVpAssistPage {
4362    pub enabled: bool,
4363    #[bits(11)]
4364    _reserved: u64,
4365    #[bits(52)]
4366    pub gpa_page_number: u64,
4367}
4368
4369#[bitfield(u32)]
4370#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4371pub struct HvX64RegisterPageDirtyFlags {
4372    pub general_purpose: bool,
4373    pub instruction_pointer: bool,
4374    pub xmm: bool,
4375    pub segments: bool,
4376    pub flags: bool,
4377    #[bits(27)]
4378    reserved: u32,
4379}
4380
4381#[repr(C)]
4382#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4383pub struct HvX64RegisterPage {
4384    pub version: u16,
4385    pub is_valid: u8,
4386    pub vtl: u8,
4387    pub dirty: HvX64RegisterPageDirtyFlags,
4388    /// General-purpose registers. These are in the order defined by the x86-64
4389    /// architecture.
4390    pub gp_registers: [u64; 16],
4391    pub rip: u64,
4392    pub rflags: u64,
4393    pub reserved: u64,
4394    pub xmm: [u128; 6],
4395    pub segment: [HvX64SegmentRegister; 6],
4396    // Misc. control registers (cannot be set via this interface).
4397    pub cr0: u64,
4398    pub cr3: u64,
4399    pub cr4: u64,
4400    pub cr8: u64,
4401    pub efer: u64,
4402    pub dr7: u64,
4403    pub pending_interruption: HvX64PendingInterruptionRegister,
4404    pub interrupt_state: HvX64InterruptStateRegister,
4405    pub instruction_emulation_hints: HvInstructionEmulatorHintsRegister,
4406    pub reserved_end: [u8; 3672],
4407}
4408
4409const _: () = assert!(size_of::<HvX64RegisterPage>() == HV_PAGE_SIZE_USIZE);
4410
4411#[bitfield(u32)]
4412#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
4413pub struct HvAarch64RegisterPageDirtyFlags {
4414    _unused: bool,
4415    pub instruction_pointer: bool,
4416    pub processor_state: bool,
4417    pub control_registers: bool,
4418    #[bits(28)]
4419    reserved: u32,
4420}
4421
4422#[repr(C)]
4423#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
4424pub struct HvAarch64RegisterPage {
4425    pub version: u16,
4426    pub is_valid: u8,
4427    pub vtl: u8,
4428    pub dirty: HvAarch64RegisterPageDirtyFlags,
4429    // Reserved.
4430    pub _rsvd: [u64; 33],
4431    // Instruction pointer.
4432    pub pc: u64,
4433    // Processor state.
4434    pub cpsr: u64,
4435    // Control registers.
4436    pub sctlr_el1: u64,
4437    pub tcr_el1: u64,
4438    // Reserved.
4439    pub reserved_end: [u8; 3792],
4440}
4441
4442const _: () = assert!(size_of::<HvAarch64RegisterPage>() == HV_PAGE_SIZE_USIZE);
4443
4444#[bitfield(u64)]
4445pub struct HvRegisterVsmWpWaitForTlbLock {
4446    pub wait: bool,
4447    #[bits(63)]
4448    _reserved: u64,
4449}
4450
4451#[bitfield(u64)]
4452pub struct HvRegisterVsmVpSecureVtlConfig {
4453    pub mbec_enabled: bool,
4454    pub tlb_locked: bool,
4455    pub supervisor_shadow_stack_enabled: bool,
4456    pub hardware_hvpt_enabled: bool,
4457    #[bits(60)]
4458    _reserved: u64,
4459}
4460
4461#[bitfield(u64)]
4462pub struct HvRegisterCrInterceptControl {
4463    pub cr0_write: bool,
4464    pub cr4_write: bool,
4465    pub xcr0_write: bool,
4466    pub ia32_misc_enable_read: bool,
4467    pub ia32_misc_enable_write: bool,
4468    pub msr_lstar_read: bool,
4469    pub msr_lstar_write: bool,
4470    pub msr_star_read: bool,
4471    pub msr_star_write: bool,
4472    pub msr_cstar_read: bool,
4473    pub msr_cstar_write: bool,
4474    pub apic_base_msr_read: bool,
4475    pub apic_base_msr_write: bool,
4476    pub msr_efer_read: bool,
4477    pub msr_efer_write: bool,
4478    pub gdtr_write: bool,
4479    pub idtr_write: bool,
4480    pub ldtr_write: bool,
4481    pub tr_write: bool,
4482    pub msr_sysenter_cs_write: bool,
4483    pub msr_sysenter_eip_write: bool,
4484    pub msr_sysenter_esp_write: bool,
4485    pub msr_sfmask_write: bool,
4486    pub msr_tsc_aux_write: bool,
4487    pub msr_sgx_launch_control_write: bool,
4488    pub msr_xss_write: bool,
4489    pub msr_scet_write: bool,
4490    pub msr_pls_ssp_write: bool,
4491    pub msr_interrupt_ssp_table_addr_write: bool,
4492    #[bits(35)]
4493    _rsvd_z: u64,
4494}
4495
4496#[repr(C)]
4497#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
4498pub struct HvX64InterruptControllerState {
4499    pub apic_id: u32,
4500    pub apic_version: u32,
4501    pub apic_ldr: u32,
4502    pub apic_dfr: u32,
4503    pub apic_spurious: u32,
4504    pub apic_isr: [u32; 8],
4505    pub apic_tmr: [u32; 8],
4506    pub apic_irr: [u32; 8],
4507    pub apic_esr: u32,
4508    pub apic_icr_high: u32,
4509    pub apic_icr_low: u32,
4510    pub apic_lvt_timer: u32,
4511    pub apic_lvt_thermal: u32,
4512    pub apic_lvt_perfmon: u32,
4513    pub apic_lvt_lint0: u32,
4514    pub apic_lvt_lint1: u32,
4515    pub apic_lvt_error: u32,
4516    pub apic_lvt_cmci: u32,
4517    pub apic_error_status: u32,
4518    pub apic_initial_count: u32,
4519    pub apic_counter_value: u32,
4520    pub apic_divide_configuration: u32,
4521    pub apic_remote_read: u32,
4522}