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, Default)]
379#[mesh(package = "virt.x86")]
380pub enum MpState {
381 #[mesh(1)]
382 #[default]
383 Running,
384 #[mesh(2)]
385 WaitForSipi,
386 #[mesh(3)]
387 Halted,
388 #[mesh(4)]
389 Idle,
390}
391
392impl HvRegisterState<HvX64RegisterName, 4> for Activity {
395 fn names(&self) -> &'static [HvX64RegisterName; 4] {
396 &[
397 HvX64RegisterName::InternalActivityState,
398 HvX64RegisterName::PendingInterruption,
399 HvX64RegisterName::InterruptState,
400 HvX64RegisterName::PendingEvent0,
401 ]
402 }
403
404 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
405 let mut activity = HvInternalActivityRegister::from(0);
406 match self.mp_state {
407 MpState::Running => {}
408 MpState::WaitForSipi => {
409 activity.set_startup_suspend(true);
410 }
411 MpState::Halted => {
412 activity.set_halt_suspend(true);
413 }
414 MpState::Idle => {
415 activity.set_idle_suspend(true);
416 }
417 };
418
419 let pending_event = if let Some(event) = self.pending_event {
420 match event {
421 PendingEvent::Exception {
422 vector,
423 error_code,
424 parameter,
425 } => HvX64PendingExceptionEvent::new()
426 .with_event_pending(true)
427 .with_event_type(hvdef::HV_X64_PENDING_EVENT_EXCEPTION)
428 .with_vector(vector.into())
429 .with_deliver_error_code(error_code.is_some())
430 .with_error_code(error_code.unwrap_or(0))
431 .with_exception_parameter(parameter)
432 .into(),
433
434 PendingEvent::ExtInt { vector } => HvX64PendingExtIntEvent::new()
435 .with_event_pending(true)
436 .with_event_type(hvdef::HV_X64_PENDING_EVENT_EXT_INT)
437 .with_vector(vector)
438 .into(),
439 }
440 } else {
441 0
442 };
443
444 let mut pending_interruption = HvX64PendingInterruptionRegister::new();
445 if let Some(interruption) = self.pending_interruption {
446 pending_interruption.set_interruption_pending(true);
447 let ty = match interruption {
448 PendingInterruption::Exception { vector, error_code } => {
449 pending_interruption.set_interruption_vector(vector.into());
450 pending_interruption.set_deliver_error_code(error_code.is_some());
451 pending_interruption.set_error_code(error_code.unwrap_or(0));
452 HvX64PendingInterruptionType::HV_X64_PENDING_EXCEPTION
453 }
454 PendingInterruption::Interrupt { vector } => {
455 pending_interruption.set_interruption_vector(vector.into());
456 HvX64PendingInterruptionType::HV_X64_PENDING_INTERRUPT
457 }
458 PendingInterruption::Nmi => HvX64PendingInterruptionType::HV_X64_PENDING_NMI,
459 };
460 pending_interruption.set_interruption_type(ty.0);
461 }
462
463 let interrupt_state = HvX64InterruptStateRegister::new()
464 .with_nmi_masked(self.nmi_masked)
465 .with_interrupt_shadow(self.interrupt_shadow);
466
467 for (dest, src) in it.zip([
468 HvRegisterValue::from(u64::from(activity)),
469 u64::from(pending_interruption).into(),
470 u64::from(interrupt_state).into(),
471 pending_event.into(),
472 ]) {
473 *dest = src;
474 }
475 }
476
477 fn set_values(&mut self, mut it: impl Iterator<Item = HvRegisterValue>) {
478 let activity = HvInternalActivityRegister::from(it.next().unwrap().as_u64());
479 let interruption = HvX64PendingInterruptionRegister::from(it.next().unwrap().as_u64());
480 let interrupt_state = HvX64InterruptStateRegister::from(it.next().unwrap().as_u64());
481 let event = HvX64PendingEventReg0::from(it.next().unwrap().as_u128());
482
483 let mp_state = if activity.startup_suspend() {
484 MpState::WaitForSipi
485 } else if activity.halt_suspend() {
486 MpState::Halted
487 } else if activity.idle_suspend() {
488 MpState::Idle
489 } else {
490 MpState::Running
491 };
492
493 let pending_event = event.event_pending().then(|| match event.event_type() {
494 hvdef::HV_X64_PENDING_EVENT_EXCEPTION => {
495 let event = HvX64PendingExceptionEvent::from(u128::from(event));
496 PendingEvent::Exception {
497 vector: event.vector().try_into().expect("exception code is 8 bits"),
498 error_code: event.deliver_error_code().then(|| event.error_code()),
499 parameter: event.exception_parameter(),
500 }
501 }
502 hvdef::HV_X64_PENDING_EVENT_EXT_INT => {
503 let event = HvX64PendingExtIntEvent::from(u128::from(event));
504 PendingEvent::ExtInt {
505 vector: event.vector(),
506 }
507 }
508 ty => panic!("unhandled event type: {}", ty),
509 });
510
511 let pending_interruption = interruption.interruption_pending().then(|| {
512 match HvX64PendingInterruptionType(interruption.interruption_type()) {
513 HvX64PendingInterruptionType::HV_X64_PENDING_INTERRUPT => {
514 PendingInterruption::Interrupt {
515 vector: interruption
516 .interruption_vector()
517 .try_into()
518 .expect("x86 vector is 8 bits"),
519 }
520 }
521 HvX64PendingInterruptionType::HV_X64_PENDING_NMI => PendingInterruption::Nmi,
522 HvX64PendingInterruptionType::HV_X64_PENDING_EXCEPTION => {
523 PendingInterruption::Exception {
524 vector: interruption
525 .interruption_vector()
526 .try_into()
527 .expect("exception code is 8 bits"),
528 error_code: interruption
529 .deliver_error_code()
530 .then(|| interruption.error_code()),
531 }
532 }
533 ty => panic!("unhandled interruption type: {ty:?}"),
534 }
535 });
536
537 *self = Self {
538 mp_state,
539 nmi_pending: false,
540 nmi_masked: interrupt_state.nmi_masked(),
541 interrupt_shadow: interrupt_state.interrupt_shadow(),
542 pending_event,
543 pending_interruption,
544 };
545 }
546}
547
548impl StateElement<X86PartitionCapabilities, X86VpInfo> for Activity {
549 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
550 true
551 }
552
553 fn at_reset(_caps: &X86PartitionCapabilities, vp_info: &X86VpInfo) -> Self {
554 let mp_state = if vp_info.base.is_bsp() {
555 MpState::Running
556 } else {
557 MpState::WaitForSipi
560 };
561 Self {
562 mp_state,
563 nmi_pending: false,
564 nmi_masked: false,
565 interrupt_shadow: false,
566 pending_event: None,
567 pending_interruption: None,
568 }
569 }
570}
571
572#[derive(Debug, PartialEq, Eq, Copy, Clone, Protobuf, Inspect)]
573#[mesh(package = "virt.x86")]
574#[inspect(external_tag)]
575pub enum PendingEvent {
576 #[mesh(1)]
577 Exception {
578 #[mesh(1)]
579 vector: u8,
580 #[mesh(2)]
581 error_code: Option<u32>,
582 #[mesh(3)]
583 parameter: u64,
584 },
585 #[mesh(2)]
586 ExtInt {
587 #[mesh(1)]
588 vector: u8,
589 },
590}
591
592#[derive(Debug, PartialEq, Eq, Copy, Clone, Protobuf, Inspect)]
593#[mesh(package = "virt.x86")]
594#[inspect(external_tag)]
595pub enum PendingInterruption {
596 #[mesh(1)]
597 Exception {
598 #[mesh(1)]
599 vector: u8,
600 #[mesh(2)]
601 error_code: Option<u32>,
602 },
603 #[mesh(2)]
604 Interrupt {
605 #[mesh(1)]
606 vector: u8,
607 },
608 #[mesh(3)]
609 Nmi,
610}
611
612#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Protobuf, Inspect)]
613#[mesh(package = "virt.x86")]
614pub struct DebugRegisters {
615 #[mesh(1)]
616 #[inspect(hex)]
617 pub dr0: u64,
618 #[mesh(2)]
619 #[inspect(hex)]
620 pub dr1: u64,
621 #[mesh(3)]
622 #[inspect(hex)]
623 pub dr2: u64,
624 #[mesh(4)]
625 #[inspect(hex)]
626 pub dr3: u64,
627 #[mesh(5)]
628 #[inspect(hex)]
629 pub dr6: u64,
630 #[mesh(6)]
631 #[inspect(hex)]
632 pub dr7: u64,
633}
634
635impl HvRegisterState<HvX64RegisterName, 6> for DebugRegisters {
636 fn names(&self) -> &'static [HvX64RegisterName; 6] {
637 &[
638 HvX64RegisterName::Dr0,
639 HvX64RegisterName::Dr1,
640 HvX64RegisterName::Dr2,
641 HvX64RegisterName::Dr3,
642 HvX64RegisterName::Dr6,
643 HvX64RegisterName::Dr7,
644 ]
645 }
646
647 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
648 for (dest, src) in it.zip([
649 self.dr0.into(),
650 self.dr1.into(),
651 self.dr2.into(),
652 self.dr3.into(),
653 self.dr6.into(),
654 self.dr7.into(),
655 ]) {
656 *dest = src;
657 }
658 }
659
660 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
661 for (src, dest) in it.zip([
662 &mut self.dr0,
663 &mut self.dr1,
664 &mut self.dr2,
665 &mut self.dr3,
666 &mut self.dr6,
667 &mut self.dr7,
668 ]) {
669 *dest = src.as_u64();
670 }
671 }
672}
673
674impl StateElement<X86PartitionCapabilities, X86VpInfo> for DebugRegisters {
675 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
676 true
677 }
678
679 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
680 Self {
681 dr0: 0,
682 dr1: 0,
683 dr2: 0,
684 dr3: 0,
685 dr6: 0xffff0ff0,
686 dr7: 0x400,
687 }
688 }
689
690 fn can_compare(caps: &X86PartitionCapabilities) -> bool {
691 !caps.dr6_tsx_broken
695 }
696}
697
698#[derive(PartialEq, Eq, Protobuf)]
699#[mesh(package = "virt.x86")]
700pub struct Xsave {
701 #[mesh(1)]
702 pub data: Vec<u64>,
703}
704
705impl Xsave {
706 fn normalize(&mut self) {
707 let (mut fxsave, data) = Ref::<_, Fxsave>::from_prefix(self.data.as_mut_bytes()).unwrap();
708 let header = XsaveHeader::mut_from_prefix(data).unwrap().0; fxsave.mxcsr_mask = 0;
713
714 if header.xstate_bv & XFEATURE_SSE != 0 {
718 if fxsave.xmm.iter().eq(std::iter::repeat_n(&[0; 16], 16))
719 && fxsave.mxcsr == DEFAULT_MXCSR
720 {
721 header.xstate_bv &= !XFEATURE_SSE;
722 }
723 } else {
724 fxsave.xmm.fill(Default::default());
725 }
726
727 if header.xstate_bv & (XFEATURE_SSE | XFEATURE_YMM) == 0 {
728 fxsave.mxcsr = 0;
729 }
730
731 if header.xstate_bv & XFEATURE_X87 != 0 {
733 if fxsave.fcw == INIT_FCW
734 && fxsave.fsw == 0
735 && fxsave.ftw == 0
736 && fxsave.fop == 0
737 && fxsave.fip == 0
738 && fxsave.fdp == 0
739 && fxsave.st == [[0; 16]; 8]
740 {
741 fxsave.fcw = 0;
742 header.xstate_bv &= !XFEATURE_X87;
743 }
744 } else {
745 fxsave.fcw = 0;
746 fxsave.fsw = 0;
747 fxsave.ftw = 0;
748 fxsave.fop = 0;
749 fxsave.fip = 0;
750 fxsave.fdp = 0;
751 fxsave.st.fill(Default::default());
752 }
753
754 fxsave.unused.fill(0);
758 }
759
760 pub fn from_compact(data: &[u8], caps: &X86PartitionCapabilities) -> Self {
762 assert_eq!(data.len() % 8, 0);
763 let mut aligned = vec![0; data.len() / 8];
764 aligned.as_mut_bytes().copy_from_slice(data);
765 let mut this = Self { data: aligned };
766
767 this.normalize();
768
769 if caps.xsaves_state_bv_broken {
774 let header =
775 XsaveHeader::mut_from_prefix(&mut this.data.as_mut_bytes()[XSAVE_LEGACY_LEN..])
776 .unwrap()
777 .0; header.xstate_bv |= header.xcomp_bv & 0x1c00;
783 }
784
785 this
786 }
787
788 pub fn from_standard(src: &[u8], caps: &X86PartitionCapabilities) -> Self {
790 let mut this = Self {
791 data: vec![0; caps.xsave.compact_len as usize / 8],
792 };
793 this.data.as_mut_bytes()[..XSAVE_VARIABLE_OFFSET]
794 .copy_from_slice(&src[..XSAVE_VARIABLE_OFFSET]);
795
796 let (mut header, data) =
797 Ref::<_, XsaveHeader>::from_prefix(&mut this.data.as_mut_bytes()[XSAVE_LEGACY_LEN..])
798 .unwrap();
799
800 header.xcomp_bv = caps.xsave.features | caps.xsave.supervisor_features | XCOMP_COMPRESSED;
801 let mut cur = 0;
802 for i in 2..63 {
803 if header.xcomp_bv & (1 << i) != 0 {
804 let feature = &caps.xsave.feature_info[i];
805 let offset = feature.offset as usize;
806 let len = feature.len as usize;
807 if feature.align {
808 cur = (cur + 63) & !63;
809 }
810 if header.xstate_bv & (1 << i) != 0 {
811 data[cur..cur + len].copy_from_slice(&src[offset..offset + len]);
812 }
813 cur += len;
814 }
815 }
816 this.normalize();
817 this
818 }
819
820 pub fn write_standard(&self, data: &mut [u8], caps: &X86PartitionCapabilities) {
822 data[..XSAVE_LEGACY_LEN].copy_from_slice(self.fxsave().as_bytes());
824
825 let header = self.xsave_header();
827 data[XSAVE_LEGACY_LEN..XSAVE_VARIABLE_OFFSET].copy_from_slice(
828 XsaveHeader {
829 xcomp_bv: 0,
830 ..*header
831 }
832 .as_bytes(),
833 );
834
835 let mut cur = XSAVE_VARIABLE_OFFSET;
837 for i in 2..63 {
838 if header.xcomp_bv & (1 << i) != 0 {
839 let feature = &caps.xsave.feature_info[i];
840 let offset = feature.offset as usize;
841 let len = feature.len as usize;
842 if feature.align {
843 cur = (cur + 63) & !63;
844 }
845 if header.xstate_bv & (1 << i) != 0 {
846 data[offset..offset + len]
847 .copy_from_slice(&self.data.as_bytes()[cur..cur + len]);
848 }
849 cur += len;
850 }
851 }
852 }
853
854 pub fn compact(&self) -> &[u8] {
856 self.data.as_bytes()
857 }
858
859 pub fn fxsave(&self) -> Fxsave {
864 let mut fxsave = Fxsave::read_from_prefix(self.data.as_bytes()).unwrap().0; let header = self.xsave_header();
866 if header.xstate_bv & XFEATURE_X87 == 0 {
867 fxsave.fcw = INIT_FCW;
868 }
869 if header.xstate_bv & (XFEATURE_SSE | XFEATURE_YMM) == 0 {
870 fxsave.mxcsr = DEFAULT_MXCSR;
871 }
872 fxsave
873 }
874
875 fn xsave_header(&self) -> &XsaveHeader {
876 XsaveHeader::ref_from_prefix(&self.data.as_bytes()[XSAVE_LEGACY_LEN..])
877 .unwrap()
878 .0 }
880}
881
882impl Debug for Xsave {
883 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
884 f.debug_struct("Xsave")
885 .field("legacy", &format_args!("{:x?}", self.fxsave()))
886 .field("header", &format_args!("{:x?}", self.xsave_header()))
887 .field("data", &&self.data[XSAVE_VARIABLE_OFFSET / 8..])
888 .finish()
889 }
890}
891
892impl Inspect for Xsave {
893 fn inspect(&self, req: inspect::Request<'_>) {
894 let Fxsave {
895 fcw,
896 fsw,
897 ftw,
898 reserved: _,
899 fop,
900 fip,
901 fdp,
902 mxcsr,
903 mxcsr_mask,
904 st,
905 xmm,
906 reserved2: _,
907 unused: _,
908 } = self.fxsave();
909
910 let &XsaveHeader {
911 xstate_bv,
912 xcomp_bv,
913 reserved: _,
914 } = self.xsave_header();
915
916 let mut resp = req.respond();
917 resp.hex("fcw", fcw)
918 .hex("fsw", fsw)
919 .hex("ftw", ftw)
920 .hex("fop", fop)
921 .hex("fip", fip)
922 .hex("fdp", fdp)
923 .hex("mxcsr", mxcsr)
924 .hex("mxcsr_mask", mxcsr_mask)
925 .hex("xstate_bv", xstate_bv)
926 .hex("xcomp_bv", xcomp_bv);
927
928 for (st, name) in st
929 .iter()
930 .zip(["st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"])
931 {
932 resp.field(name, st);
933 }
934
935 for (xmm, name) in xmm.iter().zip([
936 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9",
937 "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
938 ]) {
939 resp.field(name, xmm);
940 }
941 }
942}
943
944impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xsave {
945 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
946 true
947 }
948
949 fn at_reset(caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
950 let mut data = vec![0; caps.xsave.compact_len as usize];
951 *XsaveHeader::mut_from_prefix(&mut data[XSAVE_LEGACY_LEN..])
952 .unwrap()
953 .0 = XsaveHeader {
954 xstate_bv: 0,
956 xcomp_bv: XCOMP_COMPRESSED | caps.xsave.features | caps.xsave.supervisor_features,
957 reserved: [0; 6],
958 };
959 Self::from_compact(&data, caps)
960 }
961}
962
963#[derive(PartialEq, Eq, Clone, Protobuf, Inspect)]
964#[mesh(package = "virt.x86")]
965#[inspect(hex)]
966pub struct Apic {
967 #[mesh(1)]
968 pub apic_base: u64,
969 #[inspect(with = "ApicRegisters::from")]
970 #[mesh(2)]
971 pub registers: [u32; 64],
972 #[inspect(iter_by_index)]
973 #[mesh(3)]
974 pub auto_eoi: [u32; 8],
975}
976
977impl Debug for Apic {
978 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
979 let Self {
980 apic_base,
981 registers,
982 auto_eoi,
983 } = self;
984 f.debug_struct("Apic")
985 .field("apic_base", &format_args!("{:#x}", apic_base))
986 .field("registers", &format_args!("{:#x?}", registers))
987 .field("registers", &format_args!("{:#x?}", auto_eoi))
988 .finish()
989 }
990}
991
992#[repr(C)]
993#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
994#[inspect(hex)]
995pub struct ApicRegisters {
996 #[inspect(skip)]
997 pub reserved_0: [u32; 2],
998 pub id: u32,
999 pub version: u32,
1000 #[inspect(skip)]
1001 pub reserved_4: [u32; 4],
1002 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)]
1011 pub isr: [u32; 8], #[inspect(iter_by_index)]
1013 pub tmr: [u32; 8], #[inspect(iter_by_index)]
1015 pub irr: [u32; 8], pub esr: u32, #[inspect(skip)]
1018 pub reserved_29: [u32; 6],
1019 pub lvt_cmci: u32,
1020 #[inspect(iter_by_index)]
1021 pub icr: [u32; 2], pub lvt_timer: u32,
1023 pub lvt_thermal: u32,
1024 pub lvt_pmc: u32,
1025 pub lvt_lint0: u32,
1026 pub lvt_lint1: u32,
1027 pub lvt_error: u32,
1028 pub timer_icr: u32, pub timer_ccr: u32, #[inspect(skip)]
1031 pub reserved_3a: [u32; 4],
1032 pub timer_dcr: u32, #[inspect(skip)]
1034 pub reserved_3f: u32,
1035}
1036
1037const _: () = assert!(size_of::<ApicRegisters>() == 0x100);
1038
1039impl From<&'_ [u32; 64]> for ApicRegisters {
1040 fn from(value: &'_ [u32; 64]) -> Self {
1041 Self::read_from_bytes(value.as_bytes()).unwrap()
1042 }
1043}
1044
1045impl From<ApicRegisters> for [u32; 64] {
1046 fn from(value: ApicRegisters) -> Self {
1047 Self::read_from_bytes(value.as_bytes()).unwrap()
1048 }
1049}
1050
1051#[repr(C)]
1052#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1053struct ApicRegister {
1054 value: u32,
1055 zero: [u32; 3],
1056}
1057
1058const HV_IRR_NMI_PENDING_SHIFT: u32 = 2;
1061
1062impl Apic {
1063 pub fn as_page(&self) -> [u8; 1024] {
1064 let mut bytes = [0; 1024];
1065 self.registers
1066 .map(|value| ApicRegister {
1067 value,
1068 zero: [0; 3],
1069 })
1070 .write_to(bytes.as_mut_slice())
1071 .unwrap();
1072 bytes
1073 }
1074
1075 pub fn from_page(apic_base: u64, page: &[u8; 1024]) -> Self {
1080 let registers = <[ApicRegister; 64]>::read_from_bytes(page.as_slice()).unwrap();
1081 Self {
1082 apic_base,
1083 registers: registers.map(|reg| reg.value),
1084 auto_eoi: [0; 8],
1085 }
1086 }
1087}
1088
1089impl StateElement<X86PartitionCapabilities, X86VpInfo> for Apic {
1090 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1091 true
1092 }
1093
1094 fn at_reset(caps: &X86PartitionCapabilities, vp_info: &X86VpInfo) -> Self {
1095 let x2apic = caps.x2apic_enabled;
1096
1097 let mut regs = ApicRegisters::new_zeroed();
1098 regs.id = if x2apic {
1099 vp_info.apic_id
1100 } else {
1101 vp_info.apic_id << 24
1102 };
1103 regs.version = ApicVersion::new()
1104 .with_version(0x14)
1105 .with_max_lvt_entry(5)
1106 .into();
1107 if x2apic {
1108 regs.ldr = ((vp_info.apic_id << 12) & 0xffff0000) | (1 << (vp_info.apic_id & 0xf));
1109 } else {
1110 regs.dfr = !0;
1111 }
1112 regs.svr = 0xff;
1113 regs.lvt_timer = 0x10000;
1114 regs.lvt_thermal = 0x10000;
1115 regs.lvt_pmc = 0x10000;
1116 regs.lvt_lint0 = 0x10000;
1117 regs.lvt_lint1 = 0x10000;
1118 regs.lvt_error = 0x10000;
1119
1120 let apic_base = ApicBase::new()
1121 .with_base_page(APIC_BASE_PAGE)
1122 .with_bsp(vp_info.base.is_bsp())
1123 .with_x2apic(x2apic)
1124 .with_enable(true);
1125
1126 Apic {
1127 apic_base: apic_base.into(),
1128 registers: regs.into(),
1129 auto_eoi: [0; 8],
1130 }
1131 }
1132
1133 fn can_compare(caps: &X86PartitionCapabilities) -> bool {
1134 caps.can_freeze_time
1137 }
1138}
1139
1140pub fn set_hv_apic_nmi_pending(page: &mut [u8], pending: bool) {
1142 page[0x200] &= !(1 << HV_IRR_NMI_PENDING_SHIFT);
1143 page[0x200] |= (pending as u8) << HV_IRR_NMI_PENDING_SHIFT;
1144}
1145
1146pub fn hv_apic_nmi_pending(page: &[u8]) -> bool {
1148 page[0x200] & (1 << HV_IRR_NMI_PENDING_SHIFT) != 0
1149}
1150
1151#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1152#[mesh(package = "virt.x86")]
1153pub struct Xcr0 {
1154 #[mesh(1)]
1155 #[inspect(hex)]
1156 pub value: u64,
1157}
1158
1159impl HvRegisterState<HvX64RegisterName, 1> for Xcr0 {
1160 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1161 &[HvX64RegisterName::Xfem]
1162 }
1163
1164 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1165 for (dest, src) in it.zip([self.value]) {
1166 *dest = src.into();
1167 }
1168 }
1169
1170 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1171 for (src, dest) in it.zip([&mut self.value]) {
1172 *dest = src.as_u64();
1173 }
1174 }
1175}
1176
1177impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xcr0 {
1178 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1179 caps.xsave.features != 0
1180 }
1181
1182 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1183 Self { value: 1 }
1184 }
1185}
1186
1187#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1188#[mesh(package = "virt.x86")]
1189pub struct Xss {
1190 #[mesh(1)]
1191 #[inspect(hex)]
1192 pub value: u64,
1193}
1194
1195impl HvRegisterState<HvX64RegisterName, 1> for Xss {
1196 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1197 &[HvX64RegisterName::Xss]
1198 }
1199
1200 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1201 for (dest, src) in it.zip([self.value]) {
1202 *dest = src.into();
1203 }
1204 }
1205
1206 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1207 for (src, dest) in it.zip([&mut self.value]) {
1208 *dest = src.as_u64();
1209 }
1210 }
1211}
1212
1213impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xss {
1214 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1215 caps.xsave.supervisor_features != 0
1216 }
1217
1218 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1219 Self { value: 0 }
1220 }
1221}
1222
1223#[repr(C)]
1224#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1225#[mesh(package = "virt.x86")]
1226pub struct Pat {
1227 #[mesh(1)]
1228 #[inspect(hex)]
1229 pub value: u64,
1230}
1231
1232impl HvRegisterState<HvX64RegisterName, 1> for Pat {
1233 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1234 &[HvX64RegisterName::Pat]
1235 }
1236
1237 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1238 for (dest, src) in it.zip([self.value]) {
1239 *dest = src.into();
1240 }
1241 }
1242
1243 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1244 for (src, dest) in it.zip([&mut self.value]) {
1245 *dest = src.as_u64();
1246 }
1247 }
1248}
1249
1250impl StateElement<X86PartitionCapabilities, X86VpInfo> for Pat {
1251 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1252 true
1253 }
1254
1255 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1256 Self {
1257 value: X86X_MSR_DEFAULT_PAT,
1258 }
1259 }
1260}
1261
1262#[repr(C)]
1263#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1264#[mesh(package = "virt.x86")]
1265#[inspect(hex)]
1266pub struct Mtrrs {
1267 #[mesh(1)]
1268 #[inspect(hex)]
1269 pub msr_mtrr_def_type: u64,
1270 #[mesh(2)]
1271 #[inspect(iter_by_index)]
1272 pub fixed: [u64; 11],
1273 #[mesh(3)]
1274 #[inspect(iter_by_index)]
1275 pub variable: [u64; 16],
1276}
1277
1278impl HvRegisterState<HvX64RegisterName, 28> for Mtrrs {
1279 fn names(&self) -> &'static [HvX64RegisterName; 28] {
1280 &[
1281 HvX64RegisterName::MsrMtrrDefType,
1282 HvX64RegisterName::MsrMtrrFix64k00000,
1283 HvX64RegisterName::MsrMtrrFix16k80000,
1284 HvX64RegisterName::MsrMtrrFix16kA0000,
1285 HvX64RegisterName::MsrMtrrFix4kC0000,
1286 HvX64RegisterName::MsrMtrrFix4kC8000,
1287 HvX64RegisterName::MsrMtrrFix4kD0000,
1288 HvX64RegisterName::MsrMtrrFix4kD8000,
1289 HvX64RegisterName::MsrMtrrFix4kE0000,
1290 HvX64RegisterName::MsrMtrrFix4kE8000,
1291 HvX64RegisterName::MsrMtrrFix4kF0000,
1292 HvX64RegisterName::MsrMtrrFix4kF8000,
1293 HvX64RegisterName::MsrMtrrPhysBase0,
1294 HvX64RegisterName::MsrMtrrPhysMask0,
1295 HvX64RegisterName::MsrMtrrPhysBase1,
1296 HvX64RegisterName::MsrMtrrPhysMask1,
1297 HvX64RegisterName::MsrMtrrPhysBase2,
1298 HvX64RegisterName::MsrMtrrPhysMask2,
1299 HvX64RegisterName::MsrMtrrPhysBase3,
1300 HvX64RegisterName::MsrMtrrPhysMask3,
1301 HvX64RegisterName::MsrMtrrPhysBase4,
1302 HvX64RegisterName::MsrMtrrPhysMask4,
1303 HvX64RegisterName::MsrMtrrPhysBase5,
1304 HvX64RegisterName::MsrMtrrPhysMask5,
1305 HvX64RegisterName::MsrMtrrPhysBase6,
1306 HvX64RegisterName::MsrMtrrPhysMask6,
1307 HvX64RegisterName::MsrMtrrPhysBase7,
1308 HvX64RegisterName::MsrMtrrPhysMask7,
1309 ]
1310 }
1311
1312 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1313 for (dest, src) in it.zip(
1314 [self.msr_mtrr_def_type]
1315 .into_iter()
1316 .chain(self.fixed)
1317 .chain(self.variable),
1318 ) {
1319 *dest = src.into();
1320 }
1321 }
1322
1323 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1324 for (src, dest) in it.zip(
1325 [&mut self.msr_mtrr_def_type]
1326 .into_iter()
1327 .chain(&mut self.fixed)
1328 .chain(&mut self.variable),
1329 ) {
1330 *dest = src.as_u64();
1331 }
1332 }
1333}
1334
1335impl StateElement<X86PartitionCapabilities, X86VpInfo> for Mtrrs {
1336 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1337 true
1338 }
1339
1340 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1341 Self {
1342 msr_mtrr_def_type: 0,
1343 fixed: [0; 11],
1344 variable: [0; 16],
1345 }
1346 }
1347}
1348
1349#[repr(C)]
1350#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1351#[mesh(package = "virt.x86")]
1352#[inspect(hex)]
1353pub struct VirtualMsrs {
1354 #[mesh(1)]
1355 pub kernel_gs_base: u64,
1356 #[mesh(2)]
1357 pub sysenter_cs: u64,
1358 #[mesh(3)]
1359 pub sysenter_eip: u64,
1360 #[mesh(4)]
1361 pub sysenter_esp: u64,
1362 #[mesh(5)]
1363 pub star: u64,
1364 #[mesh(6)]
1365 pub lstar: u64,
1366 #[mesh(7)]
1367 pub cstar: u64,
1368 #[mesh(8)]
1369 pub sfmask: u64,
1370}
1371
1372impl HvRegisterState<HvX64RegisterName, 8> for VirtualMsrs {
1373 fn names(&self) -> &'static [HvX64RegisterName; 8] {
1374 &[
1375 HvX64RegisterName::KernelGsBase,
1376 HvX64RegisterName::SysenterCs,
1377 HvX64RegisterName::SysenterEsp,
1378 HvX64RegisterName::SysenterEip,
1379 HvX64RegisterName::Star,
1380 HvX64RegisterName::Lstar,
1381 HvX64RegisterName::Cstar,
1382 HvX64RegisterName::Sfmask,
1383 ]
1384 }
1385
1386 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1387 for (dest, src) in it.zip([
1388 self.kernel_gs_base,
1389 self.sysenter_cs,
1390 self.sysenter_eip,
1391 self.sysenter_esp,
1392 self.star,
1393 self.lstar,
1394 self.cstar,
1395 self.sfmask,
1396 ]) {
1397 *dest = src.into();
1398 }
1399 }
1400
1401 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1402 for (src, dest) in it.zip([
1403 &mut self.kernel_gs_base,
1404 &mut self.sysenter_cs,
1405 &mut self.sysenter_eip,
1406 &mut self.sysenter_esp,
1407 &mut self.star,
1408 &mut self.lstar,
1409 &mut self.cstar,
1410 &mut self.sfmask,
1411 ]) {
1412 *dest = src.as_u64();
1413 }
1414 }
1415}
1416
1417impl StateElement<X86PartitionCapabilities, X86VpInfo> for VirtualMsrs {
1418 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1419 true
1420 }
1421
1422 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1423 Self {
1424 kernel_gs_base: 0,
1425 sysenter_cs: 0,
1426 sysenter_eip: 0,
1427 sysenter_esp: 0,
1428 star: 0,
1429 lstar: 0,
1430 cstar: 0,
1431 sfmask: 0,
1432 }
1433 }
1434}
1435
1436#[repr(C)]
1437#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1438#[mesh(package = "virt.x86")]
1439pub struct TscAux {
1440 #[mesh(1)]
1441 #[inspect(hex)]
1442 pub value: u64,
1443}
1444
1445impl HvRegisterState<HvX64RegisterName, 1> for TscAux {
1446 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1447 &[HvX64RegisterName::TscAux]
1448 }
1449
1450 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1451 for (dest, src) in it.zip([self.value]) {
1452 *dest = src.into();
1453 }
1454 }
1455
1456 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1457 for (src, dest) in it.zip([&mut self.value]) {
1458 *dest = src.as_u64();
1459 }
1460 }
1461}
1462
1463impl StateElement<X86PartitionCapabilities, X86VpInfo> for TscAux {
1464 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1465 caps.tsc_aux
1466 }
1467
1468 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1469 Default::default()
1470 }
1471}
1472
1473#[repr(C)]
1474#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1475#[mesh(package = "virt.x86")]
1476pub struct Tsc {
1477 #[mesh(1)]
1478 #[inspect(hex)]
1479 pub value: u64,
1480}
1481
1482impl HvRegisterState<HvX64RegisterName, 1> for Tsc {
1483 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1484 &[HvX64RegisterName::Tsc]
1485 }
1486
1487 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1488 for (dest, src) in it.zip([self.value]) {
1489 *dest = src.into();
1490 }
1491 }
1492
1493 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1494 for (src, dest) in it.zip([&mut self.value]) {
1495 *dest = src.as_u64();
1496 }
1497 }
1498}
1499
1500impl StateElement<X86PartitionCapabilities, X86VpInfo> for Tsc {
1501 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1502 true
1503 }
1504
1505 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1506 Self { value: 0 }
1507 }
1508
1509 fn can_compare(caps: &X86PartitionCapabilities) -> bool {
1510 caps.can_freeze_time
1511 }
1512}
1513
1514#[repr(C)]
1515#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1516#[mesh(package = "virt.x86")]
1517pub struct Cet {
1518 #[mesh(1)]
1519 #[inspect(hex)]
1520 pub scet: u64,
1521 }
1523
1524impl HvRegisterState<HvX64RegisterName, 1> for Cet {
1525 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1526 &[HvX64RegisterName::SCet]
1527 }
1528
1529 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1530 for (dest, src) in it.zip([self.scet]) {
1531 *dest = src.into();
1532 }
1533 }
1534
1535 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1536 for (src, dest) in it.zip([&mut self.scet]) {
1537 *dest = src.as_u64();
1538 }
1539 }
1540}
1541
1542impl StateElement<X86PartitionCapabilities, X86VpInfo> for Cet {
1543 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1544 caps.cet
1545 }
1546
1547 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1548 Self { scet: 0 }
1549 }
1550}
1551
1552#[repr(C)]
1553#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1554#[mesh(package = "virt.x86")]
1555#[inspect(hex)]
1556pub struct CetSs {
1557 #[mesh(1)]
1558 pub ssp: u64,
1559 #[mesh(2)]
1560 pub interrupt_ssp_table_addr: u64,
1561 }
1563
1564impl HvRegisterState<HvX64RegisterName, 2> for CetSs {
1565 fn names(&self) -> &'static [HvX64RegisterName; 2] {
1566 &[
1567 HvX64RegisterName::Ssp,
1568 HvX64RegisterName::InterruptSspTableAddr,
1569 ]
1570 }
1571
1572 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1573 for (dest, src) in it.zip([self.ssp, self.interrupt_ssp_table_addr]) {
1574 *dest = src.into();
1575 }
1576 }
1577
1578 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1579 for (src, dest) in it.zip([&mut self.ssp, &mut self.interrupt_ssp_table_addr]) {
1580 *dest = src.as_u64();
1581 }
1582 }
1583}
1584
1585impl StateElement<X86PartitionCapabilities, X86VpInfo> for CetSs {
1586 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1587 caps.cet_ss
1588 }
1589
1590 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1591 Default::default()
1592 }
1593}
1594
1595#[repr(C)]
1596#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1597#[mesh(package = "virt.x86")]
1598#[inspect(hex)]
1599pub struct SyntheticMsrs {
1600 #[mesh(1)]
1601 pub vp_assist_page: u64,
1602 #[mesh(2)]
1603 pub scontrol: u64,
1604 #[mesh(3)]
1605 pub siefp: u64,
1606 #[mesh(4)]
1607 pub simp: u64,
1608 #[mesh(5)]
1609 #[inspect(iter_by_index)]
1610 pub sint: [u64; 16],
1611}
1612
1613impl HvRegisterState<HvX64RegisterName, 20> for SyntheticMsrs {
1614 fn names(&self) -> &'static [HvX64RegisterName; 20] {
1615 &[
1616 HvX64RegisterName::VpAssistPage,
1617 HvX64RegisterName::Scontrol,
1618 HvX64RegisterName::Sifp,
1619 HvX64RegisterName::Sipp,
1620 HvX64RegisterName::Sint0,
1621 HvX64RegisterName::Sint1,
1622 HvX64RegisterName::Sint2,
1623 HvX64RegisterName::Sint3,
1624 HvX64RegisterName::Sint4,
1625 HvX64RegisterName::Sint5,
1626 HvX64RegisterName::Sint6,
1627 HvX64RegisterName::Sint7,
1628 HvX64RegisterName::Sint8,
1629 HvX64RegisterName::Sint9,
1630 HvX64RegisterName::Sint10,
1631 HvX64RegisterName::Sint11,
1632 HvX64RegisterName::Sint12,
1633 HvX64RegisterName::Sint13,
1634 HvX64RegisterName::Sint14,
1635 HvX64RegisterName::Sint15,
1636 ]
1637 }
1638 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1639 for (dest, src) in it.zip(
1640 [self.vp_assist_page, self.scontrol, self.siefp, self.simp]
1641 .into_iter()
1642 .chain(self.sint),
1643 ) {
1644 *dest = src.into();
1645 }
1646 }
1647
1648 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1649 for (src, dest) in it.zip(
1650 [
1651 &mut self.vp_assist_page,
1652 &mut self.scontrol,
1653 &mut self.siefp,
1654 &mut self.simp,
1655 ]
1656 .into_iter()
1657 .chain(&mut self.sint),
1658 ) {
1659 *dest = src.as_u64();
1660 }
1661 }
1662}
1663
1664impl StateElement<X86PartitionCapabilities, X86VpInfo> for SyntheticMsrs {
1665 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1666 caps.hv1
1667 }
1668
1669 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1670 Self {
1671 vp_assist_page: 0,
1672 scontrol: 1,
1673 siefp: 0,
1674 simp: 0,
1675 sint: [0x10000; 16],
1676 }
1677 }
1678}
1679
1680#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Protobuf, Inspect)]
1681#[mesh(package = "virt.x86")]
1682#[inspect(hex)]
1683pub struct SynicTimer {
1684 #[mesh(1)]
1685 pub config: u64,
1686 #[mesh(2)]
1687 pub count: u64,
1688 #[mesh(3)]
1689 pub adjustment: u64,
1690 #[mesh(4)]
1691 pub undelivered_message_expiration_time: Option<u64>,
1692}
1693
1694#[derive(Debug, Copy, Clone, Eq, PartialEq, Protobuf, Inspect)]
1695#[mesh(package = "virt.x86")]
1696pub struct SynicTimers {
1697 #[mesh(1)]
1698 #[inspect(iter_by_index)]
1699 pub timers: [SynicTimer; 4],
1700}
1701
1702impl SynicTimers {
1703 pub fn as_hv(&self) -> hvdef::HvSyntheticTimersState {
1704 let timers = self.timers.map(|timer| hvdef::HvStimerState {
1705 undelivered_message_pending: timer.undelivered_message_expiration_time.is_some().into(),
1706 reserved: 0,
1707 config: timer.config,
1708 count: timer.count,
1709 adjustment: timer.adjustment,
1710 undelivered_expiration_time: timer.undelivered_message_expiration_time.unwrap_or(0),
1711 });
1712
1713 hvdef::HvSyntheticTimersState {
1714 timers,
1715 reserved: [0; 5],
1716 }
1717 }
1718
1719 pub fn from_hv(state: hvdef::HvSyntheticTimersState) -> Self {
1720 let timers = state.timers.map(|timer| SynicTimer {
1721 config: timer.config,
1722 count: timer.count,
1723 adjustment: timer.adjustment,
1724 undelivered_message_expiration_time: (timer.undelivered_message_pending & 1 != 0)
1725 .then_some(timer.undelivered_expiration_time),
1726 });
1727 Self { timers }
1728 }
1729}
1730
1731impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicTimers {
1732 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1733 caps.hv1
1734 }
1735
1736 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1737 Self {
1738 timers: [SynicTimer::default(); 4],
1739 }
1740 }
1741
1742 fn can_compare(_caps: &X86PartitionCapabilities) -> bool {
1743 false
1746 }
1747}
1748
1749#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1750#[mesh(package = "virt.x86")]
1751pub struct SynicMessageQueues {
1752 #[mesh(1)]
1753 #[inspect(with = "|x| inspect::iter_by_index(x.iter().map(Vec::len))")]
1754 pub queues: [Vec<[u8; HV_MESSAGE_SIZE]>; 16],
1755}
1756
1757impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicMessageQueues {
1758 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1759 caps.hv1
1760 }
1761
1762 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1763 Default::default()
1764 }
1765}
1766
1767#[derive(Debug, Copy, Clone, PartialEq, Eq, Protobuf, Inspect)]
1768#[mesh(package = "virt.x86")]
1769#[inspect(skip)]
1770pub struct SynicMessagePage {
1771 #[mesh(1)]
1772 pub data: [u8; 4096],
1773}
1774
1775impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicMessagePage {
1776 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1777 caps.hv1
1778 }
1779
1780 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1781 Self { data: [0; 4096] }
1782 }
1783}
1784
1785#[derive(Debug, Copy, Clone, PartialEq, Eq, Protobuf, Inspect)]
1786#[mesh(package = "virt.x86")]
1787#[inspect(skip)]
1788pub struct SynicEventFlagsPage {
1789 #[mesh(1)]
1790 pub data: [u8; 4096],
1791}
1792
1793impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicEventFlagsPage {
1794 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1795 caps.hv1
1796 }
1797
1798 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1799 Self { data: [0; 4096] }
1800 }
1801}
1802
1803state_trait! {
1804 "Per-VP state",
1805 AccessVpState,
1806 X86PartitionCapabilities,
1807 X86VpInfo,
1808 VpSavedState,
1809 "virt.x86",
1810 (1, "registers", registers, set_registers, Registers),
1811 (2, "activity", activity, set_activity, Activity),
1812 (3, "xsave", xsave, set_xsave, Xsave),
1813 (4, "apic", apic, set_apic, Apic),
1814 (5, "xcr", xcr, set_xcr, Xcr0),
1815 (6, "xss", xss, set_xss, Xss),
1816 (7, "mtrrs", mtrrs, set_mtrrs, Mtrrs),
1817 (8, "pat", pat, set_pat, Pat),
1818 (9, "msrs", virtual_msrs, set_virtual_msrs, VirtualMsrs),
1819 (10, "drs", debug_regs, set_debug_regs, DebugRegisters),
1820 (11, "tsc", tsc, set_tsc, Tsc),
1821 (12, "cet", cet, set_cet, Cet),
1822 (13, "cet_ss", cet_ss, set_cet_ss, CetSs),
1823 (14, "tsc_aux", tsc_aux, set_tsc_aux, TscAux),
1824
1825 (100, "synic", synic_msrs, set_synic_msrs, SyntheticMsrs),
1827 (
1832 101,
1833 "simp",
1834 synic_message_page,
1835 set_synic_message_page,
1836 SynicMessagePage
1837 ),
1838 (
1839 102,
1840 "siefp",
1841 synic_event_flags_page,
1842 set_synic_event_flags_page,
1843 SynicEventFlagsPage
1844 ),
1845 (
1846 103,
1847 "synic_message_queues",
1848 synic_message_queues,
1849 set_synic_message_queues,
1850 SynicMessageQueues
1851 ),
1852 (104, "synic_timers", synic_timers, set_synic_timers, SynicTimers),
1853}
1854
1855pub fn x86_init<T: AccessVpState>(access: &mut T, vp_info: &X86VpInfo) -> Result<(), T::Error> {
1857 let cr0 = access.registers()?.cr0;
1859 let mut regs = Registers::at_reset(access.caps(), vp_info);
1860 let cr0_mask = X64_CR0_NW | X64_CR0_CD;
1861 regs.cr0 = (cr0 & cr0_mask) | (regs.cr0 & !cr0_mask);
1862 access.set_registers(®s)?;
1863 access.set_debug_regs(&StateElement::at_reset(access.caps(), vp_info))?;
1864
1865 let current_apic = access.apic()?;
1870 let mut apic = Apic::at_reset(access.caps(), vp_info);
1871 apic.registers[x86defs::apic::ApicRegister::ID.0 as usize] =
1872 current_apic.registers[x86defs::apic::ApicRegister::ID.0 as usize];
1873 apic.apic_base = current_apic.apic_base;
1874 access.set_apic(&apic)?;
1875
1876 if !vp_info.base.is_bsp() {
1878 let mut activity = access.activity()?;
1879 activity.mp_state = MpState::WaitForSipi;
1880 access.set_activity(&activity)?;
1881 }
1882
1883 Ok(())
1884}