1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
// Copyright 2018 Cloudbase Solutions Srl
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]

use common::*;

pub type WHV_PARTITION_HANDLE = *mut VOID;

pub type WHV_GUEST_PHYSICAL_ADDRESS = UINT64;
pub type WHV_GUEST_VIRTUAL_ADDRESS = UINT64;

pub const WHV_E_INSUFFICIENT_BUFFER: HRESULT = -2143878399; // 0x80370301
pub const WHV_E_INVALID_PARTITION_CONFIG: HRESULT = -2143878396; // 0x80370304
pub const WHV_E_GPA_RANGE_NOT_FOUND: HRESULT = -2143878395; // 0x80370305

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_PARTITION_PROPERTY_CODE {
    WHvPartitionPropertyCodeExtendedVmExits = 0x00000001,
    WHvPartitionPropertyCodeExceptionExitBitmap = 0x00000002,
    WHvPartitionPropertyCodeProcessorFeatures = 0x00001001,
    WHvPartitionPropertyCodeProcessorClFlushSize = 0x00001002,
    WHvPartitionPropertyCodeCpuidExitList = 0x00001003,
    WHvPartitionPropertyCodeCpuidResultList = 0x00001004,
    WHvPartitionPropertyCodeProcessorCount = 0x00001fff,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_CAPABILITY_CODE {
    // Capabilities of the API implementation
    WHvCapabilityCodeHypervisorPresent = 0x00000000,
    WHvCapabilityCodeFeatures = 0x00000001,
    WHvCapabilityCodeExtendedVmExits = 0x00000002,
    WHvCapabilityCodeExceptionExitBitmap = 0x00000003,

    // Capabilities of the system's processor
    WHvCapabilityCodeProcessorVendor = 0x00001000,
    WHvCapabilityCodeProcessorFeatures = 0x00001001,
    WHvCapabilityCodeProcessorClFlushSize = 0x00001002,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_PROCESSOR_VENDOR {
    WHvProcessorVendorAmd = 0x0000,
    WHvProcessorVendorIntel = 0x0001,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_RUN_VP_EXIT_REASON {
    WHvRunVpExitReasonNone = 0x00000000,

    // Standard exits caused by operations of the virtual processor
    WHvRunVpExitReasonMemoryAccess = 0x00000001,
    WHvRunVpExitReasonX64IoPortAccess = 0x00000002,
    WHvRunVpExitReasonUnrecoverableException = 0x00000004,
    WHvRunVpExitReasonInvalidVpRegisterValue = 0x00000005,
    WHvRunVpExitReasonUnsupportedFeature = 0x00000006,
    WHvRunVpExitReasonX64InterruptWindow = 0x00000007,
    WHvRunVpExitReasonX64Halt = 0x00000008,

    // Additional exits that can be configured through partition properties
    WHvRunVpExitReasonX64MsrAccess = 0x00001000,
    WHvRunVpExitReasonX64Cpuid = 0x00001001,
    WHvRunVpExitReasonException = 0x00001002,

    // Exits caused by the host
    WHvRunVpExitReasonCanceled = 0x00002001,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_X64_PENDING_INTERRUPTION_TYPE {
    WHvX64PendingInterrupt = 0,
    WHvX64PendingNmi = 2,
    WHvX64PendingException = 3,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_X64_UNSUPPORTED_FEATURE_CODE {
    WHvUnsupportedFeatureIntercept = 1,
    WHvUnsupportedFeatureTaskSwitchTss = 2,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_RUN_VP_CANCEL_REASON {
    WhvRunVpCancelReasonUser = 0, // Execution canceled by HvCancelRunVirtualProcessor
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_REGISTER_NAME {
    // X64 General purpose registers
    WHvX64RegisterRax = 0x00000000,
    WHvX64RegisterRcx = 0x00000001,
    WHvX64RegisterRdx = 0x00000002,
    WHvX64RegisterRbx = 0x00000003,
    WHvX64RegisterRsp = 0x00000004,
    WHvX64RegisterRbp = 0x00000005,
    WHvX64RegisterRsi = 0x00000006,
    WHvX64RegisterRdi = 0x00000007,
    WHvX64RegisterR8 = 0x00000008,
    WHvX64RegisterR9 = 0x00000009,
    WHvX64RegisterR10 = 0x0000000A,
    WHvX64RegisterR11 = 0x0000000B,
    WHvX64RegisterR12 = 0x0000000C,
    WHvX64RegisterR13 = 0x0000000D,
    WHvX64RegisterR14 = 0x0000000E,
    WHvX64RegisterR15 = 0x0000000F,
    WHvX64RegisterRip = 0x00000010,
    WHvX64RegisterRflags = 0x00000011,

    // X64 Segment registers
    WHvX64RegisterEs = 0x00000012,
    WHvX64RegisterCs = 0x00000013,
    WHvX64RegisterSs = 0x00000014,
    WHvX64RegisterDs = 0x00000015,
    WHvX64RegisterFs = 0x00000016,
    WHvX64RegisterGs = 0x00000017,
    WHvX64RegisterLdtr = 0x00000018,
    WHvX64RegisterTr = 0x00000019,

    // X64 Table registers
    WHvX64RegisterIdtr = 0x0000001A,
    WHvX64RegisterGdtr = 0x0000001B,

    // X64 Control Registers
    WHvX64RegisterCr0 = 0x0000001C,
    WHvX64RegisterCr2 = 0x0000001D,
    WHvX64RegisterCr3 = 0x0000001E,
    WHvX64RegisterCr4 = 0x0000001F,
    WHvX64RegisterCr8 = 0x00000020,

    // X64 Debug Registers
    WHvX64RegisterDr0 = 0x00000021,
    WHvX64RegisterDr1 = 0x00000022,
    WHvX64RegisterDr2 = 0x00000023,
    WHvX64RegisterDr3 = 0x00000024,
    WHvX64RegisterDr6 = 0x00000025,
    WHvX64RegisterDr7 = 0x00000026,

    // X64 Floating Point and Vector Registers
    WHvX64RegisterXmm0 = 0x00001000,
    WHvX64RegisterXmm1 = 0x00001001,
    WHvX64RegisterXmm2 = 0x00001002,
    WHvX64RegisterXmm3 = 0x00001003,
    WHvX64RegisterXmm4 = 0x00001004,
    WHvX64RegisterXmm5 = 0x00001005,
    WHvX64RegisterXmm6 = 0x00001006,
    WHvX64RegisterXmm7 = 0x00001007,
    WHvX64RegisterXmm8 = 0x00001008,
    WHvX64RegisterXmm9 = 0x00001009,
    WHvX64RegisterXmm10 = 0x0000100A,
    WHvX64RegisterXmm11 = 0x0000100B,
    WHvX64RegisterXmm12 = 0x0000100C,
    WHvX64RegisterXmm13 = 0x0000100D,
    WHvX64RegisterXmm14 = 0x0000100E,
    WHvX64RegisterXmm15 = 0x0000100F,
    WHvX64RegisterFpMmx0 = 0x00001010,
    WHvX64RegisterFpMmx1 = 0x00001011,
    WHvX64RegisterFpMmx2 = 0x00001012,
    WHvX64RegisterFpMmx3 = 0x00001013,
    WHvX64RegisterFpMmx4 = 0x00001014,
    WHvX64RegisterFpMmx5 = 0x00001015,
    WHvX64RegisterFpMmx6 = 0x00001016,
    WHvX64RegisterFpMmx7 = 0x00001017,
    WHvX64RegisterFpControlStatus = 0x00001018,
    WHvX64RegisterXmmControlStatus = 0x00001019,

    // X64 MSRs
    WHvX64RegisterTsc = 0x00002000,
    WHvX64RegisterEfer = 0x00002001,
    WHvX64RegisterKernelGsBase = 0x00002002,
    WHvX64RegisterApicBase = 0x00002003,
    WHvX64RegisterPat = 0x00002004,
    WHvX64RegisterSysenterCs = 0x00002005,
    WHvX64RegisterSysenterEip = 0x00002006,
    WHvX64RegisterSysenterEsp = 0x00002007,
    WHvX64RegisterStar = 0x00002008,
    WHvX64RegisterLstar = 0x00002009,
    WHvX64RegisterCstar = 0x0000200A,
    WHvX64RegisterSfmask = 0x0000200B,

    WHvX64RegisterMsrMtrrCap = 0x0000200D,
    WHvX64RegisterMsrMtrrDefType = 0x0000200E,

    WHvX64RegisterMsrMtrrPhysBase0 = 0x00002010,
    WHvX64RegisterMsrMtrrPhysBase1 = 0x00002011,
    WHvX64RegisterMsrMtrrPhysBase2 = 0x00002012,
    WHvX64RegisterMsrMtrrPhysBase3 = 0x00002013,
    WHvX64RegisterMsrMtrrPhysBase4 = 0x00002014,
    WHvX64RegisterMsrMtrrPhysBase5 = 0x00002015,
    WHvX64RegisterMsrMtrrPhysBase6 = 0x00002016,
    WHvX64RegisterMsrMtrrPhysBase7 = 0x00002017,
    WHvX64RegisterMsrMtrrPhysBase8 = 0x00002018,
    WHvX64RegisterMsrMtrrPhysBase9 = 0x00002019,
    WHvX64RegisterMsrMtrrPhysBaseA = 0x0000201A,
    WHvX64RegisterMsrMtrrPhysBaseB = 0x0000201B,
    WHvX64RegisterMsrMtrrPhysBaseC = 0x0000201C,
    WHvX64RegisterMsrMtrrPhysBaseD = 0x0000201D,
    WHvX64RegisterMsrMtrrPhysBaseE = 0x0000201E,
    WHvX64RegisterMsrMtrrPhysBaseF = 0x0000201F,

    WHvX64RegisterMsrMtrrPhysMask0 = 0x00002040,
    WHvX64RegisterMsrMtrrPhysMask1 = 0x00002041,
    WHvX64RegisterMsrMtrrPhysMask2 = 0x00002042,
    WHvX64RegisterMsrMtrrPhysMask3 = 0x00002043,
    WHvX64RegisterMsrMtrrPhysMask4 = 0x00002044,
    WHvX64RegisterMsrMtrrPhysMask5 = 0x00002045,
    WHvX64RegisterMsrMtrrPhysMask6 = 0x00002046,
    WHvX64RegisterMsrMtrrPhysMask7 = 0x00002047,
    WHvX64RegisterMsrMtrrPhysMask8 = 0x00002048,
    WHvX64RegisterMsrMtrrPhysMask9 = 0x00002049,
    WHvX64RegisterMsrMtrrPhysMaskA = 0x0000204A,
    WHvX64RegisterMsrMtrrPhysMaskB = 0x0000204B,
    WHvX64RegisterMsrMtrrPhysMaskC = 0x0000204C,
    WHvX64RegisterMsrMtrrPhysMaskD = 0x0000204D,
    WHvX64RegisterMsrMtrrPhysMaskE = 0x0000204E,
    WHvX64RegisterMsrMtrrPhysMaskF = 0x0000204F,

    WHvX64RegisterMsrMtrrFix64k00000 = 0x00002070,
    WHvX64RegisterMsrMtrrFix16k80000 = 0x00002071,
    WHvX64RegisterMsrMtrrFix16kA0000 = 0x00002072,
    WHvX64RegisterMsrMtrrFix4kC0000 = 0x00002073,
    WHvX64RegisterMsrMtrrFix4kC8000 = 0x00002074,
    WHvX64RegisterMsrMtrrFix4kD0000 = 0x00002075,
    WHvX64RegisterMsrMtrrFix4kD8000 = 0x00002076,
    WHvX64RegisterMsrMtrrFix4kE0000 = 0x00002077,
    WHvX64RegisterMsrMtrrFix4kE8000 = 0x00002078,
    WHvX64RegisterMsrMtrrFix4kF0000 = 0x00002079,
    WHvX64RegisterMsrMtrrFix4kF8000 = 0x0000207A,

    WHvX64RegisterTscAux = 0x0000207B,

    // Interrupt / Event Registers
    WHvRegisterPendingInterruption = 0x80000000,
    WHvRegisterInterruptState = 0x80000001,
    WHvRegisterPendingEvent0 = 0x80000002,
    WHvRegisterPendingEvent1 = 0x80000003,
    WHvX64RegisterDeliverabilityNotifications = 0x80000004,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_TRANSLATE_GVA_RESULT_CODE {
    WHvTranslateGvaResultSuccess = 0,

    // Translation failures
    WHvTranslateGvaResultPageNotPresent = 1,
    WHvTranslateGvaResultPrivilegeViolation = 2,
    WHvTranslateGvaResultInvalidPageTableFlags = 3,

    // GPA access failures
    WHvTranslateGvaResultGpaUnmapped = 4,
    WHvTranslateGvaResultGpaNoReadAccess = 5,
    WHvTranslateGvaResultGpaNoWriteAccess = 6,
    WHvTranslateGvaResultGpaIllegalOverlayAccess = 7,
    WHvTranslateGvaResultIntercept = 8,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_EXCEPTION_TYPE {
    WHvX64ExceptionTypeDivideErrorFault = 0x0,
    WHvX64ExceptionTypeDebugTrapOrFault = 0x1,
    WHvX64ExceptionTypeBreakpointTrap = 0x3,
    WHvX64ExceptionTypeOverflowTrap = 0x4,
    WHvX64ExceptionTypeBoundRangeFault = 0x5,
    WHvX64ExceptionTypeInvalidOpcodeFault = 0x6,
    WHvX64ExceptionTypeDeviceNotAvailableFault = 0x7,
    WHvX64ExceptionTypeDoubleFaultAbort = 0x8,
    WHvX64ExceptionTypeInvalidTaskStateSegmentFault = 0x0A,
    WHvX64ExceptionTypeSegmentNotPresentFault = 0x0B,
    WHvX64ExceptionTypeStackFault = 0x0C,
    WHvX64ExceptionTypeGeneralProtectionFault = 0x0D,
    WHvX64ExceptionTypePageFault = 0x0E,
    WHvX64ExceptionTypeFloatingPointErrorFault = 0x10,
    WHvX64ExceptionTypeAlignmentCheckFault = 0x11,
    WHvX64ExceptionTypeMachineCheckAbort = 0x12,
    WHvX64ExceptionTypeSimdFloatingPointFault = 0x13,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WHV_MEMORY_ACCESS_TYPE {
    WHvMemoryAccessRead = 0,
    WHvMemoryAccessWrite = 1,
    WHvMemoryAccessExecute = 2,
}

bitflags! {
    #[repr(C)]
    pub struct WHV_TRANSLATE_GVA_FLAGS: UINT32 {
        const WHvTranslateGvaFlagNone = 0x00000000;
        const WHvTranslateGvaFlagValidateRead = 0x00000001;
        const WHvTranslateGvaFlagValidateWrite = 0x00000002;
        const WHvTranslateGvaFlagValidateExecute = 0x00000004;
        const WHvTranslateGvaFlagPrivilegeExempt = 0x00000008;
        const WHvTranslateGvaFlagSetPageTableBits = 0x00000010;
    }
}

bitflags! {
    #[repr(C)]
    pub struct WHV_MAP_GPA_RANGE_FLAGS: UINT32  {
        const WHvMapGpaRangeFlagNone = 0x00000000;
        const WHvMapGpaRangeFlagRead = 0x00000001;
        const WHvMapGpaRangeFlagWrite = 0x00000002;
        const WHvMapGpaRangeFlagExecute = 0x00000004;
    }
}

#[allow(non_snake_case)]
#[derive(Copy, Clone)]
#[repr(C)]
pub union WHV_CAPABILITY {
    pub HypervisorPresent: BOOL,
    pub Features: WHV_CAPABILITY_FEATURES,
    pub ExtendedVmExits: WHV_EXTENDED_VM_EXITS,
    pub ProcessorVendor: WHV_PROCESSOR_VENDOR,
    pub ProcessorFeatures: WHV_PROCESSOR_FEATURES,
    pub ProcessorClFlushSize: UINT8,
    pub ExceptionExitBitmap: UINT64,
}

#[allow(non_snake_case)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct WHV_X64_CPUID_RESULT {
    pub Function: UINT32,
    pub Reserved: [UINT32; 3],
    pub Eax: UINT32,
    pub Ebx: UINT32,
    pub Ecx: UINT32,
    pub Edx: UINT32,
}

#[allow(non_snake_case)]
#[repr(C)]
pub union WHV_PARTITION_PROPERTY {
    pub ExtendedVmExits: WHV_EXTENDED_VM_EXITS,
    pub ProcessorFeatures: WHV_PROCESSOR_FEATURES,
    pub ProcessorClFlushSize: UINT8,
    pub ProcessorCount: UINT32,
    pub CpuidExitList: [UINT32; 1],
    pub CpuidResultList: [WHV_X64_CPUID_RESULT; 1],
    pub ExceptionExitBitmap: UINT64,
}

#[allow(non_snake_case)]
#[derive(Copy, Clone)]
#[repr(C)]
pub struct WHV_CAPABILITY_FEATURES {
    pub AsUINT64: UINT64,
}

bitfield!(WHV_CAPABILITY_FEATURES AsUINT64: UINT64 [
    Reserved set_Reserved[0..64],
]);

#[allow(non_snake_case)]
#[derive(Copy, Clone)]
#[repr(C)]
pub struct WHV_EXTENDED_VM_EXITS {
    pub AsUINT64: UINT64,
}

bitfield!(WHV_EXTENDED_VM_EXITS AsUINT64: UINT64 [
    X64CpuidExit set_X64CpuidExit[0..1],
    X64MsrExit set_X64MsrExit[1..2],
    ExceptionExit set_ExceptionExit[2..3],
    Reserved set_Reserved[4..64],
]);

#[allow(non_snake_case)]
#[derive(Copy, Clone)]
#[repr(C)]
pub struct WHV_PROCESSOR_FEATURES {
    pub AsUINT64: UINT64,
}

bitfield!(WHV_PROCESSOR_FEATURES AsUINT64: UINT64 [
    Sse3Support set_Sse3Support[0..1],
    LahfSahfSupport set_LahfSahfSupport[1..2],
    Ssse3Support set_Ssse3Support[2..3],
    Sse4_1Support set_Sse4_1Support[3..4],
    Sse4_2Support set_Sse4_2Support[4..5],
    Sse4aSupport set_Sse4aSupport[5..6],
    XopSupport set_XopSupport[6..7],
    PopCntSupport set_PopCntSupport[7..8],
    Cmpxchg16bSupport set_Cmpxchg16bSupport[8..9],
    Altmovcr8Support set_Altmovcr8Support[9..10],
    LzcntSupport set_LzcntSupport[10..11],
    MisAlignSseSupport set_MisAlignSseSupport[11..12],
    MmxExtSupport set_MmxExtSupport[12..13],
    Amd3DNowSupport set_Amd3DNowSupport[13..14],
    ExtendedAmd3DNowSupport set_ExtendedAmd3DNowSupport[14..15],
    Page1GbSupport set_Page1GbSupport[15..16],
    AesSupport set_AesSupport[16..17],
    PclmulqdqSupport set_PclmulqdqSupport[17..18],
    PcidSupport set_PcidSupport[18..19],
    Fma4Support set_Fma4Support[19..20],
    F16CSupport set_F16CSupport[20..21],
    RdRandSupport set_RdRandSupport[21..22],
    RdWrFsGsSupport set_RdWrFsGsSupport[22..23],
    SmepSupport set_SmepSupport[23..24],
    EnhancedFastStringSupport set_EnhancedFastStringSupport[24..25],
    Bmi1Support set_Bmi1Support[25..26],
    Bmi2Support set_Bmi2Support[26..27],
    Reserved1 set_Reserved1[27..28],
    MovbeSupport set_MovbeSupport[28..29],
    Npiep1Support set_Npiep1Support[29..30],
    DepX87FPUSaveSupport set_DepX87FPUSaveSupport[30..31],
    RdSeedSupport set_RdSeedSupportp[31..32],
    AdxSupport set_AdxSupport[32..33],
    IntelPrefetchSupport set_IntelPrefetchSupport[33..34],
    SmapSupport set_SmapSupport[34..35],
    HleSupport set_HleSupport[35..36],
    RtmSupport set_RtmSupport[36..37],
    RdtscpSupport set_RdtscpSupport[37..38],
    ClflushoptSupport set_ClflushoptSupport[38..39],
    ClwbSupport set_ClwbSupport[39..40],
    ShaSupport set_ShaSupport[40..41],
    X87PointersSavedSupport set_X87PointersSavedSupport[41..42],
    Reserved2 set_Reserved2[42..64],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_SEGMENT_REGISTER {
    pub Base: UINT64,
    pub Limit: UINT32,
    pub Selector: UINT16,
    pub Attributes: UINT16,
}

bitfield!(WHV_X64_SEGMENT_REGISTER Attributes: UINT16 [
    SegmentType set_SegmentType[0..4],
    NonSystemSegment set_NonSystemSegment[4..5],
    DescriptorPrivilegeLevel set_DescriptorPrivilegeLevel[5..7],
    Present set_Present[7..8],
    Reserved set_Reserved[8..12],
    Available set_Available[12..13],
    Long set_Long[13..14],
    Default set_Default[14..15],
    Granularity set_Granularity[15..16],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_TABLE_REGISTER {
    pub Pad: [UINT16; 3],
    pub Limit: UINT16,
    pub Base: UINT64,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_VP_EXECUTION_STATE {
    pub AsUINT16: UINT16,
}

bitfield!(WHV_X64_VP_EXECUTION_STATE AsUINT16: UINT16[
    Cpl set_Cpl[0..2],
    Cr0Pe set_Cr0Pe[2..3],
    Cr0Am set_Cr0Am[3..4],
    EferLma set_EferLma[4..5],
    DebugActive set_DebugActive[5..6],
    InterruptionPending set_InterruptionPending[6..7],
    Reserved0 set_Reserved0[7..12],
    InterruptShadow set_InterruptShadow[12..13],
    Reserved1 set_Reserved1[13..16],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_VP_EXIT_CONTEXT {
    pub ExecutionState: WHV_X64_VP_EXECUTION_STATE,
    // Rust doesn't support bit fields so InstructionLength (4 bits) and Cr8 (4 bits)
    // are combined here
    pub InstructionLengthCr8: UINT8,
    pub Reserved: UINT8,
    pub Reserved2: UINT32,
    pub Cs: WHV_X64_SEGMENT_REGISTER,
    pub Rip: UINT64,
    pub Rflags: UINT64,
}

bitfield!(WHV_VP_EXIT_CONTEXT InstructionLengthCr8: UINT8[
    InstructionLength set_InstructionLength[0..4],
    Cr8 set_Cr8[4..8],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_MEMORY_ACCESS_INFO {
    pub AsUINT32: UINT32,
}

bitfield!(WHV_MEMORY_ACCESS_INFO  AsUINT32: UINT32[
    // WHV_MEMORY_ACCESS_TYPE
    AccessType set_AccessType[0..2],
    GpaUnmapped set_GpaUnmapped[2..3],
    GvaValid set_GvaValid[3..4],
    Reserved set_Reserved[4..32],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_MEMORY_ACCESS_CONTEXT {
    // Context of the virtual processor
    pub InstructionByteCount: UINT8,
    pub Reserved: [UINT8; 3],
    pub InstructionBytes: [UINT8; 16],

    // Memory access info
    pub AccessInfo: WHV_MEMORY_ACCESS_INFO,
    pub Gpa: WHV_GUEST_PHYSICAL_ADDRESS,
    pub Gva: WHV_GUEST_VIRTUAL_ADDRESS,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_IO_PORT_ACCESS_INFO {
    pub AsUINT32: UINT32,
}

bitfield!(WHV_X64_IO_PORT_ACCESS_INFO AsUINT32: UINT32[
    IsWrite set_IsWrite[0..1],
    AccessSize set_AccessSize[1..4],
    StringOp set_StringOp[4..5],
    RepPrefix set_RepPrefix[5..6],
    Reserved set_Reserved[6..32],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_IO_PORT_ACCESS_CONTEXT {
    // Context of the virtual processor
    pub InstructionByteCount: UINT8,
    pub Reserved: [UINT8; 3],
    pub InstructionBytes: [UINT8; 16],

    // I/O port access info
    pub AccessInfo: WHV_X64_IO_PORT_ACCESS_INFO,
    pub PortNumber: UINT16,
    pub Reserved2: [UINT16; 3],
    pub Rax: UINT64,
    pub Rcx: UINT64,
    pub Rsi: UINT64,
    pub Rdi: UINT64,
    pub Ds: WHV_X64_SEGMENT_REGISTER,
    pub Es: WHV_X64_SEGMENT_REGISTER,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_MSR_ACCESS_INFO {
    pub AsUINT32: UINT32,
}

bitfield!(WHV_X64_MSR_ACCESS_INFO AsUINT32: UINT32[
    IsWrite set_IsWrite[0..1],
    Reserved set_Reserved[1..32],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_MSR_ACCESS_CONTEXT {
    // MSR access info
    pub AccessInfo: WHV_X64_MSR_ACCESS_INFO,
    pub MsrNumber: UINT32,
    pub Rax: UINT64,
    pub Rdx: UINT64,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_CPUID_ACCESS_CONTEXT {
    // CPUID access info
    pub Rax: UINT64,
    pub Rcx: UINT64,
    pub Rdx: UINT64,
    pub Rbx: UINT64,
    pub DefaultResultRax: UINT64,
    pub DefaultResultRcx: UINT64,
    pub DefaultResultRdx: UINT64,
    pub DefaultResultRbx: UINT64,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_VP_EXCEPTION_INFO {
    pub AsUINT32: UINT32,
}

bitfield!(WHV_VP_EXCEPTION_INFO AsUINT32: UINT32[
    ErrorCodeValid set_ErrorCodeValid[0..1],
    SoftwareException set_SoftwareException[1..2],
    Reserved set_Reserved[2..32],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_VP_EXCEPTION_CONTEXT {
    pub InstructionByteCount: UINT8,
    pub Reserved: [UINT8; 3],
    pub InstructionBytes: [UINT8; 16],

    // Exception info
    pub ExceptionInfo: WHV_VP_EXCEPTION_INFO,
    // WHV_EXCEPTION_TYPE
    pub ExceptionType: UINT8,
    pub Reserved2: [UINT8; 3],
    pub ErrorCode: UINT32,
    pub ExceptionParameter: UINT64,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_INTERRUPTION_DELIVERABLE_CONTEXT {
    pub DeliverableType: WHV_X64_PENDING_INTERRUPTION_TYPE,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_UNSUPPORTED_FEATURE_CONTEXT {
    pub FeatureCode: WHV_X64_UNSUPPORTED_FEATURE_CODE,
    pub Reserved: UINT32,
    pub FeatureParameter: UINT64,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_RUN_VP_CANCELED_CONTEXT {
    pub CancelReason: WHV_RUN_VP_CANCEL_REASON,
}

#[derive(Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub union WHV_RUN_VP_EXIT_CONTEXT_anon_union {
    pub MemoryAccess: WHV_MEMORY_ACCESS_CONTEXT,
    pub IoPortAccess: WHV_X64_IO_PORT_ACCESS_CONTEXT,
    pub MsrAccess: WHV_X64_MSR_ACCESS_CONTEXT,
    pub CpuidAccess: WHV_X64_CPUID_ACCESS_CONTEXT,
    pub VpException: WHV_VP_EXCEPTION_CONTEXT,
    pub InterruptWindow: WHV_X64_INTERRUPTION_DELIVERABLE_CONTEXT,
    pub UnsupportedFeature: WHV_X64_UNSUPPORTED_FEATURE_CONTEXT,
    pub CancelReason: WHV_RUN_VP_CANCELED_CONTEXT,
}

#[derive(Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_RUN_VP_EXIT_CONTEXT {
    pub ExitReason: WHV_RUN_VP_EXIT_REASON,
    pub Reserved: UINT32,
    pub VpContext: WHV_VP_EXIT_CONTEXT,
    pub anon_union: WHV_RUN_VP_EXIT_CONTEXT_anon_union,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_UINT128 {
    pub Low64: UINT64,
    pub High64: UINT64,
    // Original type is a union that includes also:
    // UINT32  Dword[4];
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_INTERRUPT_STATE_REGISTER {
    AsUINT64: UINT64,
}

bitfield!(WHV_X64_INTERRUPT_STATE_REGISTER AsUINT64: UINT64[
    InterruptShadow set_InterruptShadow[0..1],
    NmiMasked set_NmiMasked[1..2],
    Reserved set_Reserved[2..64],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_PENDING_INTERRUPTION_REGISTER {
    AsUINT64: UINT64,
}

bitfield!(WHV_X64_PENDING_INTERRUPTION_REGISTER AsUINT64: UINT64[
    InterruptionPending set_InterruptionPending[0..1],
    // WHV_X64_PENDING_INTERRUPTION_TYPE
    InterruptionType set_InterruptionType[1..4],
    DeliverErrorCode set_DeliverErrorCode[4..5],
    InstructionLength set_InstructionLength[5..9],
    NestedEvent set_NestedEvent[9..10],
    Reserved set_Reserved[10..16],
    InterruptionVector set_InterruptionVector[16..32],
    ErrorCode set_ErrorCode[32..64],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER {
    AsUINT64: UINT64,
}

bitfield!(WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER AsUINT64: UINT64[
    NmiNotification set_NmiNotification[0..1],
    InterruptNotification set_InterruptNotification[1..2],
    InterruptPriority set_InterruptPriority[2..6],
    Reserved set_Reserved[6..64],
]);

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_FP_REGISTER {
    AsUINT128: WHV_UINT128,
    // TODO: add bitfields
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_FP_CONTROL_STATUS_REGISTER_32bit_mode_anon_struct {
    LastFpEip: UINT32,
    LastFpCs: UINT16,
    Reserved2: UINT16,
}

#[derive(Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub union WHV_X64_FP_CONTROL_STATUS_REGISTER_anon_union {
    LastFpRip: UINT64,
    anon_struct: WHV_X64_FP_CONTROL_STATUS_REGISTER_32bit_mode_anon_struct,
}

#[derive(Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_FP_CONTROL_STATUS_REGISTER_anon_struct {
    FpControl: UINT16,
    FpStatus: UINT16,
    FpTag: UINT8,
    Reserved: UINT8,
    LastFpOp: UINT16,
    anon_union: WHV_X64_FP_CONTROL_STATUS_REGISTER_anon_union,
}

#[derive(Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub union WHV_X64_FP_CONTROL_STATUS_REGISTER {
    AsUINT128: WHV_UINT128,
    anon_struct: WHV_X64_FP_CONTROL_STATUS_REGISTER_anon_struct,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_XMM_CONTROL_STATUS_REGISTER_32bit_mode_anon_struct {
    LastFpDp: UINT32,
    LastFpDs: UINT16,
    Reserved: UINT16,
}

#[derive(Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub union WHV_X64_XMM_CONTROL_STATUS_REGISTER_anon_union {
    LastFpRdp: UINT64,
    anon_struct: WHV_X64_XMM_CONTROL_STATUS_REGISTER_32bit_mode_anon_struct,
}

#[derive(Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_X64_XMM_CONTROL_STATUS_REGISTER_anon_struct {
    XmmStatusControl: UINT32,
    XmmStatusControlMask: UINT32,
    anon_union: WHV_X64_XMM_CONTROL_STATUS_REGISTER_anon_union,
}

#[derive(Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub union WHV_X64_XMM_CONTROL_STATUS_REGISTER {
    anon_struct: WHV_X64_XMM_CONTROL_STATUS_REGISTER_anon_struct,
    AsUINT128: WHV_UINT128,
}

#[derive(Copy, Clone)]
#[allow(non_snake_case)]
#[repr(C)]
pub union WHV_REGISTER_VALUE {
    pub Reg128: WHV_UINT128,
    pub Reg64: UINT64,
    pub Reg32: UINT32,
    pub Reg16: UINT16,
    pub Reg8: UINT8,
    pub Fp: WHV_X64_FP_REGISTER,
    pub FpControlStatus: WHV_X64_FP_CONTROL_STATUS_REGISTER,
    pub XmmControlStatus: WHV_X64_XMM_CONTROL_STATUS_REGISTER,
    pub Segment: WHV_X64_SEGMENT_REGISTER,
    pub Table: WHV_X64_TABLE_REGISTER,
    pub InterruptState: WHV_X64_INTERRUPT_STATE_REGISTER,
    pub PendingInterruption: WHV_X64_PENDING_INTERRUPTION_REGISTER,
    pub DeliverabilityNotifications: WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[allow(non_snake_case)]
#[repr(C)]
pub struct WHV_TRANSLATE_GVA_RESULT {
    pub ResultCode: WHV_TRANSLATE_GVA_RESULT_CODE,
    pub Reserved: UINT32,
}

#[cfg(test)]
mod tests {
    use super::*;
    use std;

    #[test]
    fn test_data_type_sizes() {
        // Make sure all unions and structs have a size that matches the value
        // obtained with a sizeof() in C.
        assert_eq!(std::mem::size_of::<WHV_CAPABILITY>(), 8);
        assert_eq!(std::mem::size_of::<WHV_X64_CPUID_RESULT>(), 32);
        assert_eq!(std::mem::size_of::<WHV_PARTITION_PROPERTY>(), 32);
        assert_eq!(std::mem::size_of::<WHV_X64_SEGMENT_REGISTER>(), 16);
        assert_eq!(std::mem::size_of::<WHV_X64_TABLE_REGISTER>(), 16);
        assert_eq!(std::mem::size_of::<WHV_VP_EXIT_CONTEXT>(), 40);
        assert_eq!(std::mem::size_of::<WHV_MEMORY_ACCESS_CONTEXT>(), 40);
        assert_eq!(std::mem::size_of::<WHV_X64_IO_PORT_ACCESS_CONTEXT>(), 96);
        assert_eq!(std::mem::size_of::<WHV_X64_MSR_ACCESS_CONTEXT>(), 24);
        assert_eq!(std::mem::size_of::<WHV_X64_CPUID_ACCESS_CONTEXT>(), 64);
        assert_eq!(std::mem::size_of::<WHV_VP_EXCEPTION_CONTEXT>(), 40);
        assert_eq!(
            std::mem::size_of::<WHV_X64_INTERRUPTION_DELIVERABLE_CONTEXT>(),
            4
        );
        assert_eq!(
            std::mem::size_of::<WHV_X64_UNSUPPORTED_FEATURE_CONTEXT>(),
            16
        );
        assert_eq!(std::mem::size_of::<WHV_RUN_VP_CANCELED_CONTEXT>(), 4);
        assert_eq!(std::mem::size_of::<WHV_RUN_VP_EXIT_CONTEXT>(), 144);
        assert_eq!(std::mem::size_of::<WHV_UINT128>(), 16);
        assert_eq!(std::mem::size_of::<WHV_REGISTER_VALUE>(), 16);
        assert_eq!(std::mem::size_of::<WHV_TRANSLATE_GVA_RESULT>(), 8);
    }
}