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