xref: /aosp_15_r20/external/crosvm/hypervisor/src/whpx/types.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::collections::HashMap;
6 
7 use once_cell::sync::Lazy;
8 use serde::Deserialize;
9 use serde::Serialize;
10 
11 use super::whpx_sys::*;
12 use crate::CpuIdEntry;
13 use crate::DebugRegs;
14 use crate::DescriptorTable;
15 use crate::Fpu;
16 use crate::FpuReg;
17 use crate::LapicState;
18 use crate::Regs;
19 use crate::Segment;
20 use crate::Sregs;
21 
22 #[derive(Default)]
23 pub(super) struct WhpxRegs {
24     register_values: [WHV_REGISTER_VALUE; 18],
25 }
26 
27 impl WhpxRegs {
get_register_names() -> &'static [WHV_REGISTER_NAME; 18]28     pub(super) fn get_register_names() -> &'static [WHV_REGISTER_NAME; 18] {
29         const REG_NAMES: [WHV_REGISTER_NAME; 18] = [
30             WHV_REGISTER_NAME_WHvX64RegisterRax,
31             WHV_REGISTER_NAME_WHvX64RegisterRbx,
32             WHV_REGISTER_NAME_WHvX64RegisterRcx,
33             WHV_REGISTER_NAME_WHvX64RegisterRdx,
34             WHV_REGISTER_NAME_WHvX64RegisterRsi,
35             WHV_REGISTER_NAME_WHvX64RegisterRdi,
36             WHV_REGISTER_NAME_WHvX64RegisterRsp,
37             WHV_REGISTER_NAME_WHvX64RegisterRbp,
38             WHV_REGISTER_NAME_WHvX64RegisterR8,
39             WHV_REGISTER_NAME_WHvX64RegisterR9,
40             WHV_REGISTER_NAME_WHvX64RegisterR10,
41             WHV_REGISTER_NAME_WHvX64RegisterR11,
42             WHV_REGISTER_NAME_WHvX64RegisterR12,
43             WHV_REGISTER_NAME_WHvX64RegisterR13,
44             WHV_REGISTER_NAME_WHvX64RegisterR14,
45             WHV_REGISTER_NAME_WHvX64RegisterR15,
46             WHV_REGISTER_NAME_WHvX64RegisterRip,
47             WHV_REGISTER_NAME_WHvX64RegisterRflags,
48         ];
49         &REG_NAMES
50     }
as_ptr(&self) -> *const WHV_REGISTER_VALUE51     pub(super) fn as_ptr(&self) -> *const WHV_REGISTER_VALUE {
52         self.register_values.as_ptr()
53     }
as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE54     pub(super) fn as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE {
55         self.register_values.as_mut_ptr()
56     }
57 }
58 
59 impl From<&Regs> for WhpxRegs {
from(regs: &Regs) -> Self60     fn from(regs: &Regs) -> Self {
61         WhpxRegs {
62             register_values: [
63                 WHV_REGISTER_VALUE { Reg64: regs.rax },
64                 WHV_REGISTER_VALUE { Reg64: regs.rbx },
65                 WHV_REGISTER_VALUE { Reg64: regs.rcx },
66                 WHV_REGISTER_VALUE { Reg64: regs.rdx },
67                 WHV_REGISTER_VALUE { Reg64: regs.rsi },
68                 WHV_REGISTER_VALUE { Reg64: regs.rdi },
69                 WHV_REGISTER_VALUE { Reg64: regs.rsp },
70                 WHV_REGISTER_VALUE { Reg64: regs.rbp },
71                 WHV_REGISTER_VALUE { Reg64: regs.r8 },
72                 WHV_REGISTER_VALUE { Reg64: regs.r9 },
73                 WHV_REGISTER_VALUE { Reg64: regs.r10 },
74                 WHV_REGISTER_VALUE { Reg64: regs.r11 },
75                 WHV_REGISTER_VALUE { Reg64: regs.r12 },
76                 WHV_REGISTER_VALUE { Reg64: regs.r13 },
77                 WHV_REGISTER_VALUE { Reg64: regs.r14 },
78                 WHV_REGISTER_VALUE { Reg64: regs.r15 },
79                 WHV_REGISTER_VALUE { Reg64: regs.rip },
80                 WHV_REGISTER_VALUE { Reg64: regs.rflags },
81             ],
82         }
83     }
84 }
85 
86 impl From<&WhpxRegs> for Regs {
from(whpx_regs: &WhpxRegs) -> Self87     fn from(whpx_regs: &WhpxRegs) -> Self {
88         unsafe {
89             Regs {
90                 rax: whpx_regs.register_values[0].Reg64,
91                 rbx: whpx_regs.register_values[1].Reg64,
92                 rcx: whpx_regs.register_values[2].Reg64,
93                 rdx: whpx_regs.register_values[3].Reg64,
94                 rsi: whpx_regs.register_values[4].Reg64,
95                 rdi: whpx_regs.register_values[5].Reg64,
96                 rsp: whpx_regs.register_values[6].Reg64,
97                 rbp: whpx_regs.register_values[7].Reg64,
98                 r8: whpx_regs.register_values[8].Reg64,
99                 r9: whpx_regs.register_values[9].Reg64,
100                 r10: whpx_regs.register_values[10].Reg64,
101                 r11: whpx_regs.register_values[11].Reg64,
102                 r12: whpx_regs.register_values[12].Reg64,
103                 r13: whpx_regs.register_values[13].Reg64,
104                 r14: whpx_regs.register_values[14].Reg64,
105                 r15: whpx_regs.register_values[15].Reg64,
106                 rip: whpx_regs.register_values[16].Reg64,
107                 rflags: whpx_regs.register_values[17].Reg64,
108             }
109         }
110     }
111 }
112 
113 impl From<&Segment> for WHV_X64_SEGMENT_REGISTER {
from(segment: &Segment) -> Self114     fn from(segment: &Segment) -> Self {
115         let attributes = WHV_X64_SEGMENT_REGISTER__bindgen_ty_1__bindgen_ty_1::new_bitfield_1(
116             segment.type_.into(),
117             segment.s.into(),
118             segment.dpl.into(),
119             segment.present.into(),
120             0, // reserved
121             segment.avl.into(),
122             segment.l.into(),
123             segment.db.into(),
124             segment.g.into(),
125         );
126         WHV_X64_SEGMENT_REGISTER {
127             Base: segment.base,
128             Limit: segment.limit_bytes,
129             Selector: segment.selector,
130             __bindgen_anon_1: WHV_X64_SEGMENT_REGISTER__bindgen_ty_1 {
131                 __bindgen_anon_1: WHV_X64_SEGMENT_REGISTER__bindgen_ty_1__bindgen_ty_1 {
132                     _bitfield_align_1: [],
133                     _bitfield_1: attributes,
134                 },
135             },
136         }
137     }
138 }
139 
140 impl From<&WHV_X64_SEGMENT_REGISTER> for Segment {
from(whpx_segment: &WHV_X64_SEGMENT_REGISTER) -> Self141     fn from(whpx_segment: &WHV_X64_SEGMENT_REGISTER) -> Self {
142         // safe because the union field can always be interpreteted as a bitfield
143         let attributes = unsafe { whpx_segment.__bindgen_anon_1.__bindgen_anon_1 };
144         Segment {
145             base: whpx_segment.Base,
146             limit_bytes: whpx_segment.Limit,
147             selector: whpx_segment.Selector,
148             type_: attributes.SegmentType() as u8,
149             present: attributes.Present() as u8,
150             dpl: attributes.DescriptorPrivilegeLevel() as u8,
151             db: attributes.Default() as u8,
152             s: attributes.NonSystemSegment() as u8,
153             l: attributes.Long() as u8,
154             g: attributes.Granularity() as u8,
155             avl: attributes.Available() as u8,
156         }
157     }
158 }
159 
160 impl From<&DescriptorTable> for WHV_X64_TABLE_REGISTER {
from(descr_table: &DescriptorTable) -> Self161     fn from(descr_table: &DescriptorTable) -> Self {
162         WHV_X64_TABLE_REGISTER {
163             Pad: Default::default(),
164             Base: descr_table.base,
165             Limit: descr_table.limit,
166         }
167     }
168 }
169 
170 impl From<&WHV_X64_TABLE_REGISTER> for DescriptorTable {
from(whpx_table_register: &WHV_X64_TABLE_REGISTER) -> Self171     fn from(whpx_table_register: &WHV_X64_TABLE_REGISTER) -> Self {
172         DescriptorTable {
173             base: whpx_table_register.Base,
174             limit: whpx_table_register.Limit,
175         }
176     }
177 }
178 
179 #[derive(Default)]
180 pub(super) struct WhpxSregs {
181     register_values: [WHV_REGISTER_VALUE; 16],
182 }
183 
184 impl WhpxSregs {
get_register_names() -> &'static [WHV_REGISTER_NAME; 16]185     pub(super) fn get_register_names() -> &'static [WHV_REGISTER_NAME; 16] {
186         const REG_NAMES: [WHV_REGISTER_NAME; 16] = [
187             WHV_REGISTER_NAME_WHvX64RegisterCs,
188             WHV_REGISTER_NAME_WHvX64RegisterDs,
189             WHV_REGISTER_NAME_WHvX64RegisterEs,
190             WHV_REGISTER_NAME_WHvX64RegisterFs,
191             WHV_REGISTER_NAME_WHvX64RegisterGs,
192             WHV_REGISTER_NAME_WHvX64RegisterSs,
193             WHV_REGISTER_NAME_WHvX64RegisterTr,
194             WHV_REGISTER_NAME_WHvX64RegisterLdtr,
195             WHV_REGISTER_NAME_WHvX64RegisterGdtr,
196             WHV_REGISTER_NAME_WHvX64RegisterIdtr,
197             WHV_REGISTER_NAME_WHvX64RegisterCr0,
198             WHV_REGISTER_NAME_WHvX64RegisterCr2,
199             WHV_REGISTER_NAME_WHvX64RegisterCr3,
200             WHV_REGISTER_NAME_WHvX64RegisterCr4,
201             WHV_REGISTER_NAME_WHvX64RegisterCr8,
202             WHV_REGISTER_NAME_WHvX64RegisterEfer, // this is actually an msr
203         ];
204         &REG_NAMES
205     }
as_ptr(&self) -> *const WHV_REGISTER_VALUE206     pub(super) fn as_ptr(&self) -> *const WHV_REGISTER_VALUE {
207         self.register_values.as_ptr()
208     }
as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE209     pub(super) fn as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE {
210         self.register_values.as_mut_ptr()
211     }
212 }
213 
214 impl From<&Sregs> for WhpxSregs {
from(sregs: &Sregs) -> Self215     fn from(sregs: &Sregs) -> Self {
216         WhpxSregs {
217             register_values: [
218                 WHV_REGISTER_VALUE {
219                     Segment: WHV_X64_SEGMENT_REGISTER::from(&sregs.cs),
220                 },
221                 WHV_REGISTER_VALUE {
222                     Segment: WHV_X64_SEGMENT_REGISTER::from(&sregs.ds),
223                 },
224                 WHV_REGISTER_VALUE {
225                     Segment: WHV_X64_SEGMENT_REGISTER::from(&sregs.es),
226                 },
227                 WHV_REGISTER_VALUE {
228                     Segment: WHV_X64_SEGMENT_REGISTER::from(&sregs.fs),
229                 },
230                 WHV_REGISTER_VALUE {
231                     Segment: WHV_X64_SEGMENT_REGISTER::from(&sregs.gs),
232                 },
233                 WHV_REGISTER_VALUE {
234                     Segment: WHV_X64_SEGMENT_REGISTER::from(&sregs.ss),
235                 },
236                 WHV_REGISTER_VALUE {
237                     Segment: WHV_X64_SEGMENT_REGISTER::from(&sregs.tr),
238                 },
239                 WHV_REGISTER_VALUE {
240                     Segment: WHV_X64_SEGMENT_REGISTER::from(&sregs.ldt),
241                 },
242                 WHV_REGISTER_VALUE {
243                     Table: WHV_X64_TABLE_REGISTER::from(&sregs.gdt),
244                 },
245                 WHV_REGISTER_VALUE {
246                     Table: WHV_X64_TABLE_REGISTER::from(&sregs.idt),
247                 },
248                 WHV_REGISTER_VALUE { Reg64: sregs.cr0 },
249                 WHV_REGISTER_VALUE { Reg64: sregs.cr2 },
250                 WHV_REGISTER_VALUE { Reg64: sregs.cr3 },
251                 WHV_REGISTER_VALUE { Reg64: sregs.cr4 },
252                 WHV_REGISTER_VALUE { Reg64: sregs.cr8 },
253                 WHV_REGISTER_VALUE { Reg64: sregs.efer },
254             ],
255         }
256     }
257 }
258 
259 impl From<&WhpxSregs> for Sregs {
from(whpx_regs: &WhpxSregs) -> Self260     fn from(whpx_regs: &WhpxSregs) -> Self {
261         unsafe {
262             Sregs {
263                 cs: Segment::from(&whpx_regs.register_values[0].Segment),
264                 ds: Segment::from(&whpx_regs.register_values[1].Segment),
265                 es: Segment::from(&whpx_regs.register_values[2].Segment),
266                 fs: Segment::from(&whpx_regs.register_values[3].Segment),
267                 gs: Segment::from(&whpx_regs.register_values[4].Segment),
268                 ss: Segment::from(&whpx_regs.register_values[5].Segment),
269                 tr: Segment::from(&whpx_regs.register_values[6].Segment),
270                 ldt: Segment::from(&whpx_regs.register_values[7].Segment),
271                 gdt: DescriptorTable::from(&whpx_regs.register_values[8].Table),
272                 idt: DescriptorTable::from(&whpx_regs.register_values[9].Table),
273                 cr0: whpx_regs.register_values[10].Reg64,
274                 cr2: whpx_regs.register_values[11].Reg64,
275                 cr3: whpx_regs.register_values[12].Reg64,
276                 cr4: whpx_regs.register_values[13].Reg64,
277                 cr8: whpx_regs.register_values[14].Reg64,
278                 efer: whpx_regs.register_values[15].Reg64,
279             }
280         }
281     }
282 }
283 
284 impl From<u128> for WHV_UINT128 {
from(v: u128) -> WHV_UINT128285     fn from(v: u128) -> WHV_UINT128 {
286         WHV_UINT128 {
287             __bindgen_anon_1: WHV_UINT128__bindgen_ty_1 {
288                 Low64: v as u64,
289                 High64: (v >> 64) as u64,
290             },
291         }
292     }
293 }
294 
295 impl From<WHV_UINT128> for u128 {
from(v: WHV_UINT128) -> u128296     fn from(v: WHV_UINT128) -> u128 {
297         // SAFETY: Accessing u64 fields of the union is always safe since all bit patterns are valid
298         // for u64.
299         let (low64, high64) = unsafe { (v.__bindgen_anon_1.Low64, v.__bindgen_anon_1.High64) };
300         u128::from(low64) | (u128::from(high64) << 64)
301     }
302 }
303 
304 impl WHV_UINT128 {
305     #[inline]
from_ne_bytes(bytes: [u8; 16]) -> WHV_UINT128306     pub fn from_ne_bytes(bytes: [u8; 16]) -> WHV_UINT128 {
307         WHV_UINT128::from(u128::from_ne_bytes(bytes))
308     }
309 
310     #[inline]
to_ne_bytes(self) -> [u8; 16]311     pub fn to_ne_bytes(self) -> [u8; 16] {
312         u128::from(self).to_ne_bytes()
313     }
314 }
315 
316 #[derive(Default)]
317 pub(super) struct WhpxFpu {
318     register_values: [WHV_REGISTER_VALUE; 26],
319 }
320 
321 impl WhpxFpu {
get_register_names() -> &'static [WHV_REGISTER_NAME; 26]322     pub(super) fn get_register_names() -> &'static [WHV_REGISTER_NAME; 26] {
323         const REG_NAMES: [WHV_REGISTER_NAME; 26] = [
324             WHV_REGISTER_NAME_WHvX64RegisterFpMmx0,
325             WHV_REGISTER_NAME_WHvX64RegisterFpMmx1,
326             WHV_REGISTER_NAME_WHvX64RegisterFpMmx2,
327             WHV_REGISTER_NAME_WHvX64RegisterFpMmx3,
328             WHV_REGISTER_NAME_WHvX64RegisterFpMmx4,
329             WHV_REGISTER_NAME_WHvX64RegisterFpMmx5,
330             WHV_REGISTER_NAME_WHvX64RegisterFpMmx6,
331             WHV_REGISTER_NAME_WHvX64RegisterFpMmx7,
332             WHV_REGISTER_NAME_WHvX64RegisterFpControlStatus,
333             WHV_REGISTER_NAME_WHvX64RegisterXmmControlStatus,
334             WHV_REGISTER_NAME_WHvX64RegisterXmm0,
335             WHV_REGISTER_NAME_WHvX64RegisterXmm1,
336             WHV_REGISTER_NAME_WHvX64RegisterXmm2,
337             WHV_REGISTER_NAME_WHvX64RegisterXmm3,
338             WHV_REGISTER_NAME_WHvX64RegisterXmm4,
339             WHV_REGISTER_NAME_WHvX64RegisterXmm5,
340             WHV_REGISTER_NAME_WHvX64RegisterXmm6,
341             WHV_REGISTER_NAME_WHvX64RegisterXmm7,
342             WHV_REGISTER_NAME_WHvX64RegisterXmm8,
343             WHV_REGISTER_NAME_WHvX64RegisterXmm9,
344             WHV_REGISTER_NAME_WHvX64RegisterXmm10,
345             WHV_REGISTER_NAME_WHvX64RegisterXmm11,
346             WHV_REGISTER_NAME_WHvX64RegisterXmm12,
347             WHV_REGISTER_NAME_WHvX64RegisterXmm13,
348             WHV_REGISTER_NAME_WHvX64RegisterXmm14,
349             WHV_REGISTER_NAME_WHvX64RegisterXmm15,
350         ];
351         &REG_NAMES
352     }
as_ptr(&self) -> *const WHV_REGISTER_VALUE353     pub(super) fn as_ptr(&self) -> *const WHV_REGISTER_VALUE {
354         self.register_values.as_ptr()
355     }
as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE356     pub(super) fn as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE {
357         self.register_values.as_mut_ptr()
358     }
359 }
360 
whpx_register_from_fpu_reg(fpr: FpuReg) -> WHV_REGISTER_VALUE361 fn whpx_register_from_fpu_reg(fpr: FpuReg) -> WHV_REGISTER_VALUE {
362     WHV_REGISTER_VALUE {
363         Fp: WHV_X64_FP_REGISTER {
364             AsUINT128: WHV_UINT128::from_ne_bytes(fpr.into()),
365         },
366     }
367 }
368 
369 impl From<&Fpu> for WhpxFpu {
from(fpu: &Fpu) -> Self370     fn from(fpu: &Fpu) -> Self {
371         WhpxFpu {
372             register_values: [
373                 whpx_register_from_fpu_reg(fpu.fpr[0]),
374                 whpx_register_from_fpu_reg(fpu.fpr[1]),
375                 whpx_register_from_fpu_reg(fpu.fpr[2]),
376                 whpx_register_from_fpu_reg(fpu.fpr[3]),
377                 whpx_register_from_fpu_reg(fpu.fpr[4]),
378                 whpx_register_from_fpu_reg(fpu.fpr[5]),
379                 whpx_register_from_fpu_reg(fpu.fpr[6]),
380                 whpx_register_from_fpu_reg(fpu.fpr[7]),
381                 WHV_REGISTER_VALUE {
382                     FpControlStatus: WHV_X64_FP_CONTROL_STATUS_REGISTER {
383                         __bindgen_anon_1: WHV_X64_FP_CONTROL_STATUS_REGISTER__bindgen_ty_1 {
384                             FpControl: fpu.fcw,
385                             FpStatus: fpu.fsw,
386                             FpTag: fpu.ftwx,
387                             Reserved: 0,
388                             LastFpOp: fpu.last_opcode,
389                             __bindgen_anon_1:
390                                 WHV_X64_FP_CONTROL_STATUS_REGISTER__bindgen_ty_1__bindgen_ty_1 {
391                                     LastFpRip: fpu.last_ip,
392                                 },
393                         },
394                     },
395                 },
396                 WHV_REGISTER_VALUE {
397                     XmmControlStatus: WHV_X64_XMM_CONTROL_STATUS_REGISTER {
398                         __bindgen_anon_1: WHV_X64_XMM_CONTROL_STATUS_REGISTER__bindgen_ty_1 {
399                             __bindgen_anon_1:
400                                 WHV_X64_XMM_CONTROL_STATUS_REGISTER__bindgen_ty_1__bindgen_ty_1 {
401                                     LastFpRdp: fpu.last_dp,
402                                 },
403                             XmmStatusControl: fpu.mxcsr,
404                             XmmStatusControlMask: 0,
405                         },
406                     },
407                 },
408                 WHV_REGISTER_VALUE {
409                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[0]),
410                 },
411                 WHV_REGISTER_VALUE {
412                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[1]),
413                 },
414                 WHV_REGISTER_VALUE {
415                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[2]),
416                 },
417                 WHV_REGISTER_VALUE {
418                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[3]),
419                 },
420                 WHV_REGISTER_VALUE {
421                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[4]),
422                 },
423                 WHV_REGISTER_VALUE {
424                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[5]),
425                 },
426                 WHV_REGISTER_VALUE {
427                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[6]),
428                 },
429                 WHV_REGISTER_VALUE {
430                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[7]),
431                 },
432                 WHV_REGISTER_VALUE {
433                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[8]),
434                 },
435                 WHV_REGISTER_VALUE {
436                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[9]),
437                 },
438                 WHV_REGISTER_VALUE {
439                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[10]),
440                 },
441                 WHV_REGISTER_VALUE {
442                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[11]),
443                 },
444                 WHV_REGISTER_VALUE {
445                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[12]),
446                 },
447                 WHV_REGISTER_VALUE {
448                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[13]),
449                 },
450                 WHV_REGISTER_VALUE {
451                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[14]),
452                 },
453                 WHV_REGISTER_VALUE {
454                     Reg128: WHV_UINT128::from_ne_bytes(fpu.xmm[15]),
455                 },
456             ],
457         }
458     }
459 }
460 
fpu_reg_from_whpx_register(whpx_reg: &WHV_REGISTER_VALUE) -> FpuReg461 fn fpu_reg_from_whpx_register(whpx_reg: &WHV_REGISTER_VALUE) -> FpuReg {
462     let fp_reg_bytes: [u8; 10] = unsafe {
463         whpx_reg.Fp.AsUINT128.to_ne_bytes()[0..10]
464             .try_into()
465             .unwrap()
466     };
467     FpuReg::from(fp_reg_bytes)
468 }
469 
470 impl From<&WhpxFpu> for Fpu {
from(whpx_regs: &WhpxFpu) -> Self471     fn from(whpx_regs: &WhpxFpu) -> Self {
472         unsafe {
473             let fp_control = whpx_regs.register_values[8]
474                 .FpControlStatus
475                 .__bindgen_anon_1;
476             let xmm_control = whpx_regs.register_values[9]
477                 .XmmControlStatus
478                 .__bindgen_anon_1;
479             Fpu {
480                 fpr: [
481                     fpu_reg_from_whpx_register(&whpx_regs.register_values[0]),
482                     fpu_reg_from_whpx_register(&whpx_regs.register_values[1]),
483                     fpu_reg_from_whpx_register(&whpx_regs.register_values[2]),
484                     fpu_reg_from_whpx_register(&whpx_regs.register_values[3]),
485                     fpu_reg_from_whpx_register(&whpx_regs.register_values[4]),
486                     fpu_reg_from_whpx_register(&whpx_regs.register_values[5]),
487                     fpu_reg_from_whpx_register(&whpx_regs.register_values[6]),
488                     fpu_reg_from_whpx_register(&whpx_regs.register_values[7]),
489                 ],
490                 fcw: fp_control.FpControl,
491                 fsw: fp_control.FpStatus,
492                 ftwx: fp_control.FpTag,
493                 last_opcode: fp_control.LastFpOp,
494                 last_ip: fp_control.__bindgen_anon_1.LastFpRip,
495                 last_dp: xmm_control.__bindgen_anon_1.LastFpRdp,
496                 xmm: [
497                     whpx_regs.register_values[10].Reg128.to_ne_bytes(),
498                     whpx_regs.register_values[11].Reg128.to_ne_bytes(),
499                     whpx_regs.register_values[12].Reg128.to_ne_bytes(),
500                     whpx_regs.register_values[13].Reg128.to_ne_bytes(),
501                     whpx_regs.register_values[14].Reg128.to_ne_bytes(),
502                     whpx_regs.register_values[15].Reg128.to_ne_bytes(),
503                     whpx_regs.register_values[16].Reg128.to_ne_bytes(),
504                     whpx_regs.register_values[17].Reg128.to_ne_bytes(),
505                     whpx_regs.register_values[18].Reg128.to_ne_bytes(),
506                     whpx_regs.register_values[19].Reg128.to_ne_bytes(),
507                     whpx_regs.register_values[20].Reg128.to_ne_bytes(),
508                     whpx_regs.register_values[21].Reg128.to_ne_bytes(),
509                     whpx_regs.register_values[22].Reg128.to_ne_bytes(),
510                     whpx_regs.register_values[23].Reg128.to_ne_bytes(),
511                     whpx_regs.register_values[24].Reg128.to_ne_bytes(),
512                     whpx_regs.register_values[25].Reg128.to_ne_bytes(),
513                 ],
514                 mxcsr: xmm_control.XmmStatusControl,
515             }
516         }
517     }
518 }
519 
520 #[derive(Default)]
521 pub(super) struct WhpxDebugRegs {
522     register_values: [WHV_REGISTER_VALUE; 6],
523 }
524 
525 impl WhpxDebugRegs {
get_register_names() -> &'static [WHV_REGISTER_NAME; 6]526     pub(super) fn get_register_names() -> &'static [WHV_REGISTER_NAME; 6] {
527         const REG_NAMES: [WHV_REGISTER_NAME; 6] = [
528             WHV_REGISTER_NAME_WHvX64RegisterDr0,
529             WHV_REGISTER_NAME_WHvX64RegisterDr1,
530             WHV_REGISTER_NAME_WHvX64RegisterDr2,
531             WHV_REGISTER_NAME_WHvX64RegisterDr3,
532             WHV_REGISTER_NAME_WHvX64RegisterDr6,
533             WHV_REGISTER_NAME_WHvX64RegisterDr7,
534         ];
535         &REG_NAMES
536     }
as_ptr(&self) -> *const WHV_REGISTER_VALUE537     pub(super) fn as_ptr(&self) -> *const WHV_REGISTER_VALUE {
538         self.register_values.as_ptr()
539     }
as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE540     pub(super) fn as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE {
541         self.register_values.as_mut_ptr()
542     }
543 }
544 
545 impl From<&DebugRegs> for WhpxDebugRegs {
from(debug_regs: &DebugRegs) -> Self546     fn from(debug_regs: &DebugRegs) -> Self {
547         WhpxDebugRegs {
548             register_values: [
549                 WHV_REGISTER_VALUE {
550                     Reg64: debug_regs.db[0],
551                 },
552                 WHV_REGISTER_VALUE {
553                     Reg64: debug_regs.db[1],
554                 },
555                 WHV_REGISTER_VALUE {
556                     Reg64: debug_regs.db[2],
557                 },
558                 WHV_REGISTER_VALUE {
559                     Reg64: debug_regs.db[3],
560                 },
561                 WHV_REGISTER_VALUE {
562                     Reg64: debug_regs.dr6,
563                 },
564                 WHV_REGISTER_VALUE {
565                     Reg64: debug_regs.dr7,
566                 },
567             ],
568         }
569     }
570 }
571 
572 impl From<&WhpxDebugRegs> for DebugRegs {
from(whpx_regs: &WhpxDebugRegs) -> Self573     fn from(whpx_regs: &WhpxDebugRegs) -> Self {
574         // safe because accessing the union Reg64 value for WhpxDebugRegs should
575         // always be valid.
576         unsafe {
577             DebugRegs {
578                 db: [
579                     whpx_regs.register_values[0].Reg64,
580                     whpx_regs.register_values[1].Reg64,
581                     whpx_regs.register_values[2].Reg64,
582                     whpx_regs.register_values[3].Reg64,
583                 ],
584                 dr6: whpx_regs.register_values[4].Reg64,
585                 dr7: whpx_regs.register_values[5].Reg64,
586             }
587         }
588     }
589 }
590 
591 /// Registers that store pending interrupts and interrupt state.
592 ///
593 /// There are four critical registers:
594 /// * WHvRegisterPendingInterruption (u64; HTLFS page 55): contains interrupts which are pending,
595 ///   but not yet delivered.
596 /// * WHvRegisterInterruptState (u64; HTLFS page 55): contains the interrupt state for the VCPU
597 ///   (e.g. masking nmis, etc).
598 /// * WHvX64RegisterDeliverabilityNotifications (u64; WHPX docs only): allows us to request a VCPU
599 ///   exit once injection of interrupts is possible.
600 /// * WHvRegisterInternalActivityState (u64; WHPX docs only): this register is unspecified except
601 ///   for its existence, so we consider it to be opaque. From experimentation, we believe it
602 ///   contains some kind of state required by SMP guests, because snapshotting/restoring without it
603 ///   causes all APs to freeze (the BSP does exit periodically, but also seems to be very unhappy).
604 #[derive(Default)]
605 pub(super) struct WhpxInterruptRegs {
606     register_values: [WHV_REGISTER_VALUE; 4],
607 }
608 
609 #[derive(Serialize, Deserialize)]
610 pub(super) struct SerializedWhpxInterruptRegs {
611     pending_interruption: u64,
612     interrupt_state: u64,
613     deliverability_notifications: u64,
614     internal_activity_state: u64,
615 }
616 
617 impl WhpxInterruptRegs {
get_register_names() -> &'static [WHV_REGISTER_NAME; 4]618     pub(super) fn get_register_names() -> &'static [WHV_REGISTER_NAME; 4] {
619         const REG_NAMES: [WHV_REGISTER_NAME; 4] = [
620             WHV_REGISTER_NAME_WHvRegisterPendingInterruption,
621             WHV_REGISTER_NAME_WHvRegisterInterruptState,
622             WHV_REGISTER_NAME_WHvX64RegisterDeliverabilityNotifications,
623             WHV_REGISTER_NAME_WHvRegisterInternalActivityState,
624         ];
625         &REG_NAMES
626     }
as_ptr(&self) -> *const WHV_REGISTER_VALUE627     pub(super) fn as_ptr(&self) -> *const WHV_REGISTER_VALUE {
628         self.register_values.as_ptr()
629     }
as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE630     pub(super) fn as_mut_ptr(&mut self) -> *mut WHV_REGISTER_VALUE {
631         self.register_values.as_mut_ptr()
632     }
633 
into_serializable(self) -> SerializedWhpxInterruptRegs634     pub(super) fn into_serializable(self) -> SerializedWhpxInterruptRegs {
635         SerializedWhpxInterruptRegs {
636             // SAFETY: This register is a valid u64.
637             pending_interruption: unsafe { self.register_values[0].PendingInterruption.AsUINT64 },
638             // SAFETY: This register is a valid u64.
639             interrupt_state: unsafe { self.register_values[1].InterruptState.AsUINT64 },
640             // SAFETY: This register is a valid u64.
641             deliverability_notifications: unsafe {
642                 self.register_values[2].DeliverabilityNotifications.AsUINT64
643             },
644             // SAFETY: This register is a valid u64.
645             internal_activity_state: unsafe { self.register_values[3].InternalActivity.AsUINT64 },
646         }
647     }
648 
from_serializable(serialized_regs: SerializedWhpxInterruptRegs) -> Self649     pub(super) fn from_serializable(serialized_regs: SerializedWhpxInterruptRegs) -> Self {
650         let mut whpx_interrupt_regs: WhpxInterruptRegs = Default::default();
651         whpx_interrupt_regs.register_values[0]
652             .PendingInterruption
653             .AsUINT64 = serialized_regs.pending_interruption;
654         whpx_interrupt_regs.register_values[1]
655             .InterruptState
656             .AsUINT64 = serialized_regs.interrupt_state;
657         whpx_interrupt_regs.register_values[2]
658             .DeliverabilityNotifications
659             .AsUINT64 = serialized_regs.deliverability_notifications;
660         whpx_interrupt_regs.register_values[3]
661             .InternalActivity
662             .AsUINT64 = serialized_regs.internal_activity_state;
663         whpx_interrupt_regs
664     }
665 }
666 
667 // list of MSR registers for whpx, and their actual ids
668 pub(super) const MSR_TSC: u32 = 0x00000010;
669 pub(super) const MSR_EFER: u32 = 0xc0000080;
670 pub(super) const MSR_KERNEL_GS_BASE: u32 = 0xc0000102;
671 pub(super) const MSR_APIC_BASE: u32 = 0x0000001b;
672 pub(super) const MSR_PAT: u32 = 0x00000277;
673 pub(super) const MSR_SYSENTER_CS: u32 = 0x00000174;
674 pub(super) const MSR_SYSENTER_EIP: u32 = 0x00000176;
675 pub(super) const MSR_SYSENTER_ESP: u32 = 0x00000175;
676 pub(super) const MSR_STAR: u32 = 0xc0000081;
677 pub(super) const MSR_LSTAR: u32 = 0xc0000082;
678 pub(super) const MSR_CSTAR: u32 = 0xc0000083;
679 pub(super) const MSR_SFMASK: u32 = 0xc0000084;
680 pub(super) const MSR_MTRR_CAP: u32 = 0x000000fe;
681 pub(super) const MSR_MTRR_DEF_TYPE: u32 = 0x000002ff;
682 pub(super) const MSR_MTRR_PHYS_BASE0: u32 = 0x00000200;
683 pub(super) const MSR_MTRR_PHYS_BASE1: u32 = 0x00000202;
684 pub(super) const MSR_MTRR_PHYS_BASE2: u32 = 0x00000204;
685 pub(super) const MSR_MTRR_PHYS_BASE3: u32 = 0x00000206;
686 pub(super) const MSR_MTRR_PHYS_BASE4: u32 = 0x00000208;
687 pub(super) const MSR_MTRR_PHYS_BASE5: u32 = 0x0000020a;
688 pub(super) const MSR_MTRR_PHYS_BASE6: u32 = 0x0000020c;
689 pub(super) const MSR_MTRR_PHYS_BASE7: u32 = 0x0000020e;
690 pub(super) const MSR_MTRR_PHYS_BASE8: u32 = 0x00000210;
691 pub(super) const MSR_MTRR_PHYS_BASE9: u32 = 0x00000212;
692 pub(super) const MSR_MTRR_PHYS_BASEA: u32 = 0x00000214;
693 pub(super) const MSR_MTRR_PHYS_BASEB: u32 = 0x00000216;
694 pub(super) const MSR_MTRR_PHYS_BASEC: u32 = 0x00000218;
695 pub(super) const MSR_MTRR_PHYS_BASED: u32 = 0x0000021a;
696 pub(super) const MSR_MTRR_PHYS_BASEE: u32 = 0x0000021c;
697 pub(super) const MSR_MTRR_PHYS_BASEF: u32 = 0x0000021e;
698 pub(super) const MSR_MTRR_PHYS_MASK0: u32 = 0x00000201;
699 pub(super) const MSR_MTRR_PHYS_MASK1: u32 = 0x00000203;
700 pub(super) const MSR_MTRR_PHYS_MASK2: u32 = 0x00000205;
701 pub(super) const MSR_MTRR_PHYS_MASK3: u32 = 0x00000207;
702 pub(super) const MSR_MTRR_PHYS_MASK4: u32 = 0x00000209;
703 pub(super) const MSR_MTRR_PHYS_MASK5: u32 = 0x0000020b;
704 pub(super) const MSR_MTRR_PHYS_MASK6: u32 = 0x0000020d;
705 pub(super) const MSR_MTRR_PHYS_MASK7: u32 = 0x0000020f;
706 pub(super) const MSR_MTRR_PHYS_MASK8: u32 = 0x00000211;
707 pub(super) const MSR_MTRR_PHYS_MASK9: u32 = 0x00000213;
708 pub(super) const MSR_MTRR_PHYS_MASKA: u32 = 0x00000215;
709 pub(super) const MSR_MTRR_PHYS_MASKB: u32 = 0x00000217;
710 pub(super) const MSR_MTRR_PHYS_MASKC: u32 = 0x00000219;
711 pub(super) const MSR_MTRR_PHYS_MASKD: u32 = 0x0000021b;
712 pub(super) const MSR_MTRR_PHYS_MASKE: u32 = 0x0000021d;
713 pub(super) const MSR_MTRR_PHYS_MASKF: u32 = 0x0000021f;
714 pub(super) const MSR_MTRR_FIX64K_00000: u32 = 0x00000250;
715 pub(super) const MSR_MTRR_FIX16K_80000: u32 = 0x00000258;
716 pub(super) const MSR_MTRR_FIX16K_A0000: u32 = 0x00000259;
717 pub(super) const MSR_MTRR_FIX4K_C0000: u32 = 0x00000268;
718 pub(super) const MSR_MTRR_FIX4K_C8000: u32 = 0x00000269;
719 pub(super) const MSR_MTRR_FIX4K_D0000: u32 = 0x0000026a;
720 pub(super) const MSR_MTRR_FIX4K_D8000: u32 = 0x0000026b;
721 pub(super) const MSR_MTRR_FIX4K_E0000: u32 = 0x0000026c;
722 pub(super) const MSR_MTRR_FIX4K_E8000: u32 = 0x0000026d;
723 pub(super) const MSR_MTRR_FIX4K_F0000: u32 = 0x0000026e;
724 pub(super) const MSR_MTRR_FIX4K_F8000: u32 = 0x0000026f;
725 pub(super) const MSR_TSC_AUX: u32 = 0xc0000103;
726 pub(super) const MSR_SPEC_CTRL: u32 = 0x00000048;
727 pub(super) const MSR_PRED_CMD: u32 = 0x00000049;
728 
729 // the valid msrs for whpx, converting from the x86 efer id's to the whpx register name value.
730 // https://docs.microsoft.com/en-us/virtualization/api/hypervisor-platform/funcs/whvvirtualprocessordatatypes
731 #[rustfmt::skip]
732 pub(super) static VALID_MSRS: Lazy<HashMap<u32, WHV_REGISTER_NAME>> = Lazy::new(|| {
733     [
734         (MSR_TSC,WHV_REGISTER_NAME_WHvX64RegisterTsc),
735         (MSR_EFER,WHV_REGISTER_NAME_WHvX64RegisterEfer),
736         (MSR_KERNEL_GS_BASE,WHV_REGISTER_NAME_WHvX64RegisterKernelGsBase),
737         (MSR_APIC_BASE,WHV_REGISTER_NAME_WHvX64RegisterApicBase),
738         (MSR_PAT,WHV_REGISTER_NAME_WHvX64RegisterPat),
739         (MSR_SYSENTER_CS,WHV_REGISTER_NAME_WHvX64RegisterSysenterCs),
740         (MSR_SYSENTER_EIP,WHV_REGISTER_NAME_WHvX64RegisterSysenterEip),
741         (MSR_SYSENTER_ESP,WHV_REGISTER_NAME_WHvX64RegisterSysenterEsp),
742         (MSR_STAR,WHV_REGISTER_NAME_WHvX64RegisterStar),
743         (MSR_LSTAR,WHV_REGISTER_NAME_WHvX64RegisterLstar),
744         (MSR_CSTAR,WHV_REGISTER_NAME_WHvX64RegisterCstar),
745         (MSR_SFMASK,WHV_REGISTER_NAME_WHvX64RegisterSfmask),
746         (MSR_MTRR_CAP,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrCap),
747         (MSR_MTRR_DEF_TYPE,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrDefType),
748         (MSR_MTRR_PHYS_BASE0,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase0),
749         (MSR_MTRR_PHYS_BASE1,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase1),
750         (MSR_MTRR_PHYS_BASE2,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase2),
751         (MSR_MTRR_PHYS_BASE3,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase3),
752         (MSR_MTRR_PHYS_BASE4,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase4),
753         (MSR_MTRR_PHYS_BASE5,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase5),
754         (MSR_MTRR_PHYS_BASE6,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase6),
755         (MSR_MTRR_PHYS_BASE7,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase7),
756         (MSR_MTRR_PHYS_BASE8,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase8),
757         (MSR_MTRR_PHYS_BASE9,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBase9),
758         (MSR_MTRR_PHYS_BASEA,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBaseA),
759         (MSR_MTRR_PHYS_BASEB,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBaseB),
760         (MSR_MTRR_PHYS_BASEC,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBaseC),
761         (MSR_MTRR_PHYS_BASED,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBaseD),
762         (MSR_MTRR_PHYS_BASEE,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBaseE),
763         (MSR_MTRR_PHYS_BASEF,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysBaseF),
764         (MSR_MTRR_PHYS_MASK0,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask0),
765         (MSR_MTRR_PHYS_MASK1,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask1),
766         (MSR_MTRR_PHYS_MASK2,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask2),
767         (MSR_MTRR_PHYS_MASK3,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask3),
768         (MSR_MTRR_PHYS_MASK4,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask4),
769         (MSR_MTRR_PHYS_MASK5,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask5),
770         (MSR_MTRR_PHYS_MASK6,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask6),
771         (MSR_MTRR_PHYS_MASK7,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask7),
772         (MSR_MTRR_PHYS_MASK8,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask8),
773         (MSR_MTRR_PHYS_MASK9,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMask9),
774         (MSR_MTRR_PHYS_MASKA,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMaskA),
775         (MSR_MTRR_PHYS_MASKB,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMaskB),
776         (MSR_MTRR_PHYS_MASKC,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMaskC),
777         (MSR_MTRR_PHYS_MASKD,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMaskD),
778         (MSR_MTRR_PHYS_MASKE,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMaskE),
779         (MSR_MTRR_PHYS_MASKF,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrPhysMaskF),
780         (MSR_MTRR_FIX64K_00000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix64k00000),
781         (MSR_MTRR_FIX16K_80000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix16k80000),
782         (MSR_MTRR_FIX16K_A0000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix16kA0000),
783         (MSR_MTRR_FIX4K_C0000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix4kC0000),
784         (MSR_MTRR_FIX4K_C8000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix4kC8000),
785         (MSR_MTRR_FIX4K_D0000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix4kD0000),
786         (MSR_MTRR_FIX4K_D8000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix4kD8000),
787         (MSR_MTRR_FIX4K_E0000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix4kE0000),
788         (MSR_MTRR_FIX4K_E8000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix4kE8000),
789         (MSR_MTRR_FIX4K_F0000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix4kF0000),
790         (MSR_MTRR_FIX4K_F8000,WHV_REGISTER_NAME_WHvX64RegisterMsrMtrrFix4kF8000),
791         (MSR_TSC_AUX,WHV_REGISTER_NAME_WHvX64RegisterTscAux),
792         (MSR_SPEC_CTRL,WHV_REGISTER_NAME_WHvX64RegisterSpecCtrl),
793         (MSR_PRED_CMD,WHV_REGISTER_NAME_WHvX64RegisterPredCmd),
794     ].into_iter().collect()
795 });
796 
797 impl From<&CpuIdEntry> for WHV_X64_CPUID_RESULT {
from(entry: &CpuIdEntry) -> Self798     fn from(entry: &CpuIdEntry) -> Self {
799         WHV_X64_CPUID_RESULT {
800             Function: entry.function,
801             Eax: entry.cpuid.eax,
802             Ebx: entry.cpuid.ebx,
803             Ecx: entry.cpuid.ecx,
804             Edx: entry.cpuid.edx,
805             ..Default::default()
806         }
807     }
808 }
809 
810 /// WHPX's LAPIC setting API just lets you supply an arbitrary buffer and size. WHPX seems to use
811 /// the full 4K size of the APIC, although we only care about the state of the registers which live
812 /// in the first 1k.
813 #[repr(C)]
814 pub struct WhpxLapicState {
815     pub regs: [u32; 1024],
816 }
817 
818 impl From<&WhpxLapicState> for LapicState {
from(item: &WhpxLapicState) -> Self819     fn from(item: &WhpxLapicState) -> Self {
820         let mut state = LapicState { regs: [0; 64] };
821         for i in 0..64 {
822             state.regs[i] = item.regs[i * 4];
823         }
824         state
825     }
826 }
827 
828 impl From<&LapicState> for WhpxLapicState {
from(item: &LapicState) -> Self829     fn from(item: &LapicState) -> Self {
830         let mut state = WhpxLapicState { regs: [0; 1024] };
831         for i in 0..64 {
832             state.regs[i * 4] = item.regs[i];
833         }
834         state
835     }
836 }
837