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