Skip to main content

virt/x86/
vp.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Per-VP state.
5
6use 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
392// N.B. This does not include the NMI pending bit, which must be get/set via the
393//      APIC page.
394impl 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            // FUTURE: we should really emulate INIT and SIPI to have
558            // finer-grained control over the states.
559            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        // Some machines support clearing bit 16 for some TSX debugging feature,
692        // but the hypervisor does not support restoring DR6 into this state.
693        // Ignore comparison failures in this case.
694        !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; // TODO: zerocopy: ref-from-prefix: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
709
710        // Clear the mxcsr mask since it's ignored in the restore process and
711        // will only cause xsave comparisons to fail.
712        fxsave.mxcsr_mask = 0;
713
714        // Clear SSE state if it's not actually set to anything interesting.
715        // This normalizes behavior between mshv (which always sets SSE in
716        // xstate_bv) and KVM (which does not).
717        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        // Clear init FPU state as well.
732        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        // Clear the portion of the xsave legacy region that's specified to not
755        // to be used by the processor. Never versions of KVM put garbage values
756        // in here for some (possibly incorrect) reason.
757        fxsave.unused.fill(0);
758    }
759
760    /// Construct from the xsave compact format.
761    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        // Some versions of the MS hypervisor fail to set xstate_bv for
770        // supervisor states. In this case, force-enable them--this is always
771        // safe (since their init state == zero) and does not have a performance
772        // penalty.
773        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; // TODO: zerocopy: ref-from-prefix: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
778
779            // Just enable supervisor states that were possible when the
780            // hypervisor had the bug. Future ones will only be supported by
781            // fixed hypervisors.
782            header.xstate_bv |= header.xcomp_bv & 0x1c00;
783        }
784
785        this
786    }
787
788    /// Construct from standard (non-compact) xsave format.
789    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    /// Write out to standard (non-compact) xsave format.
821    pub fn write_standard(&self, data: &mut [u8], caps: &X86PartitionCapabilities) {
822        // Copy the legacy region including default values for disabled features.
823        data[..XSAVE_LEGACY_LEN].copy_from_slice(self.fxsave().as_bytes());
824
825        // Copy the xsave header but clear xcomp_bv.
826        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        // Copy the features.
836        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    /// Returns the compact form.
855    pub fn compact(&self) -> &[u8] {
856        self.data.as_bytes()
857    }
858
859    /// Returns the legacy fxsave state only.
860    ///
861    /// Since this does not include `xstate_bv`, fields for disabled features
862    /// will be set to their default values.
863    pub fn fxsave(&self) -> Fxsave {
864        let mut fxsave = Fxsave::read_from_prefix(self.data.as_bytes()).unwrap().0; // TODO: zerocopy: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
865        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 // TODO: zerocopy: ref-from-prefix: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
879    }
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            // TODO: zerocopy: ref-from-prefix: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
955            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, // Task Priority Register
1017    pub apr: u32, // Arbitration Priority Register
1018    pub ppr: u32, // Processor Priority Register
1019    pub eoi: u32, //
1020    pub rrd: u32, // Remote Read Register
1021    pub ldr: u32, // Logical Destination Register
1022    pub dfr: u32, // Destination Format Register
1023    pub svr: u32, // Spurious Interrupt Vector
1024    #[inspect(iter_by_index)]
1025    pub isr: [u32; 8], // In-Service Register
1026    #[inspect(iter_by_index)]
1027    pub tmr: [u32; 8], // Trigger Mode Register
1028    #[inspect(iter_by_index)]
1029    pub irr: [u32; 8], // Interrupt Request Register
1030    pub esr: u32, // Error Status Register
1031    #[inspect(skip)]
1032    pub reserved_29: [u32; 6],
1033    pub lvt_cmci: u32,
1034    #[inspect(iter_by_index)]
1035    pub icr: [u32; 2], // Interrupt Command Register
1036    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, // Initial Count Register
1043    pub timer_ccr: u32, // Current Count Register
1044    #[inspect(skip)]
1045    pub reserved_3a: [u32; 4],
1046    pub timer_dcr: u32, // Divide Configuration Register
1047    #[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            // The unlatched error status is not preserved across save/restore.
1105            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    /// Convert from an APIC page.
1179    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        // If a partition (ie KVM) cannot freeze time, one of the APIC timer values will continue counting up after restore.
1227        // For now, disallow comparing the whole Apic structure if so.
1228        caps.can_freeze_time
1229    }
1230}
1231
1232// The IRR bit number corresponding to NMI pending in the Hyper-V exo APIC saved
1233// state.
1234const NMI_VECTOR: u32 = 2;
1235
1236impl ApicRegisters {
1237    /// Sets the non-architectural Hyper-V NMI pending bit in the APIC page.
1238    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    /// Gets the non-architectural Hyper-V NMI pending bit from the APIC page.
1244    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    // Ucet is part of xsave state.
1620}
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    // Plx_ssp are part of xsave state.
1660}
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        // These can't be compared, since the hypervisor may choose to
1842        // immediately deliver the undelivered message.
1843        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    // Synic state
1924    (100, "synic", synic_msrs, set_synic_msrs, SyntheticMsrs),
1925    // The simp page contents must come after synic MSRs so that the SIMP page
1926    // register is set, but before the message queues and timers in case the
1927    // hypervisor decides to flush a pending message to the message page during
1928    // restore.
1929    (
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
1953/// Resets register state for an x86 INIT via the APIC.
1954pub fn x86_init<T: AccessVpState>(access: &mut T, vp_info: &X86VpInfo) -> Result<(), T::Error> {
1955    // Reset core register and debug register state, but preserve a few bits of cr0.
1956    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(&regs)?;
1961    access.set_debug_regs(&StateElement::at_reset(access.caps(), vp_info))?;
1962
1963    // Reset the APIC state, leaving the APIC base address and APIC ID intact.
1964    //
1965    // Note that there may be still be pending interrupt requests in the APIC
1966    // (e.g. an incoming SIPI), which this should not affect.
1967    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    // Enable the wait-for-SIPI state.
1975    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}