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