1use super::SegmentRegister;
7use super::TableRegister;
8use super::X86PartitionCapabilities;
9use crate::state::HvRegisterState;
10use crate::state::StateElement;
11use crate::state::state_trait;
12use hvdef::HV_MESSAGE_SIZE;
13use hvdef::HvInternalActivityRegister;
14use hvdef::HvRegisterValue;
15use hvdef::HvX64InterruptStateRegister;
16use hvdef::HvX64PendingEventReg0;
17use hvdef::HvX64PendingExceptionEvent;
18use hvdef::HvX64PendingExtIntEvent;
19use hvdef::HvX64PendingInterruptionRegister;
20use hvdef::HvX64PendingInterruptionType;
21use hvdef::HvX64RegisterName;
22use hvdef::HvX64SegmentRegister;
23use hvdef::HvX64TableRegister;
24use inspect::Inspect;
25use mesh_protobuf::Protobuf;
26use std::fmt::Debug;
27use vm_topology::processor::x86::X86VpInfo;
28use x86defs::RFlags;
29use x86defs::X64_CR0_CD;
30use x86defs::X64_CR0_ET;
31use x86defs::X64_CR0_NW;
32use x86defs::X64_EFER_NXE;
33use x86defs::X86X_MSR_DEFAULT_PAT;
34use x86defs::apic::APIC_BASE_PAGE;
35use x86defs::apic::ApicBase;
36use x86defs::apic::ApicVersion;
37use x86defs::xsave::DEFAULT_MXCSR;
38use x86defs::xsave::Fxsave;
39use x86defs::xsave::INIT_FCW;
40use x86defs::xsave::XCOMP_COMPRESSED;
41use x86defs::xsave::XFEATURE_SSE;
42use x86defs::xsave::XFEATURE_X87;
43use x86defs::xsave::XFEATURE_YMM;
44use x86defs::xsave::XSAVE_LEGACY_LEN;
45use x86defs::xsave::XSAVE_VARIABLE_OFFSET;
46use x86defs::xsave::XsaveHeader;
47use zerocopy::FromBytes;
48use zerocopy::FromZeros;
49use zerocopy::Immutable;
50use zerocopy::IntoBytes;
51use zerocopy::KnownLayout;
52use zerocopy::Ref;
53
54#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
55#[mesh(package = "virt.x86")]
56pub struct Registers {
57 #[inspect(hex)]
58 #[mesh(1)]
59 pub rax: u64,
60 #[inspect(hex)]
61 #[mesh(2)]
62 pub rcx: u64,
63 #[inspect(hex)]
64 #[mesh(3)]
65 pub rdx: u64,
66 #[inspect(hex)]
67 #[mesh(4)]
68 pub rbx: u64,
69 #[inspect(hex)]
70 #[mesh(5)]
71 pub rsp: u64,
72 #[inspect(hex)]
73 #[mesh(6)]
74 pub rbp: u64,
75 #[inspect(hex)]
76 #[mesh(7)]
77 pub rsi: u64,
78 #[inspect(hex)]
79 #[mesh(8)]
80 pub rdi: u64,
81 #[inspect(hex)]
82 #[mesh(9)]
83 pub r8: u64,
84 #[inspect(hex)]
85 #[mesh(10)]
86 pub r9: u64,
87 #[inspect(hex)]
88 #[mesh(11)]
89 pub r10: u64,
90 #[inspect(hex)]
91 #[mesh(12)]
92 pub r11: u64,
93 #[inspect(hex)]
94 #[mesh(13)]
95 pub r12: u64,
96 #[inspect(hex)]
97 #[mesh(14)]
98 pub r13: u64,
99 #[inspect(hex)]
100 #[mesh(15)]
101 pub r14: u64,
102 #[inspect(hex)]
103 #[mesh(16)]
104 pub r15: u64,
105 #[inspect(hex)]
106 #[mesh(17)]
107 pub rip: u64,
108 #[inspect(hex)]
109 #[mesh(18)]
110 pub rflags: u64,
111 #[mesh(19)]
112 pub cs: SegmentRegister,
113 #[mesh(20)]
114 pub ds: SegmentRegister,
115 #[mesh(21)]
116 pub es: SegmentRegister,
117 #[mesh(22)]
118 pub fs: SegmentRegister,
119 #[mesh(23)]
120 pub gs: SegmentRegister,
121 #[mesh(24)]
122 pub ss: SegmentRegister,
123 #[mesh(25)]
124 pub tr: SegmentRegister,
125 #[mesh(26)]
126 pub ldtr: SegmentRegister,
127 #[mesh(27)]
128 pub gdtr: TableRegister,
129 #[mesh(28)]
130 pub idtr: TableRegister,
131 #[inspect(hex)]
132 #[mesh(29)]
133 pub cr0: u64,
134 #[inspect(hex)]
135 #[mesh(30)]
136 pub cr2: u64,
137 #[inspect(hex)]
138 #[mesh(31)]
139 pub cr3: u64,
140 #[inspect(hex)]
141 #[mesh(32)]
142 pub cr4: u64,
143 #[inspect(hex)]
144 #[mesh(33)]
145 pub cr8: u64,
146 #[inspect(hex)]
147 #[mesh(34)]
148 pub efer: u64,
149}
150
151impl HvRegisterState<HvX64RegisterName, 34> for Registers {
152 fn names(&self) -> &'static [HvX64RegisterName; 34] {
153 &[
154 HvX64RegisterName::Rax,
155 HvX64RegisterName::Rcx,
156 HvX64RegisterName::Rdx,
157 HvX64RegisterName::Rbx,
158 HvX64RegisterName::Rsp,
159 HvX64RegisterName::Rbp,
160 HvX64RegisterName::Rsi,
161 HvX64RegisterName::Rdi,
162 HvX64RegisterName::R8,
163 HvX64RegisterName::R9,
164 HvX64RegisterName::R10,
165 HvX64RegisterName::R11,
166 HvX64RegisterName::R12,
167 HvX64RegisterName::R13,
168 HvX64RegisterName::R14,
169 HvX64RegisterName::R15,
170 HvX64RegisterName::Rip,
171 HvX64RegisterName::Rflags,
172 HvX64RegisterName::Cr0,
173 HvX64RegisterName::Cr2,
174 HvX64RegisterName::Cr3,
175 HvX64RegisterName::Cr4,
176 HvX64RegisterName::Cr8,
177 HvX64RegisterName::Efer,
178 HvX64RegisterName::Cs,
179 HvX64RegisterName::Ds,
180 HvX64RegisterName::Es,
181 HvX64RegisterName::Fs,
182 HvX64RegisterName::Gs,
183 HvX64RegisterName::Ss,
184 HvX64RegisterName::Tr,
185 HvX64RegisterName::Ldtr,
186 HvX64RegisterName::Gdtr,
187 HvX64RegisterName::Idtr,
188 ]
189 }
190
191 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
192 for (dest, src) in it.zip([
193 self.rax.into(),
194 self.rcx.into(),
195 self.rdx.into(),
196 self.rbx.into(),
197 self.rsp.into(),
198 self.rbp.into(),
199 self.rsi.into(),
200 self.rdi.into(),
201 self.r8.into(),
202 self.r9.into(),
203 self.r10.into(),
204 self.r11.into(),
205 self.r12.into(),
206 self.r13.into(),
207 self.r14.into(),
208 self.r15.into(),
209 self.rip.into(),
210 self.rflags.into(),
211 self.cr0.into(),
212 self.cr2.into(),
213 self.cr3.into(),
214 self.cr4.into(),
215 self.cr8.into(),
216 self.efer.into(),
217 HvX64SegmentRegister::from(self.cs).into(),
218 HvX64SegmentRegister::from(self.ds).into(),
219 HvX64SegmentRegister::from(self.es).into(),
220 HvX64SegmentRegister::from(self.fs).into(),
221 HvX64SegmentRegister::from(self.gs).into(),
222 HvX64SegmentRegister::from(self.ss).into(),
223 HvX64SegmentRegister::from(self.tr).into(),
224 HvX64SegmentRegister::from(self.ldtr).into(),
225 HvX64TableRegister::from(self.gdtr).into(),
226 HvX64TableRegister::from(self.idtr).into(),
227 ]) {
228 *dest = src;
229 }
230 }
231
232 fn set_values(&mut self, mut it: impl Iterator<Item = HvRegisterValue>) {
233 for (dest, src) in [
234 &mut self.rax,
235 &mut self.rcx,
236 &mut self.rdx,
237 &mut self.rbx,
238 &mut self.rsp,
239 &mut self.rbp,
240 &mut self.rsi,
241 &mut self.rdi,
242 &mut self.r8,
243 &mut self.r9,
244 &mut self.r10,
245 &mut self.r11,
246 &mut self.r12,
247 &mut self.r13,
248 &mut self.r14,
249 &mut self.r15,
250 &mut self.rip,
251 &mut self.rflags,
252 &mut self.cr0,
253 &mut self.cr2,
254 &mut self.cr3,
255 &mut self.cr4,
256 &mut self.cr8,
257 &mut self.efer,
258 ]
259 .into_iter()
260 .zip(&mut it)
261 {
262 *dest = src.as_u64();
263 }
264
265 for (dest, src) in [
266 &mut self.cs,
267 &mut self.ds,
268 &mut self.es,
269 &mut self.fs,
270 &mut self.gs,
271 &mut self.ss,
272 &mut self.tr,
273 &mut self.ldtr,
274 ]
275 .into_iter()
276 .zip(&mut it)
277 {
278 *dest = src.as_segment().into();
279 }
280
281 for (dest, src) in [&mut self.gdtr, &mut self.idtr].into_iter().zip(it) {
282 *dest = src.as_table().into();
283 }
284 }
285}
286
287impl StateElement<X86PartitionCapabilities, X86VpInfo> for Registers {
288 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
289 true
290 }
291
292 fn at_reset(caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
293 let cs = SegmentRegister {
294 base: 0xffff0000,
295 limit: 0xffff,
296 selector: 0xf000,
297 attributes: 0x9b,
298 };
299 let ds = SegmentRegister {
300 base: 0,
301 limit: 0xffff,
302 selector: 0,
303 attributes: 0x93,
304 };
305 let tr = SegmentRegister {
306 base: 0,
307 limit: 0xffff,
308 selector: 0,
309 attributes: 0x8b,
310 };
311 let ldtr = SegmentRegister {
312 base: 0,
313 limit: 0xffff,
314 selector: 0,
315 attributes: 0x82,
316 };
317 let gdtr = TableRegister {
318 base: 0,
319 limit: 0xffff,
320 };
321 let efer = if caps.nxe_forced_on { X64_EFER_NXE } else { 0 };
322 Self {
323 rax: 0,
324 rcx: 0,
325 rdx: caps.reset_rdx,
326 rbx: 0,
327 rbp: 0,
328 rsp: 0,
329 rsi: 0,
330 rdi: 0,
331 r8: 0,
332 r9: 0,
333 r10: 0,
334 r11: 0,
335 r12: 0,
336 r13: 0,
337 r14: 0,
338 r15: 0,
339 rip: 0xfff0,
340 rflags: RFlags::at_reset().into(),
341 cs,
342 ds,
343 es: ds,
344 fs: ds,
345 gs: ds,
346 ss: ds,
347 tr,
348 ldtr,
349 gdtr,
350 idtr: gdtr,
351 cr0: X64_CR0_ET | X64_CR0_CD | X64_CR0_NW,
352 cr2: 0,
353 cr3: 0,
354 cr4: 0,
355 cr8: 0,
356 efer,
357 }
358 }
359}
360
361#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
362#[mesh(package = "virt.x86")]
363pub struct Activity {
364 #[mesh(1)]
365 pub mp_state: MpState,
366 #[mesh(2)]
367 pub nmi_pending: bool,
368 #[mesh(3)]
369 pub nmi_masked: bool,
370 #[mesh(4)]
371 pub interrupt_shadow: bool,
372 #[mesh(5)]
373 pub pending_event: Option<PendingEvent>,
374 #[mesh(6)]
375 pub pending_interruption: Option<PendingInterruption>,
376}
377
378#[derive(Copy, Clone, Debug, PartialEq, Eq, Protobuf, Inspect)]
379#[mesh(package = "virt.x86")]
380pub enum MpState {
381 #[mesh(1)]
382 Running,
383 #[mesh(2)]
384 WaitForSipi,
385 #[mesh(3)]
386 Halted,
387 #[mesh(4)]
388 Idle,
389}
390
391impl Default for MpState {
392 fn default() -> Self {
393 Self::Running
394 }
395}
396
397impl HvRegisterState<HvX64RegisterName, 4> for Activity {
400 fn names(&self) -> &'static [HvX64RegisterName; 4] {
401 &[
402 HvX64RegisterName::InternalActivityState,
403 HvX64RegisterName::PendingInterruption,
404 HvX64RegisterName::InterruptState,
405 HvX64RegisterName::PendingEvent0,
406 ]
407 }
408
409 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
410 let mut activity = HvInternalActivityRegister::from(0);
411 match self.mp_state {
412 MpState::Running => {}
413 MpState::WaitForSipi => {
414 activity.set_startup_suspend(true);
415 }
416 MpState::Halted => {
417 activity.set_halt_suspend(true);
418 }
419 MpState::Idle => {
420 activity.set_idle_suspend(true);
421 }
422 };
423
424 let pending_event = if let Some(event) = self.pending_event {
425 match event {
426 PendingEvent::Exception {
427 vector,
428 error_code,
429 parameter,
430 } => HvX64PendingExceptionEvent::new()
431 .with_event_pending(true)
432 .with_event_type(hvdef::HV_X64_PENDING_EVENT_EXCEPTION)
433 .with_vector(vector.into())
434 .with_deliver_error_code(error_code.is_some())
435 .with_error_code(error_code.unwrap_or(0))
436 .with_exception_parameter(parameter)
437 .into(),
438
439 PendingEvent::ExtInt { vector } => HvX64PendingExtIntEvent::new()
440 .with_event_pending(true)
441 .with_event_type(hvdef::HV_X64_PENDING_EVENT_EXT_INT)
442 .with_vector(vector)
443 .into(),
444 }
445 } else {
446 0
447 };
448
449 let mut pending_interruption = HvX64PendingInterruptionRegister::new();
450 if let Some(interruption) = self.pending_interruption {
451 pending_interruption.set_interruption_pending(true);
452 let ty = match interruption {
453 PendingInterruption::Exception { vector, error_code } => {
454 pending_interruption.set_interruption_vector(vector.into());
455 pending_interruption.set_deliver_error_code(error_code.is_some());
456 pending_interruption.set_error_code(error_code.unwrap_or(0));
457 HvX64PendingInterruptionType::HV_X64_PENDING_EXCEPTION
458 }
459 PendingInterruption::Interrupt { vector } => {
460 pending_interruption.set_interruption_vector(vector.into());
461 HvX64PendingInterruptionType::HV_X64_PENDING_INTERRUPT
462 }
463 PendingInterruption::Nmi => HvX64PendingInterruptionType::HV_X64_PENDING_NMI,
464 };
465 pending_interruption.set_interruption_type(ty.0);
466 }
467
468 let interrupt_state = HvX64InterruptStateRegister::new()
469 .with_nmi_masked(self.nmi_masked)
470 .with_interrupt_shadow(self.interrupt_shadow);
471
472 for (dest, src) in it.zip([
473 HvRegisterValue::from(u64::from(activity)),
474 u64::from(pending_interruption).into(),
475 u64::from(interrupt_state).into(),
476 pending_event.into(),
477 ]) {
478 *dest = src;
479 }
480 }
481
482 fn set_values(&mut self, mut it: impl Iterator<Item = HvRegisterValue>) {
483 let activity = HvInternalActivityRegister::from(it.next().unwrap().as_u64());
484 let interruption = HvX64PendingInterruptionRegister::from(it.next().unwrap().as_u64());
485 let interrupt_state = HvX64InterruptStateRegister::from(it.next().unwrap().as_u64());
486 let event = HvX64PendingEventReg0::from(it.next().unwrap().as_u128());
487
488 let mp_state = if activity.startup_suspend() {
489 MpState::WaitForSipi
490 } else if activity.halt_suspend() {
491 MpState::Halted
492 } else if activity.idle_suspend() {
493 MpState::Idle
494 } else {
495 MpState::Running
496 };
497
498 let pending_event = event.event_pending().then(|| match event.event_type() {
499 hvdef::HV_X64_PENDING_EVENT_EXCEPTION => {
500 let event = HvX64PendingExceptionEvent::from(u128::from(event));
501 PendingEvent::Exception {
502 vector: event.vector().try_into().expect("exception code is 8 bits"),
503 error_code: event.deliver_error_code().then(|| event.error_code()),
504 parameter: event.exception_parameter(),
505 }
506 }
507 hvdef::HV_X64_PENDING_EVENT_EXT_INT => {
508 let event = HvX64PendingExtIntEvent::from(u128::from(event));
509 PendingEvent::ExtInt {
510 vector: event.vector(),
511 }
512 }
513 ty => panic!("unhandled event type: {}", ty),
514 });
515
516 let pending_interruption = interruption.interruption_pending().then(|| {
517 match HvX64PendingInterruptionType(interruption.interruption_type()) {
518 HvX64PendingInterruptionType::HV_X64_PENDING_INTERRUPT => {
519 PendingInterruption::Interrupt {
520 vector: interruption
521 .interruption_vector()
522 .try_into()
523 .expect("x86 vector is 8 bits"),
524 }
525 }
526 HvX64PendingInterruptionType::HV_X64_PENDING_NMI => PendingInterruption::Nmi,
527 HvX64PendingInterruptionType::HV_X64_PENDING_EXCEPTION => {
528 PendingInterruption::Exception {
529 vector: interruption
530 .interruption_vector()
531 .try_into()
532 .expect("exception code is 8 bits"),
533 error_code: interruption
534 .deliver_error_code()
535 .then(|| interruption.error_code()),
536 }
537 }
538 ty => panic!("unhandled interruption type: {ty:?}"),
539 }
540 });
541
542 *self = Self {
543 mp_state,
544 nmi_pending: false,
545 nmi_masked: interrupt_state.nmi_masked(),
546 interrupt_shadow: interrupt_state.interrupt_shadow(),
547 pending_event,
548 pending_interruption,
549 };
550 }
551}
552
553impl StateElement<X86PartitionCapabilities, X86VpInfo> for Activity {
554 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
555 true
556 }
557
558 fn at_reset(_caps: &X86PartitionCapabilities, vp_info: &X86VpInfo) -> Self {
559 let mp_state = if vp_info.base.is_bsp() {
560 MpState::Running
561 } else {
562 MpState::WaitForSipi
565 };
566 Self {
567 mp_state,
568 nmi_pending: false,
569 nmi_masked: false,
570 interrupt_shadow: false,
571 pending_event: None,
572 pending_interruption: None,
573 }
574 }
575}
576
577#[derive(Debug, PartialEq, Eq, Copy, Clone, Protobuf, Inspect)]
578#[mesh(package = "virt.x86")]
579#[inspect(external_tag)]
580pub enum PendingEvent {
581 #[mesh(1)]
582 Exception {
583 #[mesh(1)]
584 vector: u8,
585 #[mesh(2)]
586 error_code: Option<u32>,
587 #[mesh(3)]
588 parameter: u64,
589 },
590 #[mesh(2)]
591 ExtInt {
592 #[mesh(1)]
593 vector: u8,
594 },
595}
596
597#[derive(Debug, PartialEq, Eq, Copy, Clone, Protobuf, Inspect)]
598#[mesh(package = "virt.x86")]
599#[inspect(external_tag)]
600pub enum PendingInterruption {
601 #[mesh(1)]
602 Exception {
603 #[mesh(1)]
604 vector: u8,
605 #[mesh(2)]
606 error_code: Option<u32>,
607 },
608 #[mesh(2)]
609 Interrupt {
610 #[mesh(1)]
611 vector: u8,
612 },
613 #[mesh(3)]
614 Nmi,
615}
616
617#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Protobuf, Inspect)]
618#[mesh(package = "virt.x86")]
619pub struct DebugRegisters {
620 #[mesh(1)]
621 #[inspect(hex)]
622 pub dr0: u64,
623 #[mesh(2)]
624 #[inspect(hex)]
625 pub dr1: u64,
626 #[mesh(3)]
627 #[inspect(hex)]
628 pub dr2: u64,
629 #[mesh(4)]
630 #[inspect(hex)]
631 pub dr3: u64,
632 #[mesh(5)]
633 #[inspect(hex)]
634 pub dr6: u64,
635 #[mesh(6)]
636 #[inspect(hex)]
637 pub dr7: u64,
638}
639
640impl HvRegisterState<HvX64RegisterName, 6> for DebugRegisters {
641 fn names(&self) -> &'static [HvX64RegisterName; 6] {
642 &[
643 HvX64RegisterName::Dr0,
644 HvX64RegisterName::Dr1,
645 HvX64RegisterName::Dr2,
646 HvX64RegisterName::Dr3,
647 HvX64RegisterName::Dr6,
648 HvX64RegisterName::Dr7,
649 ]
650 }
651
652 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
653 for (dest, src) in it.zip([
654 self.dr0.into(),
655 self.dr1.into(),
656 self.dr2.into(),
657 self.dr3.into(),
658 self.dr6.into(),
659 self.dr7.into(),
660 ]) {
661 *dest = src;
662 }
663 }
664
665 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
666 for (src, dest) in it.zip([
667 &mut self.dr0,
668 &mut self.dr1,
669 &mut self.dr2,
670 &mut self.dr3,
671 &mut self.dr6,
672 &mut self.dr7,
673 ]) {
674 *dest = src.as_u64();
675 }
676 }
677}
678
679impl StateElement<X86PartitionCapabilities, X86VpInfo> for DebugRegisters {
680 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
681 true
682 }
683
684 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
685 Self {
686 dr0: 0,
687 dr1: 0,
688 dr2: 0,
689 dr3: 0,
690 dr6: 0xffff0ff0,
691 dr7: 0x400,
692 }
693 }
694
695 fn can_compare(caps: &X86PartitionCapabilities) -> bool {
696 !caps.dr6_tsx_broken
700 }
701}
702
703#[derive(PartialEq, Eq, Protobuf)]
704#[mesh(package = "virt.x86")]
705pub struct Xsave {
706 #[mesh(1)]
707 pub data: Vec<u64>,
708}
709
710impl Xsave {
711 fn normalize(&mut self) {
712 let (mut fxsave, data) = Ref::<_, Fxsave>::from_prefix(self.data.as_mut_bytes()).unwrap();
713 let header = XsaveHeader::mut_from_prefix(data).unwrap().0; fxsave.mxcsr_mask = 0;
718
719 if header.xstate_bv & XFEATURE_SSE != 0 {
723 if fxsave.xmm.iter().eq(std::iter::repeat_n(&[0; 16], 16))
724 && fxsave.mxcsr == DEFAULT_MXCSR
725 {
726 header.xstate_bv &= !XFEATURE_SSE;
727 }
728 } else {
729 fxsave.xmm.fill(Default::default());
730 }
731
732 if header.xstate_bv & (XFEATURE_SSE | XFEATURE_YMM) == 0 {
733 fxsave.mxcsr = 0;
734 }
735
736 if header.xstate_bv & XFEATURE_X87 != 0 {
738 if fxsave.fcw == INIT_FCW
739 && fxsave.fsw == 0
740 && fxsave.ftw == 0
741 && fxsave.fop == 0
742 && fxsave.fip == 0
743 && fxsave.fdp == 0
744 && fxsave.st == [[0; 16]; 8]
745 {
746 fxsave.fcw = 0;
747 header.xstate_bv &= !XFEATURE_X87;
748 }
749 } else {
750 fxsave.fcw = 0;
751 fxsave.fsw = 0;
752 fxsave.ftw = 0;
753 fxsave.fop = 0;
754 fxsave.fip = 0;
755 fxsave.fdp = 0;
756 fxsave.st.fill(Default::default());
757 }
758
759 fxsave.unused.fill(0);
763 }
764
765 pub fn from_compact(data: &[u8], caps: &X86PartitionCapabilities) -> Self {
767 assert_eq!(data.len() % 8, 0);
768 let mut aligned = vec![0; data.len() / 8];
769 aligned.as_mut_bytes().copy_from_slice(data);
770 let mut this = Self { data: aligned };
771
772 this.normalize();
773
774 if caps.xsaves_state_bv_broken {
779 let header =
780 XsaveHeader::mut_from_prefix(&mut this.data.as_mut_bytes()[XSAVE_LEGACY_LEN..])
781 .unwrap()
782 .0; header.xstate_bv |= header.xcomp_bv & 0x1c00;
788 }
789
790 this
791 }
792
793 pub fn from_standard(src: &[u8], caps: &X86PartitionCapabilities) -> Self {
795 let mut this = Self {
796 data: vec![0; caps.xsave.compact_len as usize / 8],
797 };
798 this.data.as_mut_bytes()[..XSAVE_VARIABLE_OFFSET]
799 .copy_from_slice(&src[..XSAVE_VARIABLE_OFFSET]);
800
801 let (mut header, data) =
802 Ref::<_, XsaveHeader>::from_prefix(&mut this.data.as_mut_bytes()[XSAVE_LEGACY_LEN..])
803 .unwrap();
804
805 header.xcomp_bv = caps.xsave.features | caps.xsave.supervisor_features | XCOMP_COMPRESSED;
806 let mut cur = 0;
807 for i in 2..63 {
808 if header.xcomp_bv & (1 << i) != 0 {
809 let feature = &caps.xsave.feature_info[i];
810 let offset = feature.offset as usize;
811 let len = feature.len as usize;
812 if feature.align {
813 cur = (cur + 63) & !63;
814 }
815 if header.xstate_bv & (1 << i) != 0 {
816 data[cur..cur + len].copy_from_slice(&src[offset..offset + len]);
817 }
818 cur += len;
819 }
820 }
821 this.normalize();
822 this
823 }
824
825 pub fn write_standard(&self, data: &mut [u8], caps: &X86PartitionCapabilities) {
827 data[..XSAVE_LEGACY_LEN].copy_from_slice(self.fxsave().as_bytes());
829
830 let header = self.xsave_header();
832 data[XSAVE_LEGACY_LEN..XSAVE_VARIABLE_OFFSET].copy_from_slice(
833 XsaveHeader {
834 xcomp_bv: 0,
835 ..*header
836 }
837 .as_bytes(),
838 );
839
840 let mut cur = XSAVE_VARIABLE_OFFSET;
842 for i in 2..63 {
843 if header.xcomp_bv & (1 << i) != 0 {
844 let feature = &caps.xsave.feature_info[i];
845 let offset = feature.offset as usize;
846 let len = feature.len as usize;
847 if feature.align {
848 cur = (cur + 63) & !63;
849 }
850 if header.xstate_bv & (1 << i) != 0 {
851 data[offset..offset + len]
852 .copy_from_slice(&self.data.as_bytes()[cur..cur + len]);
853 }
854 cur += len;
855 }
856 }
857 }
858
859 pub fn compact(&self) -> &[u8] {
861 self.data.as_bytes()
862 }
863
864 pub fn fxsave(&self) -> Fxsave {
869 let mut fxsave = Fxsave::read_from_prefix(self.data.as_bytes()).unwrap().0; let header = self.xsave_header();
871 if header.xstate_bv & XFEATURE_X87 == 0 {
872 fxsave.fcw = INIT_FCW;
873 }
874 if header.xstate_bv & (XFEATURE_SSE | XFEATURE_YMM) == 0 {
875 fxsave.mxcsr = DEFAULT_MXCSR;
876 }
877 fxsave
878 }
879
880 fn xsave_header(&self) -> &XsaveHeader {
881 XsaveHeader::ref_from_prefix(&self.data.as_bytes()[XSAVE_LEGACY_LEN..])
882 .unwrap()
883 .0 }
885}
886
887impl Debug for Xsave {
888 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
889 f.debug_struct("Xsave")
890 .field("legacy", &format_args!("{:x?}", self.fxsave()))
891 .field("header", &format_args!("{:x?}", self.xsave_header()))
892 .field("data", &&self.data[XSAVE_VARIABLE_OFFSET / 8..])
893 .finish()
894 }
895}
896
897impl Inspect for Xsave {
898 fn inspect(&self, req: inspect::Request<'_>) {
899 let Fxsave {
900 fcw,
901 fsw,
902 ftw,
903 reserved: _,
904 fop,
905 fip,
906 fdp,
907 mxcsr,
908 mxcsr_mask,
909 st,
910 xmm,
911 reserved2: _,
912 unused: _,
913 } = self.fxsave();
914
915 let &XsaveHeader {
916 xstate_bv,
917 xcomp_bv,
918 reserved: _,
919 } = self.xsave_header();
920
921 let mut resp = req.respond();
922 resp.hex("fcw", fcw)
923 .hex("fsw", fsw)
924 .hex("ftw", ftw)
925 .hex("fop", fop)
926 .hex("fip", fip)
927 .hex("fdp", fdp)
928 .hex("mxcsr", mxcsr)
929 .hex("mxcsr_mask", mxcsr_mask)
930 .hex("xstate_bv", xstate_bv)
931 .hex("xcomp_bv", xcomp_bv);
932
933 for (st, name) in st
934 .iter()
935 .zip(["st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"])
936 {
937 resp.field(name, st);
938 }
939
940 for (xmm, name) in xmm.iter().zip([
941 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9",
942 "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
943 ]) {
944 resp.field(name, xmm);
945 }
946 }
947}
948
949impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xsave {
950 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
951 true
952 }
953
954 fn at_reset(caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
955 let mut data = vec![0; caps.xsave.compact_len as usize];
956 *XsaveHeader::mut_from_prefix(&mut data[XSAVE_LEGACY_LEN..])
957 .unwrap()
958 .0 = XsaveHeader {
959 xstate_bv: 0,
961 xcomp_bv: XCOMP_COMPRESSED | caps.xsave.features | caps.xsave.supervisor_features,
962 reserved: [0; 6],
963 };
964 Self::from_compact(&data, caps)
965 }
966}
967
968#[derive(PartialEq, Eq, Clone, Protobuf, Inspect)]
969#[mesh(package = "virt.x86")]
970#[inspect(hex)]
971pub struct Apic {
972 #[mesh(1)]
973 pub apic_base: u64,
974 #[inspect(with = "ApicRegisters::from")]
975 #[mesh(2)]
976 pub registers: [u32; 64],
977 #[inspect(iter_by_index)]
978 #[mesh(3)]
979 pub auto_eoi: [u32; 8],
980}
981
982impl Debug for Apic {
983 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
984 let Self {
985 apic_base,
986 registers,
987 auto_eoi,
988 } = self;
989 f.debug_struct("Apic")
990 .field("apic_base", &format_args!("{:#x}", apic_base))
991 .field("registers", &format_args!("{:#x?}", registers))
992 .field("registers", &format_args!("{:#x?}", auto_eoi))
993 .finish()
994 }
995}
996
997#[repr(C)]
998#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
999#[inspect(hex)]
1000pub struct ApicRegisters {
1001 #[inspect(skip)]
1002 pub reserved_0: [u32; 2],
1003 pub id: u32,
1004 pub version: u32,
1005 #[inspect(skip)]
1006 pub reserved_4: [u32; 4],
1007 pub tpr: u32, pub apr: u32, pub ppr: u32, pub eoi: u32, pub rrd: u32, pub ldr: u32, pub dfr: u32, pub svr: u32, #[inspect(iter_by_index)]
1016 pub isr: [u32; 8], #[inspect(iter_by_index)]
1018 pub tmr: [u32; 8], #[inspect(iter_by_index)]
1020 pub irr: [u32; 8], pub esr: u32, #[inspect(skip)]
1023 pub reserved_29: [u32; 6],
1024 pub lvt_cmci: u32,
1025 #[inspect(iter_by_index)]
1026 pub icr: [u32; 2], pub lvt_timer: u32,
1028 pub lvt_thermal: u32,
1029 pub lvt_pmc: u32,
1030 pub lvt_lint0: u32,
1031 pub lvt_lint1: u32,
1032 pub lvt_error: u32,
1033 pub timer_icr: u32, pub timer_ccr: u32, #[inspect(skip)]
1036 pub reserved_3a: [u32; 4],
1037 pub timer_dcr: u32, #[inspect(skip)]
1039 pub reserved_3f: u32,
1040}
1041
1042const _: () = assert!(size_of::<ApicRegisters>() == 0x100);
1043
1044impl From<&'_ [u32; 64]> for ApicRegisters {
1045 fn from(value: &'_ [u32; 64]) -> Self {
1046 Self::read_from_bytes(value.as_bytes()).unwrap()
1047 }
1048}
1049
1050impl From<ApicRegisters> for [u32; 64] {
1051 fn from(value: ApicRegisters) -> Self {
1052 Self::read_from_bytes(value.as_bytes()).unwrap()
1053 }
1054}
1055
1056#[repr(C)]
1057#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1058struct ApicRegister {
1059 value: u32,
1060 zero: [u32; 3],
1061}
1062
1063const HV_IRR_NMI_PENDING_SHIFT: u32 = 2;
1066
1067impl Apic {
1068 pub fn as_page(&self) -> [u8; 1024] {
1069 let mut bytes = [0; 1024];
1070 self.registers
1071 .map(|value| ApicRegister {
1072 value,
1073 zero: [0; 3],
1074 })
1075 .write_to(bytes.as_mut_slice())
1076 .unwrap();
1077 bytes
1078 }
1079
1080 pub fn from_page(apic_base: u64, page: &[u8; 1024]) -> Self {
1085 let registers = <[ApicRegister; 64]>::read_from_bytes(page.as_slice()).unwrap();
1086 Self {
1087 apic_base,
1088 registers: registers.map(|reg| reg.value),
1089 auto_eoi: [0; 8],
1090 }
1091 }
1092}
1093
1094impl StateElement<X86PartitionCapabilities, X86VpInfo> for Apic {
1095 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1096 true
1097 }
1098
1099 fn at_reset(caps: &X86PartitionCapabilities, vp_info: &X86VpInfo) -> Self {
1100 let x2apic = caps.x2apic_enabled;
1101
1102 let mut regs = ApicRegisters::new_zeroed();
1103 regs.id = if x2apic {
1104 vp_info.apic_id
1105 } else {
1106 vp_info.apic_id << 24
1107 };
1108 regs.version = ApicVersion::new()
1109 .with_version(0x14)
1110 .with_max_lvt_entry(5)
1111 .into();
1112 if x2apic {
1113 regs.ldr = ((vp_info.apic_id << 12) & 0xffff0000) | (1 << (vp_info.apic_id & 0xf));
1114 } else {
1115 regs.dfr = !0;
1116 }
1117 regs.svr = 0xff;
1118 regs.lvt_timer = 0x10000;
1119 regs.lvt_thermal = 0x10000;
1120 regs.lvt_pmc = 0x10000;
1121 regs.lvt_lint0 = 0x10000;
1122 regs.lvt_lint1 = 0x10000;
1123 regs.lvt_error = 0x10000;
1124
1125 let apic_base = ApicBase::new()
1126 .with_base_page(APIC_BASE_PAGE)
1127 .with_bsp(vp_info.base.is_bsp())
1128 .with_x2apic(x2apic)
1129 .with_enable(true);
1130
1131 Apic {
1132 apic_base: apic_base.into(),
1133 registers: regs.into(),
1134 auto_eoi: [0; 8],
1135 }
1136 }
1137
1138 fn can_compare(caps: &X86PartitionCapabilities) -> bool {
1139 caps.can_freeze_time
1142 }
1143}
1144
1145pub fn set_hv_apic_nmi_pending(page: &mut [u8], pending: bool) {
1147 page[0x200] &= !(1 << HV_IRR_NMI_PENDING_SHIFT);
1148 page[0x200] |= (pending as u8) << HV_IRR_NMI_PENDING_SHIFT;
1149}
1150
1151pub fn hv_apic_nmi_pending(page: &[u8]) -> bool {
1153 page[0x200] & (1 << HV_IRR_NMI_PENDING_SHIFT) != 0
1154}
1155
1156#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1157#[mesh(package = "virt.x86")]
1158pub struct Xcr0 {
1159 #[mesh(1)]
1160 #[inspect(hex)]
1161 pub value: u64,
1162}
1163
1164impl HvRegisterState<HvX64RegisterName, 1> for Xcr0 {
1165 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1166 &[HvX64RegisterName::Xfem]
1167 }
1168
1169 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1170 for (dest, src) in it.zip([self.value]) {
1171 *dest = src.into();
1172 }
1173 }
1174
1175 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1176 for (src, dest) in it.zip([&mut self.value]) {
1177 *dest = src.as_u64();
1178 }
1179 }
1180}
1181
1182impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xcr0 {
1183 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1184 caps.xsave.features != 0
1185 }
1186
1187 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1188 Self { value: 1 }
1189 }
1190}
1191
1192#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1193#[mesh(package = "virt.x86")]
1194pub struct Xss {
1195 #[mesh(1)]
1196 #[inspect(hex)]
1197 pub value: u64,
1198}
1199
1200impl HvRegisterState<HvX64RegisterName, 1> for Xss {
1201 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1202 &[HvX64RegisterName::Xss]
1203 }
1204
1205 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1206 for (dest, src) in it.zip([self.value]) {
1207 *dest = src.into();
1208 }
1209 }
1210
1211 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1212 for (src, dest) in it.zip([&mut self.value]) {
1213 *dest = src.as_u64();
1214 }
1215 }
1216}
1217
1218impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xss {
1219 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1220 caps.xsave.supervisor_features != 0
1221 }
1222
1223 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1224 Self { value: 0 }
1225 }
1226}
1227
1228#[repr(C)]
1229#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1230#[mesh(package = "virt.x86")]
1231pub struct Pat {
1232 #[mesh(1)]
1233 #[inspect(hex)]
1234 pub value: u64,
1235}
1236
1237impl HvRegisterState<HvX64RegisterName, 1> for Pat {
1238 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1239 &[HvX64RegisterName::Pat]
1240 }
1241
1242 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1243 for (dest, src) in it.zip([self.value]) {
1244 *dest = src.into();
1245 }
1246 }
1247
1248 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1249 for (src, dest) in it.zip([&mut self.value]) {
1250 *dest = src.as_u64();
1251 }
1252 }
1253}
1254
1255impl StateElement<X86PartitionCapabilities, X86VpInfo> for Pat {
1256 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1257 true
1258 }
1259
1260 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1261 Self {
1262 value: X86X_MSR_DEFAULT_PAT,
1263 }
1264 }
1265}
1266
1267#[repr(C)]
1268#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1269#[mesh(package = "virt.x86")]
1270#[inspect(hex)]
1271pub struct Mtrrs {
1272 #[mesh(1)]
1273 #[inspect(hex)]
1274 pub msr_mtrr_def_type: u64,
1275 #[mesh(2)]
1276 #[inspect(iter_by_index)]
1277 pub fixed: [u64; 11],
1278 #[mesh(3)]
1279 #[inspect(iter_by_index)]
1280 pub variable: [u64; 16],
1281}
1282
1283impl HvRegisterState<HvX64RegisterName, 28> for Mtrrs {
1284 fn names(&self) -> &'static [HvX64RegisterName; 28] {
1285 &[
1286 HvX64RegisterName::MsrMtrrDefType,
1287 HvX64RegisterName::MsrMtrrFix64k00000,
1288 HvX64RegisterName::MsrMtrrFix16k80000,
1289 HvX64RegisterName::MsrMtrrFix16kA0000,
1290 HvX64RegisterName::MsrMtrrFix4kC0000,
1291 HvX64RegisterName::MsrMtrrFix4kC8000,
1292 HvX64RegisterName::MsrMtrrFix4kD0000,
1293 HvX64RegisterName::MsrMtrrFix4kD8000,
1294 HvX64RegisterName::MsrMtrrFix4kE0000,
1295 HvX64RegisterName::MsrMtrrFix4kE8000,
1296 HvX64RegisterName::MsrMtrrFix4kF0000,
1297 HvX64RegisterName::MsrMtrrFix4kF8000,
1298 HvX64RegisterName::MsrMtrrPhysBase0,
1299 HvX64RegisterName::MsrMtrrPhysMask0,
1300 HvX64RegisterName::MsrMtrrPhysBase1,
1301 HvX64RegisterName::MsrMtrrPhysMask1,
1302 HvX64RegisterName::MsrMtrrPhysBase2,
1303 HvX64RegisterName::MsrMtrrPhysMask2,
1304 HvX64RegisterName::MsrMtrrPhysBase3,
1305 HvX64RegisterName::MsrMtrrPhysMask3,
1306 HvX64RegisterName::MsrMtrrPhysBase4,
1307 HvX64RegisterName::MsrMtrrPhysMask4,
1308 HvX64RegisterName::MsrMtrrPhysBase5,
1309 HvX64RegisterName::MsrMtrrPhysMask5,
1310 HvX64RegisterName::MsrMtrrPhysBase6,
1311 HvX64RegisterName::MsrMtrrPhysMask6,
1312 HvX64RegisterName::MsrMtrrPhysBase7,
1313 HvX64RegisterName::MsrMtrrPhysMask7,
1314 ]
1315 }
1316
1317 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1318 for (dest, src) in it.zip(
1319 [self.msr_mtrr_def_type]
1320 .into_iter()
1321 .chain(self.fixed)
1322 .chain(self.variable),
1323 ) {
1324 *dest = src.into();
1325 }
1326 }
1327
1328 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1329 for (src, dest) in it.zip(
1330 [&mut self.msr_mtrr_def_type]
1331 .into_iter()
1332 .chain(&mut self.fixed)
1333 .chain(&mut self.variable),
1334 ) {
1335 *dest = src.as_u64();
1336 }
1337 }
1338}
1339
1340impl StateElement<X86PartitionCapabilities, X86VpInfo> for Mtrrs {
1341 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1342 true
1343 }
1344
1345 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1346 Self {
1347 msr_mtrr_def_type: 0,
1348 fixed: [0; 11],
1349 variable: [0; 16],
1350 }
1351 }
1352}
1353
1354#[repr(C)]
1355#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1356#[mesh(package = "virt.x86")]
1357#[inspect(hex)]
1358pub struct VirtualMsrs {
1359 #[mesh(1)]
1360 pub kernel_gs_base: u64,
1361 #[mesh(2)]
1362 pub sysenter_cs: u64,
1363 #[mesh(3)]
1364 pub sysenter_eip: u64,
1365 #[mesh(4)]
1366 pub sysenter_esp: u64,
1367 #[mesh(5)]
1368 pub star: u64,
1369 #[mesh(6)]
1370 pub lstar: u64,
1371 #[mesh(7)]
1372 pub cstar: u64,
1373 #[mesh(8)]
1374 pub sfmask: u64,
1375}
1376
1377impl HvRegisterState<HvX64RegisterName, 8> for VirtualMsrs {
1378 fn names(&self) -> &'static [HvX64RegisterName; 8] {
1379 &[
1380 HvX64RegisterName::KernelGsBase,
1381 HvX64RegisterName::SysenterCs,
1382 HvX64RegisterName::SysenterEsp,
1383 HvX64RegisterName::SysenterEip,
1384 HvX64RegisterName::Star,
1385 HvX64RegisterName::Lstar,
1386 HvX64RegisterName::Cstar,
1387 HvX64RegisterName::Sfmask,
1388 ]
1389 }
1390
1391 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1392 for (dest, src) in it.zip([
1393 self.kernel_gs_base,
1394 self.sysenter_cs,
1395 self.sysenter_eip,
1396 self.sysenter_esp,
1397 self.star,
1398 self.lstar,
1399 self.cstar,
1400 self.sfmask,
1401 ]) {
1402 *dest = src.into();
1403 }
1404 }
1405
1406 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1407 for (src, dest) in it.zip([
1408 &mut self.kernel_gs_base,
1409 &mut self.sysenter_cs,
1410 &mut self.sysenter_eip,
1411 &mut self.sysenter_esp,
1412 &mut self.star,
1413 &mut self.lstar,
1414 &mut self.cstar,
1415 &mut self.sfmask,
1416 ]) {
1417 *dest = src.as_u64();
1418 }
1419 }
1420}
1421
1422impl StateElement<X86PartitionCapabilities, X86VpInfo> for VirtualMsrs {
1423 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1424 true
1425 }
1426
1427 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1428 Self {
1429 kernel_gs_base: 0,
1430 sysenter_cs: 0,
1431 sysenter_eip: 0,
1432 sysenter_esp: 0,
1433 star: 0,
1434 lstar: 0,
1435 cstar: 0,
1436 sfmask: 0,
1437 }
1438 }
1439}
1440
1441#[repr(C)]
1442#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1443#[mesh(package = "virt.x86")]
1444pub struct TscAux {
1445 #[mesh(1)]
1446 #[inspect(hex)]
1447 pub value: u64,
1448}
1449
1450impl HvRegisterState<HvX64RegisterName, 1> for TscAux {
1451 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1452 &[HvX64RegisterName::TscAux]
1453 }
1454
1455 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1456 for (dest, src) in it.zip([self.value]) {
1457 *dest = src.into();
1458 }
1459 }
1460
1461 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1462 for (src, dest) in it.zip([&mut self.value]) {
1463 *dest = src.as_u64();
1464 }
1465 }
1466}
1467
1468impl StateElement<X86PartitionCapabilities, X86VpInfo> for TscAux {
1469 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1470 caps.tsc_aux
1471 }
1472
1473 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1474 Default::default()
1475 }
1476}
1477
1478#[repr(C)]
1479#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1480#[mesh(package = "virt.x86")]
1481pub struct Tsc {
1482 #[mesh(1)]
1483 #[inspect(hex)]
1484 pub value: u64,
1485}
1486
1487impl HvRegisterState<HvX64RegisterName, 1> for Tsc {
1488 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1489 &[HvX64RegisterName::Tsc]
1490 }
1491
1492 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1493 for (dest, src) in it.zip([self.value]) {
1494 *dest = src.into();
1495 }
1496 }
1497
1498 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1499 for (src, dest) in it.zip([&mut self.value]) {
1500 *dest = src.as_u64();
1501 }
1502 }
1503}
1504
1505impl StateElement<X86PartitionCapabilities, X86VpInfo> for Tsc {
1506 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1507 true
1508 }
1509
1510 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1511 Self { value: 0 }
1512 }
1513
1514 fn can_compare(caps: &X86PartitionCapabilities) -> bool {
1515 caps.can_freeze_time
1516 }
1517}
1518
1519#[repr(C)]
1520#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1521#[mesh(package = "virt.x86")]
1522pub struct Cet {
1523 #[mesh(1)]
1524 #[inspect(hex)]
1525 pub scet: u64,
1526 }
1528
1529impl HvRegisterState<HvX64RegisterName, 1> for Cet {
1530 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1531 &[HvX64RegisterName::SCet]
1532 }
1533
1534 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1535 for (dest, src) in it.zip([self.scet]) {
1536 *dest = src.into();
1537 }
1538 }
1539
1540 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1541 for (src, dest) in it.zip([&mut self.scet]) {
1542 *dest = src.as_u64();
1543 }
1544 }
1545}
1546
1547impl StateElement<X86PartitionCapabilities, X86VpInfo> for Cet {
1548 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1549 caps.cet
1550 }
1551
1552 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1553 Self { scet: 0 }
1554 }
1555}
1556
1557#[repr(C)]
1558#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1559#[mesh(package = "virt.x86")]
1560#[inspect(hex)]
1561pub struct CetSs {
1562 #[mesh(1)]
1563 pub ssp: u64,
1564 #[mesh(2)]
1565 pub interrupt_ssp_table_addr: u64,
1566 }
1568
1569impl HvRegisterState<HvX64RegisterName, 2> for CetSs {
1570 fn names(&self) -> &'static [HvX64RegisterName; 2] {
1571 &[
1572 HvX64RegisterName::Ssp,
1573 HvX64RegisterName::InterruptSspTableAddr,
1574 ]
1575 }
1576
1577 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1578 for (dest, src) in it.zip([self.ssp, self.interrupt_ssp_table_addr]) {
1579 *dest = src.into();
1580 }
1581 }
1582
1583 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1584 for (src, dest) in it.zip([&mut self.ssp, &mut self.interrupt_ssp_table_addr]) {
1585 *dest = src.as_u64();
1586 }
1587 }
1588}
1589
1590impl StateElement<X86PartitionCapabilities, X86VpInfo> for CetSs {
1591 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1592 caps.cet_ss
1593 }
1594
1595 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1596 Default::default()
1597 }
1598}
1599
1600#[repr(C)]
1601#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1602#[mesh(package = "virt.x86")]
1603#[inspect(hex)]
1604pub struct SyntheticMsrs {
1605 #[mesh(1)]
1606 pub vp_assist_page: u64,
1607 #[mesh(2)]
1608 pub scontrol: u64,
1609 #[mesh(3)]
1610 pub siefp: u64,
1611 #[mesh(4)]
1612 pub simp: u64,
1613 #[mesh(5)]
1614 #[inspect(iter_by_index)]
1615 pub sint: [u64; 16],
1616}
1617
1618impl HvRegisterState<HvX64RegisterName, 20> for SyntheticMsrs {
1619 fn names(&self) -> &'static [HvX64RegisterName; 20] {
1620 &[
1621 HvX64RegisterName::VpAssistPage,
1622 HvX64RegisterName::Scontrol,
1623 HvX64RegisterName::Sifp,
1624 HvX64RegisterName::Sipp,
1625 HvX64RegisterName::Sint0,
1626 HvX64RegisterName::Sint1,
1627 HvX64RegisterName::Sint2,
1628 HvX64RegisterName::Sint3,
1629 HvX64RegisterName::Sint4,
1630 HvX64RegisterName::Sint5,
1631 HvX64RegisterName::Sint6,
1632 HvX64RegisterName::Sint7,
1633 HvX64RegisterName::Sint8,
1634 HvX64RegisterName::Sint9,
1635 HvX64RegisterName::Sint10,
1636 HvX64RegisterName::Sint11,
1637 HvX64RegisterName::Sint12,
1638 HvX64RegisterName::Sint13,
1639 HvX64RegisterName::Sint14,
1640 HvX64RegisterName::Sint15,
1641 ]
1642 }
1643 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1644 for (dest, src) in it.zip(
1645 [self.vp_assist_page, self.scontrol, self.siefp, self.simp]
1646 .into_iter()
1647 .chain(self.sint),
1648 ) {
1649 *dest = src.into();
1650 }
1651 }
1652
1653 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1654 for (src, dest) in it.zip(
1655 [
1656 &mut self.vp_assist_page,
1657 &mut self.scontrol,
1658 &mut self.siefp,
1659 &mut self.simp,
1660 ]
1661 .into_iter()
1662 .chain(&mut self.sint),
1663 ) {
1664 *dest = src.as_u64();
1665 }
1666 }
1667}
1668
1669impl StateElement<X86PartitionCapabilities, X86VpInfo> for SyntheticMsrs {
1670 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1671 caps.hv1
1672 }
1673
1674 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1675 Self {
1676 vp_assist_page: 0,
1677 scontrol: 1,
1678 siefp: 0,
1679 simp: 0,
1680 sint: [0x10000; 16],
1681 }
1682 }
1683}
1684
1685#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Protobuf, Inspect)]
1686#[mesh(package = "virt.x86")]
1687#[inspect(hex)]
1688pub struct SynicTimer {
1689 #[mesh(1)]
1690 pub config: u64,
1691 #[mesh(2)]
1692 pub count: u64,
1693 #[mesh(3)]
1694 pub adjustment: u64,
1695 #[mesh(4)]
1696 pub undelivered_message_expiration_time: Option<u64>,
1697}
1698
1699#[derive(Debug, Copy, Clone, Eq, PartialEq, Protobuf, Inspect)]
1700#[mesh(package = "virt.x86")]
1701pub struct SynicTimers {
1702 #[mesh(1)]
1703 #[inspect(iter_by_index)]
1704 pub timers: [SynicTimer; 4],
1705}
1706
1707impl SynicTimers {
1708 pub fn as_hv(&self) -> hvdef::HvSyntheticTimersState {
1709 let timers = self.timers.map(|timer| hvdef::HvStimerState {
1710 undelivered_message_pending: timer.undelivered_message_expiration_time.is_some().into(),
1711 reserved: 0,
1712 config: timer.config,
1713 count: timer.count,
1714 adjustment: timer.adjustment,
1715 undelivered_expiration_time: timer.undelivered_message_expiration_time.unwrap_or(0),
1716 });
1717
1718 hvdef::HvSyntheticTimersState {
1719 timers,
1720 reserved: [0; 5],
1721 }
1722 }
1723
1724 pub fn from_hv(state: hvdef::HvSyntheticTimersState) -> Self {
1725 let timers = state.timers.map(|timer| SynicTimer {
1726 config: timer.config,
1727 count: timer.count,
1728 adjustment: timer.adjustment,
1729 undelivered_message_expiration_time: (timer.undelivered_message_pending & 1 != 0)
1730 .then_some(timer.undelivered_expiration_time),
1731 });
1732 Self { timers }
1733 }
1734}
1735
1736impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicTimers {
1737 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1738 caps.hv1
1739 }
1740
1741 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1742 Self {
1743 timers: [SynicTimer::default(); 4],
1744 }
1745 }
1746
1747 fn can_compare(_caps: &X86PartitionCapabilities) -> bool {
1748 false
1751 }
1752}
1753
1754#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1755#[mesh(package = "virt.x86")]
1756pub struct SynicMessageQueues {
1757 #[mesh(1)]
1758 #[inspect(with = "|x| inspect::iter_by_index(x.iter().map(Vec::len))")]
1759 pub queues: [Vec<[u8; HV_MESSAGE_SIZE]>; 16],
1760}
1761
1762impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicMessageQueues {
1763 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1764 caps.hv1
1765 }
1766
1767 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1768 Default::default()
1769 }
1770}
1771
1772#[derive(Debug, Copy, Clone, PartialEq, Eq, Protobuf, Inspect)]
1773#[mesh(package = "virt.x86")]
1774#[inspect(skip)]
1775pub struct SynicMessagePage {
1776 #[mesh(1)]
1777 pub data: [u8; 4096],
1778}
1779
1780impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicMessagePage {
1781 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1782 caps.hv1
1783 }
1784
1785 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1786 Self { data: [0; 4096] }
1787 }
1788}
1789
1790#[derive(Debug, Copy, Clone, PartialEq, Eq, Protobuf, Inspect)]
1791#[mesh(package = "virt.x86")]
1792#[inspect(skip)]
1793pub struct SynicEventFlagsPage {
1794 #[mesh(1)]
1795 pub data: [u8; 4096],
1796}
1797
1798impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicEventFlagsPage {
1799 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1800 caps.hv1
1801 }
1802
1803 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1804 Self { data: [0; 4096] }
1805 }
1806}
1807
1808state_trait! {
1809 "Per-VP state",
1810 AccessVpState,
1811 X86PartitionCapabilities,
1812 X86VpInfo,
1813 VpSavedState,
1814 "virt.x86",
1815 (1, "registers", registers, set_registers, Registers),
1816 (2, "activity", activity, set_activity, Activity),
1817 (3, "xsave", xsave, set_xsave, Xsave),
1818 (4, "apic", apic, set_apic, Apic),
1819 (5, "xcr", xcr, set_xcr, Xcr0),
1820 (6, "xss", xss, set_xss, Xss),
1821 (7, "mtrrs", mtrrs, set_mtrrs, Mtrrs),
1822 (8, "pat", pat, set_pat, Pat),
1823 (9, "msrs", virtual_msrs, set_virtual_msrs, VirtualMsrs),
1824 (10, "drs", debug_regs, set_debug_regs, DebugRegisters),
1825 (11, "tsc", tsc, set_tsc, Tsc),
1826 (12, "cet", cet, set_cet, Cet),
1827 (13, "cet_ss", cet_ss, set_cet_ss, CetSs),
1828 (14, "tsc_aux", tsc_aux, set_tsc_aux, TscAux),
1829
1830 (100, "synic", synic_msrs, set_synic_msrs, SyntheticMsrs),
1832 (
1837 101,
1838 "simp",
1839 synic_message_page,
1840 set_synic_message_page,
1841 SynicMessagePage
1842 ),
1843 (
1844 102,
1845 "siefp",
1846 synic_event_flags_page,
1847 set_synic_event_flags_page,
1848 SynicEventFlagsPage
1849 ),
1850 (
1851 103,
1852 "synic_message_queues",
1853 synic_message_queues,
1854 set_synic_message_queues,
1855 SynicMessageQueues
1856 ),
1857 (104, "synic_timers", synic_timers, set_synic_timers, SynicTimers),
1858}
1859
1860pub fn x86_init<T: AccessVpState>(access: &mut T, vp_info: &X86VpInfo) -> Result<(), T::Error> {
1862 let cr0 = access.registers()?.cr0;
1864 let mut regs = Registers::at_reset(access.caps(), vp_info);
1865 let cr0_mask = X64_CR0_NW | X64_CR0_CD;
1866 regs.cr0 = (cr0 & cr0_mask) | (regs.cr0 & !cr0_mask);
1867 access.set_registers(®s)?;
1868 access.set_debug_regs(&StateElement::at_reset(access.caps(), vp_info))?;
1869
1870 let current_apic = access.apic()?;
1875 let mut apic = Apic::at_reset(access.caps(), vp_info);
1876 apic.registers[x86defs::apic::ApicRegister::ID.0 as usize] =
1877 current_apic.registers[x86defs::apic::ApicRegister::ID.0 as usize];
1878 apic.apic_base = current_apic.apic_base;
1879 access.set_apic(&apic)?;
1880
1881 if !vp_info.base.is_bsp() {
1883 let mut activity = access.activity()?;
1884 activity.mp_state = MpState::WaitForSipi;
1885 access.set_activity(&activity)?;
1886 }
1887
1888 Ok(())
1889}