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_array_ref")]
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
992impl Apic {
993 pub fn new(apic_base: ApicBase, registers: ApicRegisters, auto_eoi: [u32; 8]) -> Self {
994 Self {
995 apic_base: apic_base.into(),
996 registers: *registers.as_array(),
997 auto_eoi,
998 }
999 }
1000
1001 pub fn registers(&self) -> &ApicRegisters {
1002 ApicRegisters::from_array_ref(&self.registers)
1003 }
1004}
1005
1006#[repr(C)]
1007#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
1008#[inspect(hex)]
1009pub struct ApicRegisters {
1010 #[inspect(skip)]
1011 pub reserved_0: [u32; 2],
1012 pub id: u32,
1013 pub version: u32,
1014 #[inspect(skip)]
1015 pub reserved_4: [u32; 4],
1016 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)]
1025 pub isr: [u32; 8], #[inspect(iter_by_index)]
1027 pub tmr: [u32; 8], #[inspect(iter_by_index)]
1029 pub irr: [u32; 8], pub esr: u32, #[inspect(skip)]
1032 pub reserved_29: [u32; 6],
1033 pub lvt_cmci: u32,
1034 #[inspect(iter_by_index)]
1035 pub icr: [u32; 2], pub lvt_timer: u32,
1037 pub lvt_thermal: u32,
1038 pub lvt_pmc: u32,
1039 pub lvt_lint0: u32,
1040 pub lvt_lint1: u32,
1041 pub lvt_error: u32,
1042 pub timer_icr: u32, pub timer_ccr: u32, #[inspect(skip)]
1045 pub reserved_3a: [u32; 4],
1046 pub timer_dcr: u32, #[inspect(skip)]
1048 pub reserved_3f: u32,
1049}
1050
1051const _: () = assert!(size_of::<ApicRegisters>() == 0x100);
1052
1053impl From<ApicRegisters> for hvdef::HvX64InterruptControllerState {
1054 fn from(value: ApicRegisters) -> Self {
1055 Self {
1056 apic_id: value.id,
1057 apic_version: value.version,
1058 apic_ldr: value.ldr,
1059 apic_dfr: value.dfr,
1060 apic_spurious: value.svr,
1061 apic_isr: value.isr,
1062 apic_tmr: value.tmr,
1063 apic_irr: value.irr,
1064 apic_esr: value.esr,
1065 apic_icr_high: value.icr[1],
1066 apic_icr_low: value.icr[0],
1067 apic_lvt_timer: value.lvt_timer,
1068 apic_lvt_thermal: value.lvt_thermal,
1069 apic_lvt_perfmon: value.lvt_pmc,
1070 apic_lvt_lint0: value.lvt_lint0,
1071 apic_lvt_lint1: value.lvt_lint1,
1072 apic_lvt_error: value.lvt_error,
1073 apic_lvt_cmci: value.lvt_cmci,
1074 apic_error_status: value.esr,
1075 apic_initial_count: value.timer_icr,
1076 apic_counter_value: value.timer_ccr,
1077 apic_divide_configuration: value.timer_dcr,
1078 apic_remote_read: value.rrd,
1079 }
1080 }
1081}
1082
1083impl From<hvdef::HvX64InterruptControllerState> for ApicRegisters {
1084 fn from(value: hvdef::HvX64InterruptControllerState) -> Self {
1085 let hvdef::HvX64InterruptControllerState {
1086 apic_id,
1087 apic_version,
1088 apic_ldr,
1089 apic_dfr,
1090 apic_spurious,
1091 apic_isr,
1092 apic_tmr,
1093 apic_irr,
1094 apic_esr,
1095 apic_icr_high,
1096 apic_icr_low,
1097 apic_lvt_timer,
1098 apic_lvt_thermal,
1099 apic_lvt_perfmon,
1100 apic_lvt_lint0,
1101 apic_lvt_lint1,
1102 apic_lvt_error,
1103 apic_lvt_cmci,
1104 apic_error_status: _,
1106 apic_initial_count,
1107 apic_counter_value,
1108 apic_divide_configuration,
1109 apic_remote_read,
1110 } = value;
1111 Self {
1112 reserved_0: [0; 2],
1113 id: apic_id,
1114 version: apic_version,
1115 reserved_4: [0; 4],
1116 tpr: 0,
1117 apr: 0,
1118 ppr: 0,
1119 eoi: 0,
1120 rrd: apic_remote_read,
1121 ldr: apic_ldr,
1122 dfr: apic_dfr,
1123 svr: apic_spurious,
1124 isr: apic_isr,
1125 tmr: apic_tmr,
1126 irr: apic_irr,
1127 esr: apic_esr,
1128 reserved_29: [0; 6],
1129 lvt_cmci: apic_lvt_cmci,
1130 icr: [apic_icr_low, apic_icr_high],
1131 lvt_timer: apic_lvt_timer,
1132 lvt_thermal: apic_lvt_thermal,
1133 lvt_pmc: apic_lvt_perfmon,
1134 lvt_lint0: apic_lvt_lint0,
1135 lvt_lint1: apic_lvt_lint1,
1136 lvt_error: apic_lvt_error,
1137 timer_icr: apic_initial_count,
1138 timer_ccr: apic_counter_value,
1139 reserved_3a: [0; 4],
1140 timer_dcr: apic_divide_configuration,
1141 reserved_3f: 0,
1142 }
1143 }
1144}
1145
1146#[repr(C)]
1147#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1148struct ApicRegister {
1149 value: u32,
1150 zero: [u32; 3],
1151}
1152
1153impl ApicRegisters {
1154 pub fn as_array(&self) -> &[u32; 64] {
1155 zerocopy::transmute_ref!(self)
1156 }
1157
1158 pub fn from_array(array: [u32; 64]) -> Self {
1159 zerocopy::transmute!(array)
1160 }
1161
1162 pub fn from_array_ref(array: &[u32; 64]) -> &Self {
1163 zerocopy::transmute_ref!(array)
1164 }
1165
1166 pub fn as_page(&self) -> [u8; 1024] {
1167 let mut bytes = [0; 1024];
1168 self.as_array()
1169 .map(|value| ApicRegister {
1170 value,
1171 zero: [0; 3],
1172 })
1173 .write_to(bytes.as_mut_slice())
1174 .unwrap();
1175 bytes
1176 }
1177
1178 pub fn from_page(page: &[u8; 1024]) -> Self {
1180 let registers = <[ApicRegister; 64]>::read_from_bytes(page.as_slice()).unwrap();
1181 Self::from_array(registers.map(|reg| reg.value))
1182 }
1183}
1184
1185impl StateElement<X86PartitionCapabilities, X86VpInfo> for Apic {
1186 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1187 true
1188 }
1189
1190 fn at_reset(caps: &X86PartitionCapabilities, vp_info: &X86VpInfo) -> Self {
1191 let x2apic = caps.x2apic_enabled;
1192
1193 let mut regs = ApicRegisters::new_zeroed();
1194 regs.id = if x2apic {
1195 vp_info.apic_id
1196 } else {
1197 vp_info.apic_id << 24
1198 };
1199 regs.version = ApicVersion::new()
1200 .with_version(0x14)
1201 .with_max_lvt_entry(5)
1202 .into();
1203 if x2apic {
1204 regs.ldr = ((vp_info.apic_id << 12) & 0xffff0000) | (1 << (vp_info.apic_id & 0xf));
1205 } else {
1206 regs.dfr = !0;
1207 }
1208 regs.svr = 0xff;
1209 regs.lvt_timer = 0x10000;
1210 regs.lvt_thermal = 0x10000;
1211 regs.lvt_pmc = 0x10000;
1212 regs.lvt_lint0 = 0x10000;
1213 regs.lvt_lint1 = 0x10000;
1214 regs.lvt_error = 0x10000;
1215
1216 let apic_base = ApicBase::new()
1217 .with_base_page(APIC_BASE_PAGE)
1218 .with_bsp(vp_info.base.is_bsp())
1219 .with_x2apic(x2apic)
1220 .with_enable(true);
1221
1222 Apic::new(apic_base, regs, [0; 8])
1223 }
1224
1225 fn can_compare(caps: &X86PartitionCapabilities) -> bool {
1226 caps.can_freeze_time
1229 }
1230}
1231
1232const NMI_VECTOR: u32 = 2;
1235
1236impl ApicRegisters {
1237 pub fn set_hv_apic_nmi_pending(&mut self, pending: bool) {
1239 self.irr[0] &= !(1 << NMI_VECTOR);
1240 self.irr[0] |= (pending as u32) << NMI_VECTOR;
1241 }
1242
1243 pub fn hv_apic_nmi_pending(&self) -> bool {
1245 self.irr[0] & (1 << NMI_VECTOR) != 0
1246 }
1247}
1248
1249#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1250#[mesh(package = "virt.x86")]
1251pub struct Xcr0 {
1252 #[mesh(1)]
1253 #[inspect(hex)]
1254 pub value: u64,
1255}
1256
1257impl HvRegisterState<HvX64RegisterName, 1> for Xcr0 {
1258 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1259 &[HvX64RegisterName::Xfem]
1260 }
1261
1262 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1263 for (dest, src) in it.zip([self.value]) {
1264 *dest = src.into();
1265 }
1266 }
1267
1268 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1269 for (src, dest) in it.zip([&mut self.value]) {
1270 *dest = src.as_u64();
1271 }
1272 }
1273}
1274
1275impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xcr0 {
1276 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1277 caps.xsave.features != 0
1278 }
1279
1280 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1281 Self { value: 1 }
1282 }
1283}
1284
1285#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1286#[mesh(package = "virt.x86")]
1287pub struct Xss {
1288 #[mesh(1)]
1289 #[inspect(hex)]
1290 pub value: u64,
1291}
1292
1293impl HvRegisterState<HvX64RegisterName, 1> for Xss {
1294 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1295 &[HvX64RegisterName::Xss]
1296 }
1297
1298 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1299 for (dest, src) in it.zip([self.value]) {
1300 *dest = src.into();
1301 }
1302 }
1303
1304 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1305 for (src, dest) in it.zip([&mut self.value]) {
1306 *dest = src.as_u64();
1307 }
1308 }
1309}
1310
1311impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xss {
1312 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1313 caps.xsave.supervisor_features != 0
1314 }
1315
1316 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1317 Self { value: 0 }
1318 }
1319}
1320
1321#[repr(C)]
1322#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1323#[mesh(package = "virt.x86")]
1324pub struct Pat {
1325 #[mesh(1)]
1326 #[inspect(hex)]
1327 pub value: u64,
1328}
1329
1330impl HvRegisterState<HvX64RegisterName, 1> for Pat {
1331 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1332 &[HvX64RegisterName::Pat]
1333 }
1334
1335 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1336 for (dest, src) in it.zip([self.value]) {
1337 *dest = src.into();
1338 }
1339 }
1340
1341 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1342 for (src, dest) in it.zip([&mut self.value]) {
1343 *dest = src.as_u64();
1344 }
1345 }
1346}
1347
1348impl StateElement<X86PartitionCapabilities, X86VpInfo> for Pat {
1349 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1350 true
1351 }
1352
1353 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1354 Self {
1355 value: X86X_MSR_DEFAULT_PAT,
1356 }
1357 }
1358}
1359
1360#[repr(C)]
1361#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1362#[mesh(package = "virt.x86")]
1363#[inspect(hex)]
1364pub struct Mtrrs {
1365 #[mesh(1)]
1366 #[inspect(hex)]
1367 pub msr_mtrr_def_type: u64,
1368 #[mesh(2)]
1369 #[inspect(iter_by_index)]
1370 pub fixed: [u64; 11],
1371 #[mesh(3)]
1372 #[inspect(iter_by_index)]
1373 pub variable: [u64; 16],
1374}
1375
1376impl HvRegisterState<HvX64RegisterName, 28> for Mtrrs {
1377 fn names(&self) -> &'static [HvX64RegisterName; 28] {
1378 &[
1379 HvX64RegisterName::MsrMtrrDefType,
1380 HvX64RegisterName::MsrMtrrFix64k00000,
1381 HvX64RegisterName::MsrMtrrFix16k80000,
1382 HvX64RegisterName::MsrMtrrFix16kA0000,
1383 HvX64RegisterName::MsrMtrrFix4kC0000,
1384 HvX64RegisterName::MsrMtrrFix4kC8000,
1385 HvX64RegisterName::MsrMtrrFix4kD0000,
1386 HvX64RegisterName::MsrMtrrFix4kD8000,
1387 HvX64RegisterName::MsrMtrrFix4kE0000,
1388 HvX64RegisterName::MsrMtrrFix4kE8000,
1389 HvX64RegisterName::MsrMtrrFix4kF0000,
1390 HvX64RegisterName::MsrMtrrFix4kF8000,
1391 HvX64RegisterName::MsrMtrrPhysBase0,
1392 HvX64RegisterName::MsrMtrrPhysMask0,
1393 HvX64RegisterName::MsrMtrrPhysBase1,
1394 HvX64RegisterName::MsrMtrrPhysMask1,
1395 HvX64RegisterName::MsrMtrrPhysBase2,
1396 HvX64RegisterName::MsrMtrrPhysMask2,
1397 HvX64RegisterName::MsrMtrrPhysBase3,
1398 HvX64RegisterName::MsrMtrrPhysMask3,
1399 HvX64RegisterName::MsrMtrrPhysBase4,
1400 HvX64RegisterName::MsrMtrrPhysMask4,
1401 HvX64RegisterName::MsrMtrrPhysBase5,
1402 HvX64RegisterName::MsrMtrrPhysMask5,
1403 HvX64RegisterName::MsrMtrrPhysBase6,
1404 HvX64RegisterName::MsrMtrrPhysMask6,
1405 HvX64RegisterName::MsrMtrrPhysBase7,
1406 HvX64RegisterName::MsrMtrrPhysMask7,
1407 ]
1408 }
1409
1410 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1411 for (dest, src) in it.zip(
1412 [self.msr_mtrr_def_type]
1413 .into_iter()
1414 .chain(self.fixed)
1415 .chain(self.variable),
1416 ) {
1417 *dest = src.into();
1418 }
1419 }
1420
1421 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1422 for (src, dest) in it.zip(
1423 [&mut self.msr_mtrr_def_type]
1424 .into_iter()
1425 .chain(&mut self.fixed)
1426 .chain(&mut self.variable),
1427 ) {
1428 *dest = src.as_u64();
1429 }
1430 }
1431}
1432
1433impl StateElement<X86PartitionCapabilities, X86VpInfo> for Mtrrs {
1434 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1435 true
1436 }
1437
1438 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1439 Self {
1440 msr_mtrr_def_type: 0,
1441 fixed: [0; 11],
1442 variable: [0; 16],
1443 }
1444 }
1445}
1446
1447#[repr(C)]
1448#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1449#[mesh(package = "virt.x86")]
1450#[inspect(hex)]
1451pub struct VirtualMsrs {
1452 #[mesh(1)]
1453 pub kernel_gs_base: u64,
1454 #[mesh(2)]
1455 pub sysenter_cs: u64,
1456 #[mesh(3)]
1457 pub sysenter_eip: u64,
1458 #[mesh(4)]
1459 pub sysenter_esp: u64,
1460 #[mesh(5)]
1461 pub star: u64,
1462 #[mesh(6)]
1463 pub lstar: u64,
1464 #[mesh(7)]
1465 pub cstar: u64,
1466 #[mesh(8)]
1467 pub sfmask: u64,
1468}
1469
1470impl HvRegisterState<HvX64RegisterName, 8> for VirtualMsrs {
1471 fn names(&self) -> &'static [HvX64RegisterName; 8] {
1472 &[
1473 HvX64RegisterName::KernelGsBase,
1474 HvX64RegisterName::SysenterCs,
1475 HvX64RegisterName::SysenterEsp,
1476 HvX64RegisterName::SysenterEip,
1477 HvX64RegisterName::Star,
1478 HvX64RegisterName::Lstar,
1479 HvX64RegisterName::Cstar,
1480 HvX64RegisterName::Sfmask,
1481 ]
1482 }
1483
1484 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1485 for (dest, src) in it.zip([
1486 self.kernel_gs_base,
1487 self.sysenter_cs,
1488 self.sysenter_eip,
1489 self.sysenter_esp,
1490 self.star,
1491 self.lstar,
1492 self.cstar,
1493 self.sfmask,
1494 ]) {
1495 *dest = src.into();
1496 }
1497 }
1498
1499 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1500 for (src, dest) in it.zip([
1501 &mut self.kernel_gs_base,
1502 &mut self.sysenter_cs,
1503 &mut self.sysenter_eip,
1504 &mut self.sysenter_esp,
1505 &mut self.star,
1506 &mut self.lstar,
1507 &mut self.cstar,
1508 &mut self.sfmask,
1509 ]) {
1510 *dest = src.as_u64();
1511 }
1512 }
1513}
1514
1515impl StateElement<X86PartitionCapabilities, X86VpInfo> for VirtualMsrs {
1516 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1517 true
1518 }
1519
1520 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1521 Self {
1522 kernel_gs_base: 0,
1523 sysenter_cs: 0,
1524 sysenter_eip: 0,
1525 sysenter_esp: 0,
1526 star: 0,
1527 lstar: 0,
1528 cstar: 0,
1529 sfmask: 0,
1530 }
1531 }
1532}
1533
1534#[repr(C)]
1535#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1536#[mesh(package = "virt.x86")]
1537pub struct TscAux {
1538 #[mesh(1)]
1539 #[inspect(hex)]
1540 pub value: u64,
1541}
1542
1543impl HvRegisterState<HvX64RegisterName, 1> for TscAux {
1544 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1545 &[HvX64RegisterName::TscAux]
1546 }
1547
1548 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1549 for (dest, src) in it.zip([self.value]) {
1550 *dest = src.into();
1551 }
1552 }
1553
1554 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1555 for (src, dest) in it.zip([&mut self.value]) {
1556 *dest = src.as_u64();
1557 }
1558 }
1559}
1560
1561impl StateElement<X86PartitionCapabilities, X86VpInfo> for TscAux {
1562 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1563 caps.tsc_aux
1564 }
1565
1566 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1567 Default::default()
1568 }
1569}
1570
1571#[repr(C)]
1572#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1573#[mesh(package = "virt.x86")]
1574pub struct Tsc {
1575 #[mesh(1)]
1576 #[inspect(hex)]
1577 pub value: u64,
1578}
1579
1580impl HvRegisterState<HvX64RegisterName, 1> for Tsc {
1581 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1582 &[HvX64RegisterName::Tsc]
1583 }
1584
1585 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1586 for (dest, src) in it.zip([self.value]) {
1587 *dest = src.into();
1588 }
1589 }
1590
1591 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1592 for (src, dest) in it.zip([&mut self.value]) {
1593 *dest = src.as_u64();
1594 }
1595 }
1596}
1597
1598impl StateElement<X86PartitionCapabilities, X86VpInfo> for Tsc {
1599 fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1600 true
1601 }
1602
1603 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1604 Self { value: 0 }
1605 }
1606
1607 fn can_compare(caps: &X86PartitionCapabilities) -> bool {
1608 caps.can_freeze_time
1609 }
1610}
1611
1612#[repr(C)]
1613#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1614#[mesh(package = "virt.x86")]
1615pub struct Cet {
1616 #[mesh(1)]
1617 #[inspect(hex)]
1618 pub scet: u64,
1619 }
1621
1622impl HvRegisterState<HvX64RegisterName, 1> for Cet {
1623 fn names(&self) -> &'static [HvX64RegisterName; 1] {
1624 &[HvX64RegisterName::SCet]
1625 }
1626
1627 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1628 for (dest, src) in it.zip([self.scet]) {
1629 *dest = src.into();
1630 }
1631 }
1632
1633 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1634 for (src, dest) in it.zip([&mut self.scet]) {
1635 *dest = src.as_u64();
1636 }
1637 }
1638}
1639
1640impl StateElement<X86PartitionCapabilities, X86VpInfo> for Cet {
1641 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1642 caps.cet
1643 }
1644
1645 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1646 Self { scet: 0 }
1647 }
1648}
1649
1650#[repr(C)]
1651#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1652#[mesh(package = "virt.x86")]
1653#[inspect(hex)]
1654pub struct CetSs {
1655 #[mesh(1)]
1656 pub ssp: u64,
1657 #[mesh(2)]
1658 pub interrupt_ssp_table_addr: u64,
1659 }
1661
1662impl HvRegisterState<HvX64RegisterName, 2> for CetSs {
1663 fn names(&self) -> &'static [HvX64RegisterName; 2] {
1664 &[
1665 HvX64RegisterName::Ssp,
1666 HvX64RegisterName::InterruptSspTableAddr,
1667 ]
1668 }
1669
1670 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1671 for (dest, src) in it.zip([self.ssp, self.interrupt_ssp_table_addr]) {
1672 *dest = src.into();
1673 }
1674 }
1675
1676 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1677 for (src, dest) in it.zip([&mut self.ssp, &mut self.interrupt_ssp_table_addr]) {
1678 *dest = src.as_u64();
1679 }
1680 }
1681}
1682
1683impl StateElement<X86PartitionCapabilities, X86VpInfo> for CetSs {
1684 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1685 caps.cet_ss
1686 }
1687
1688 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1689 Default::default()
1690 }
1691}
1692
1693#[repr(C)]
1694#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1695#[mesh(package = "virt.x86")]
1696#[inspect(hex)]
1697pub struct SyntheticMsrs {
1698 #[mesh(1)]
1699 pub vp_assist_page: u64,
1700 #[mesh(2)]
1701 pub scontrol: u64,
1702 #[mesh(3)]
1703 pub siefp: u64,
1704 #[mesh(4)]
1705 pub simp: u64,
1706 #[mesh(5)]
1707 #[inspect(iter_by_index)]
1708 pub sint: [u64; 16],
1709}
1710
1711impl HvRegisterState<HvX64RegisterName, 20> for SyntheticMsrs {
1712 fn names(&self) -> &'static [HvX64RegisterName; 20] {
1713 &[
1714 HvX64RegisterName::VpAssistPage,
1715 HvX64RegisterName::Scontrol,
1716 HvX64RegisterName::Sifp,
1717 HvX64RegisterName::Sipp,
1718 HvX64RegisterName::Sint0,
1719 HvX64RegisterName::Sint1,
1720 HvX64RegisterName::Sint2,
1721 HvX64RegisterName::Sint3,
1722 HvX64RegisterName::Sint4,
1723 HvX64RegisterName::Sint5,
1724 HvX64RegisterName::Sint6,
1725 HvX64RegisterName::Sint7,
1726 HvX64RegisterName::Sint8,
1727 HvX64RegisterName::Sint9,
1728 HvX64RegisterName::Sint10,
1729 HvX64RegisterName::Sint11,
1730 HvX64RegisterName::Sint12,
1731 HvX64RegisterName::Sint13,
1732 HvX64RegisterName::Sint14,
1733 HvX64RegisterName::Sint15,
1734 ]
1735 }
1736 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1737 for (dest, src) in it.zip(
1738 [self.vp_assist_page, self.scontrol, self.siefp, self.simp]
1739 .into_iter()
1740 .chain(self.sint),
1741 ) {
1742 *dest = src.into();
1743 }
1744 }
1745
1746 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1747 for (src, dest) in it.zip(
1748 [
1749 &mut self.vp_assist_page,
1750 &mut self.scontrol,
1751 &mut self.siefp,
1752 &mut self.simp,
1753 ]
1754 .into_iter()
1755 .chain(&mut self.sint),
1756 ) {
1757 *dest = src.as_u64();
1758 }
1759 }
1760}
1761
1762impl StateElement<X86PartitionCapabilities, X86VpInfo> for SyntheticMsrs {
1763 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1764 caps.hv1
1765 }
1766
1767 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1768 Self {
1769 vp_assist_page: 0,
1770 scontrol: 1,
1771 siefp: 0,
1772 simp: 0,
1773 sint: [0x10000; 16],
1774 }
1775 }
1776}
1777
1778#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Protobuf, Inspect)]
1779#[mesh(package = "virt.x86")]
1780#[inspect(hex)]
1781pub struct SynicTimer {
1782 #[mesh(1)]
1783 pub config: u64,
1784 #[mesh(2)]
1785 pub count: u64,
1786 #[mesh(3)]
1787 pub adjustment: u64,
1788 #[mesh(4)]
1789 pub undelivered_message_expiration_time: Option<u64>,
1790}
1791
1792#[derive(Debug, Copy, Clone, Eq, PartialEq, Protobuf, Inspect)]
1793#[mesh(package = "virt.x86")]
1794pub struct SynicTimers {
1795 #[mesh(1)]
1796 #[inspect(iter_by_index)]
1797 pub timers: [SynicTimer; 4],
1798}
1799
1800impl SynicTimers {
1801 pub fn as_hv(&self) -> hvdef::HvSyntheticTimersState {
1802 let timers = self.timers.map(|timer| hvdef::HvStimerState {
1803 undelivered_message_pending: timer.undelivered_message_expiration_time.is_some().into(),
1804 reserved: 0,
1805 config: timer.config,
1806 count: timer.count,
1807 adjustment: timer.adjustment,
1808 undelivered_expiration_time: timer.undelivered_message_expiration_time.unwrap_or(0),
1809 });
1810
1811 hvdef::HvSyntheticTimersState {
1812 timers,
1813 reserved: [0; 5],
1814 }
1815 }
1816
1817 pub fn from_hv(state: hvdef::HvSyntheticTimersState) -> Self {
1818 let timers = state.timers.map(|timer| SynicTimer {
1819 config: timer.config,
1820 count: timer.count,
1821 adjustment: timer.adjustment,
1822 undelivered_message_expiration_time: (timer.undelivered_message_pending & 1 != 0)
1823 .then_some(timer.undelivered_expiration_time),
1824 });
1825 Self { timers }
1826 }
1827}
1828
1829impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicTimers {
1830 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1831 caps.hv1
1832 }
1833
1834 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1835 Self {
1836 timers: [SynicTimer::default(); 4],
1837 }
1838 }
1839
1840 fn can_compare(_caps: &X86PartitionCapabilities) -> bool {
1841 false
1844 }
1845}
1846
1847#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1848#[mesh(package = "virt.x86")]
1849pub struct SynicMessageQueues {
1850 #[mesh(1)]
1851 #[inspect(with = "|x| inspect::iter_by_index(x.iter().map(Vec::len))")]
1852 pub queues: [Vec<[u8; HV_MESSAGE_SIZE]>; 16],
1853}
1854
1855impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicMessageQueues {
1856 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1857 caps.hv1
1858 }
1859
1860 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1861 Default::default()
1862 }
1863}
1864
1865#[derive(Debug, Copy, Clone, PartialEq, Eq, Protobuf, Inspect)]
1866#[mesh(package = "virt.x86")]
1867#[inspect(skip)]
1868pub struct SynicMessagePage {
1869 #[mesh(1)]
1870 pub data: [u8; 4096],
1871}
1872
1873impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicMessagePage {
1874 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1875 caps.hv1
1876 }
1877
1878 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1879 Self { data: [0; 4096] }
1880 }
1881}
1882
1883#[derive(Debug, Copy, Clone, PartialEq, Eq, Protobuf, Inspect)]
1884#[mesh(package = "virt.x86")]
1885#[inspect(skip)]
1886pub struct SynicEventFlagsPage {
1887 #[mesh(1)]
1888 pub data: [u8; 4096],
1889}
1890
1891impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicEventFlagsPage {
1892 fn is_present(caps: &X86PartitionCapabilities) -> bool {
1893 caps.hv1
1894 }
1895
1896 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1897 Self { data: [0; 4096] }
1898 }
1899}
1900
1901state_trait! {
1902 "Per-VP state",
1903 AccessVpState,
1904 X86PartitionCapabilities,
1905 X86VpInfo,
1906 VpSavedState,
1907 "virt.x86",
1908 (1, "registers", registers, set_registers, Registers),
1909 (2, "activity", activity, set_activity, Activity),
1910 (3, "xsave", xsave, set_xsave, Xsave),
1911 (4, "apic", apic, set_apic, Apic),
1912 (5, "xcr", xcr, set_xcr, Xcr0),
1913 (6, "xss", xss, set_xss, Xss),
1914 (7, "mtrrs", mtrrs, set_mtrrs, Mtrrs),
1915 (8, "pat", pat, set_pat, Pat),
1916 (9, "msrs", virtual_msrs, set_virtual_msrs, VirtualMsrs),
1917 (10, "drs", debug_regs, set_debug_regs, DebugRegisters),
1918 (11, "tsc", tsc, set_tsc, Tsc),
1919 (12, "cet", cet, set_cet, Cet),
1920 (13, "cet_ss", cet_ss, set_cet_ss, CetSs),
1921 (14, "tsc_aux", tsc_aux, set_tsc_aux, TscAux),
1922
1923 (100, "synic", synic_msrs, set_synic_msrs, SyntheticMsrs),
1925 (
1930 101,
1931 "simp",
1932 synic_message_page,
1933 set_synic_message_page,
1934 SynicMessagePage
1935 ),
1936 (
1937 102,
1938 "siefp",
1939 synic_event_flags_page,
1940 set_synic_event_flags_page,
1941 SynicEventFlagsPage
1942 ),
1943 (
1944 103,
1945 "synic_message_queues",
1946 synic_message_queues,
1947 set_synic_message_queues,
1948 SynicMessageQueues
1949 ),
1950 (104, "synic_timers", synic_timers, set_synic_timers, SynicTimers),
1951}
1952
1953pub fn x86_init<T: AccessVpState>(access: &mut T, vp_info: &X86VpInfo) -> Result<(), T::Error> {
1955 let cr0 = access.registers()?.cr0;
1957 let mut regs = Registers::at_reset(access.caps(), vp_info);
1958 let cr0_mask = X64_CR0_NW | X64_CR0_CD;
1959 regs.cr0 = (cr0 & cr0_mask) | (regs.cr0 & !cr0_mask);
1960 access.set_registers(®s)?;
1961 access.set_debug_regs(&StateElement::at_reset(access.caps(), vp_info))?;
1962
1963 let current_apic = access.apic()?;
1968 let mut apic = Apic::at_reset(access.caps(), vp_info);
1969 apic.registers[x86defs::apic::ApicRegister::ID.0 as usize] =
1970 current_apic.registers[x86defs::apic::ApicRegister::ID.0 as usize];
1971 apic.apic_base = current_apic.apic_base;
1972 access.set_apic(&apic)?;
1973
1974 if !vp_info.base.is_bsp() {
1976 let mut activity = access.activity()?;
1977 activity.mp_state = MpState::WaitForSipi;
1978 access.set_activity(&activity)?;
1979 }
1980
1981 Ok(())
1982}