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