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 ®_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 ®_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 ®_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 ®_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 ®_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