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")]
970    #[mesh(2)]
971    pub registers: [u32; 64],
972    #[inspect(iter_by_index)]
973    #[mesh(3)]
974    pub auto_eoi: [u32; 8],
975}
976
977impl Debug for Apic {
978    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
979        let Self {
980            apic_base,
981            registers,
982            auto_eoi,
983        } = self;
984        f.debug_struct("Apic")
985            .field("apic_base", &format_args!("{:#x}", apic_base))
986            .field("registers", &format_args!("{:#x?}", registers))
987            .field("registers", &format_args!("{:#x?}", auto_eoi))
988            .finish()
989    }
990}
991
992#[repr(C)]
993#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
994#[inspect(hex)]
995pub struct ApicRegisters {
996    #[inspect(skip)]
997    pub reserved_0: [u32; 2],
998    pub id: u32,
999    pub version: u32,
1000    #[inspect(skip)]
1001    pub reserved_4: [u32; 4],
1002    pub tpr: u32, // Task Priority Register
1003    pub apr: u32, // Arbitration Priority Register
1004    pub ppr: u32, // Processor Priority Register
1005    pub eoi: u32, //
1006    pub rrd: u32, // Remote Read Register
1007    pub ldr: u32, // Logical Destination Register
1008    pub dfr: u32, // Destination Format Register
1009    pub svr: u32, // Spurious Interrupt Vector
1010    #[inspect(iter_by_index)]
1011    pub isr: [u32; 8], // In-Service Register
1012    #[inspect(iter_by_index)]
1013    pub tmr: [u32; 8], // Trigger Mode Register
1014    #[inspect(iter_by_index)]
1015    pub irr: [u32; 8], // Interrupt Request Register
1016    pub esr: u32, // Error Status Register
1017    #[inspect(skip)]
1018    pub reserved_29: [u32; 6],
1019    pub lvt_cmci: u32,
1020    #[inspect(iter_by_index)]
1021    pub icr: [u32; 2], // Interrupt Command Register
1022    pub lvt_timer: u32,
1023    pub lvt_thermal: u32,
1024    pub lvt_pmc: u32,
1025    pub lvt_lint0: u32,
1026    pub lvt_lint1: u32,
1027    pub lvt_error: u32,
1028    pub timer_icr: u32, // Initial Count Register
1029    pub timer_ccr: u32, // Current Count Register
1030    #[inspect(skip)]
1031    pub reserved_3a: [u32; 4],
1032    pub timer_dcr: u32, // Divide Configuration Register
1033    #[inspect(skip)]
1034    pub reserved_3f: u32,
1035}
1036
1037const _: () = assert!(size_of::<ApicRegisters>() == 0x100);
1038
1039impl From<&'_ [u32; 64]> for ApicRegisters {
1040    fn from(value: &'_ [u32; 64]) -> Self {
1041        Self::read_from_bytes(value.as_bytes()).unwrap()
1042    }
1043}
1044
1045impl From<ApicRegisters> for [u32; 64] {
1046    fn from(value: ApicRegisters) -> Self {
1047        Self::read_from_bytes(value.as_bytes()).unwrap()
1048    }
1049}
1050
1051#[repr(C)]
1052#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1053struct ApicRegister {
1054    value: u32,
1055    zero: [u32; 3],
1056}
1057
1058// The IRR bit number corresponding to NMI pending in the Hyper-V exo APIC saved
1059// state.
1060const HV_IRR_NMI_PENDING_SHIFT: u32 = 2;
1061
1062impl Apic {
1063    pub fn as_page(&self) -> [u8; 1024] {
1064        let mut bytes = [0; 1024];
1065        self.registers
1066            .map(|value| ApicRegister {
1067                value,
1068                zero: [0; 3],
1069            })
1070            .write_to(bytes.as_mut_slice())
1071            .unwrap();
1072        bytes
1073    }
1074
1075    /// Convert from an APIC page.
1076    ///
1077    /// N.B. The MS hypervisor's APIC page format includes a non-architectural
1078    /// NMI pending bit that should be stripped first.
1079    pub fn from_page(apic_base: u64, page: &[u8; 1024]) -> Self {
1080        let registers = <[ApicRegister; 64]>::read_from_bytes(page.as_slice()).unwrap();
1081        Self {
1082            apic_base,
1083            registers: registers.map(|reg| reg.value),
1084            auto_eoi: [0; 8],
1085        }
1086    }
1087}
1088
1089impl StateElement<X86PartitionCapabilities, X86VpInfo> for Apic {
1090    fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1091        true
1092    }
1093
1094    fn at_reset(caps: &X86PartitionCapabilities, vp_info: &X86VpInfo) -> Self {
1095        let x2apic = caps.x2apic_enabled;
1096
1097        let mut regs = ApicRegisters::new_zeroed();
1098        regs.id = if x2apic {
1099            vp_info.apic_id
1100        } else {
1101            vp_info.apic_id << 24
1102        };
1103        regs.version = ApicVersion::new()
1104            .with_version(0x14)
1105            .with_max_lvt_entry(5)
1106            .into();
1107        if x2apic {
1108            regs.ldr = ((vp_info.apic_id << 12) & 0xffff0000) | (1 << (vp_info.apic_id & 0xf));
1109        } else {
1110            regs.dfr = !0;
1111        }
1112        regs.svr = 0xff;
1113        regs.lvt_timer = 0x10000;
1114        regs.lvt_thermal = 0x10000;
1115        regs.lvt_pmc = 0x10000;
1116        regs.lvt_lint0 = 0x10000;
1117        regs.lvt_lint1 = 0x10000;
1118        regs.lvt_error = 0x10000;
1119
1120        let apic_base = ApicBase::new()
1121            .with_base_page(APIC_BASE_PAGE)
1122            .with_bsp(vp_info.base.is_bsp())
1123            .with_x2apic(x2apic)
1124            .with_enable(true);
1125
1126        Apic {
1127            apic_base: apic_base.into(),
1128            registers: regs.into(),
1129            auto_eoi: [0; 8],
1130        }
1131    }
1132
1133    fn can_compare(caps: &X86PartitionCapabilities) -> bool {
1134        // If a partition (ie KVM) cannot freeze time, one of the APIC timer values will continue counting up after restore.
1135        // For now, disallow comparing the whole Apic structure if so.
1136        caps.can_freeze_time
1137    }
1138}
1139
1140/// Sets the non-architectural Hyper-V NMI pending bit in the APIC page.
1141pub fn set_hv_apic_nmi_pending(page: &mut [u8], pending: bool) {
1142    page[0x200] &= !(1 << HV_IRR_NMI_PENDING_SHIFT);
1143    page[0x200] |= (pending as u8) << HV_IRR_NMI_PENDING_SHIFT;
1144}
1145
1146/// Gets the non-architectural Hyper-V NMI pending bit from the APIC page.
1147pub fn hv_apic_nmi_pending(page: &[u8]) -> bool {
1148    page[0x200] & (1 << HV_IRR_NMI_PENDING_SHIFT) != 0
1149}
1150
1151#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1152#[mesh(package = "virt.x86")]
1153pub struct Xcr0 {
1154    #[mesh(1)]
1155    #[inspect(hex)]
1156    pub value: u64,
1157}
1158
1159impl HvRegisterState<HvX64RegisterName, 1> for Xcr0 {
1160    fn names(&self) -> &'static [HvX64RegisterName; 1] {
1161        &[HvX64RegisterName::Xfem]
1162    }
1163
1164    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1165        for (dest, src) in it.zip([self.value]) {
1166            *dest = src.into();
1167        }
1168    }
1169
1170    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1171        for (src, dest) in it.zip([&mut self.value]) {
1172            *dest = src.as_u64();
1173        }
1174    }
1175}
1176
1177impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xcr0 {
1178    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1179        caps.xsave.features != 0
1180    }
1181
1182    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1183        Self { value: 1 }
1184    }
1185}
1186
1187#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1188#[mesh(package = "virt.x86")]
1189pub struct Xss {
1190    #[mesh(1)]
1191    #[inspect(hex)]
1192    pub value: u64,
1193}
1194
1195impl HvRegisterState<HvX64RegisterName, 1> for Xss {
1196    fn names(&self) -> &'static [HvX64RegisterName; 1] {
1197        &[HvX64RegisterName::Xss]
1198    }
1199
1200    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1201        for (dest, src) in it.zip([self.value]) {
1202            *dest = src.into();
1203        }
1204    }
1205
1206    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1207        for (src, dest) in it.zip([&mut self.value]) {
1208            *dest = src.as_u64();
1209        }
1210    }
1211}
1212
1213impl StateElement<X86PartitionCapabilities, X86VpInfo> for Xss {
1214    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1215        caps.xsave.supervisor_features != 0
1216    }
1217
1218    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1219        Self { value: 0 }
1220    }
1221}
1222
1223#[repr(C)]
1224#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1225#[mesh(package = "virt.x86")]
1226pub struct Pat {
1227    #[mesh(1)]
1228    #[inspect(hex)]
1229    pub value: u64,
1230}
1231
1232impl HvRegisterState<HvX64RegisterName, 1> for Pat {
1233    fn names(&self) -> &'static [HvX64RegisterName; 1] {
1234        &[HvX64RegisterName::Pat]
1235    }
1236
1237    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1238        for (dest, src) in it.zip([self.value]) {
1239            *dest = src.into();
1240        }
1241    }
1242
1243    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1244        for (src, dest) in it.zip([&mut self.value]) {
1245            *dest = src.as_u64();
1246        }
1247    }
1248}
1249
1250impl StateElement<X86PartitionCapabilities, X86VpInfo> for Pat {
1251    fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1252        true
1253    }
1254
1255    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1256        Self {
1257            value: X86X_MSR_DEFAULT_PAT,
1258        }
1259    }
1260}
1261
1262#[repr(C)]
1263#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1264#[mesh(package = "virt.x86")]
1265#[inspect(hex)]
1266pub struct Mtrrs {
1267    #[mesh(1)]
1268    #[inspect(hex)]
1269    pub msr_mtrr_def_type: u64,
1270    #[mesh(2)]
1271    #[inspect(iter_by_index)]
1272    pub fixed: [u64; 11],
1273    #[mesh(3)]
1274    #[inspect(iter_by_index)]
1275    pub variable: [u64; 16],
1276}
1277
1278impl HvRegisterState<HvX64RegisterName, 28> for Mtrrs {
1279    fn names(&self) -> &'static [HvX64RegisterName; 28] {
1280        &[
1281            HvX64RegisterName::MsrMtrrDefType,
1282            HvX64RegisterName::MsrMtrrFix64k00000,
1283            HvX64RegisterName::MsrMtrrFix16k80000,
1284            HvX64RegisterName::MsrMtrrFix16kA0000,
1285            HvX64RegisterName::MsrMtrrFix4kC0000,
1286            HvX64RegisterName::MsrMtrrFix4kC8000,
1287            HvX64RegisterName::MsrMtrrFix4kD0000,
1288            HvX64RegisterName::MsrMtrrFix4kD8000,
1289            HvX64RegisterName::MsrMtrrFix4kE0000,
1290            HvX64RegisterName::MsrMtrrFix4kE8000,
1291            HvX64RegisterName::MsrMtrrFix4kF0000,
1292            HvX64RegisterName::MsrMtrrFix4kF8000,
1293            HvX64RegisterName::MsrMtrrPhysBase0,
1294            HvX64RegisterName::MsrMtrrPhysMask0,
1295            HvX64RegisterName::MsrMtrrPhysBase1,
1296            HvX64RegisterName::MsrMtrrPhysMask1,
1297            HvX64RegisterName::MsrMtrrPhysBase2,
1298            HvX64RegisterName::MsrMtrrPhysMask2,
1299            HvX64RegisterName::MsrMtrrPhysBase3,
1300            HvX64RegisterName::MsrMtrrPhysMask3,
1301            HvX64RegisterName::MsrMtrrPhysBase4,
1302            HvX64RegisterName::MsrMtrrPhysMask4,
1303            HvX64RegisterName::MsrMtrrPhysBase5,
1304            HvX64RegisterName::MsrMtrrPhysMask5,
1305            HvX64RegisterName::MsrMtrrPhysBase6,
1306            HvX64RegisterName::MsrMtrrPhysMask6,
1307            HvX64RegisterName::MsrMtrrPhysBase7,
1308            HvX64RegisterName::MsrMtrrPhysMask7,
1309        ]
1310    }
1311
1312    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1313        for (dest, src) in it.zip(
1314            [self.msr_mtrr_def_type]
1315                .into_iter()
1316                .chain(self.fixed)
1317                .chain(self.variable),
1318        ) {
1319            *dest = src.into();
1320        }
1321    }
1322
1323    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1324        for (src, dest) in it.zip(
1325            [&mut self.msr_mtrr_def_type]
1326                .into_iter()
1327                .chain(&mut self.fixed)
1328                .chain(&mut self.variable),
1329        ) {
1330            *dest = src.as_u64();
1331        }
1332    }
1333}
1334
1335impl StateElement<X86PartitionCapabilities, X86VpInfo> for Mtrrs {
1336    fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1337        true
1338    }
1339
1340    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1341        Self {
1342            msr_mtrr_def_type: 0,
1343            fixed: [0; 11],
1344            variable: [0; 16],
1345        }
1346    }
1347}
1348
1349#[repr(C)]
1350#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1351#[mesh(package = "virt.x86")]
1352#[inspect(hex)]
1353pub struct VirtualMsrs {
1354    #[mesh(1)]
1355    pub kernel_gs_base: u64,
1356    #[mesh(2)]
1357    pub sysenter_cs: u64,
1358    #[mesh(3)]
1359    pub sysenter_eip: u64,
1360    #[mesh(4)]
1361    pub sysenter_esp: u64,
1362    #[mesh(5)]
1363    pub star: u64,
1364    #[mesh(6)]
1365    pub lstar: u64,
1366    #[mesh(7)]
1367    pub cstar: u64,
1368    #[mesh(8)]
1369    pub sfmask: u64,
1370}
1371
1372impl HvRegisterState<HvX64RegisterName, 8> for VirtualMsrs {
1373    fn names(&self) -> &'static [HvX64RegisterName; 8] {
1374        &[
1375            HvX64RegisterName::KernelGsBase,
1376            HvX64RegisterName::SysenterCs,
1377            HvX64RegisterName::SysenterEsp,
1378            HvX64RegisterName::SysenterEip,
1379            HvX64RegisterName::Star,
1380            HvX64RegisterName::Lstar,
1381            HvX64RegisterName::Cstar,
1382            HvX64RegisterName::Sfmask,
1383        ]
1384    }
1385
1386    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1387        for (dest, src) in it.zip([
1388            self.kernel_gs_base,
1389            self.sysenter_cs,
1390            self.sysenter_eip,
1391            self.sysenter_esp,
1392            self.star,
1393            self.lstar,
1394            self.cstar,
1395            self.sfmask,
1396        ]) {
1397            *dest = src.into();
1398        }
1399    }
1400
1401    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1402        for (src, dest) in it.zip([
1403            &mut self.kernel_gs_base,
1404            &mut self.sysenter_cs,
1405            &mut self.sysenter_eip,
1406            &mut self.sysenter_esp,
1407            &mut self.star,
1408            &mut self.lstar,
1409            &mut self.cstar,
1410            &mut self.sfmask,
1411        ]) {
1412            *dest = src.as_u64();
1413        }
1414    }
1415}
1416
1417impl StateElement<X86PartitionCapabilities, X86VpInfo> for VirtualMsrs {
1418    fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1419        true
1420    }
1421
1422    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1423        Self {
1424            kernel_gs_base: 0,
1425            sysenter_cs: 0,
1426            sysenter_eip: 0,
1427            sysenter_esp: 0,
1428            star: 0,
1429            lstar: 0,
1430            cstar: 0,
1431            sfmask: 0,
1432        }
1433    }
1434}
1435
1436#[repr(C)]
1437#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1438#[mesh(package = "virt.x86")]
1439pub struct TscAux {
1440    #[mesh(1)]
1441    #[inspect(hex)]
1442    pub value: u64,
1443}
1444
1445impl HvRegisterState<HvX64RegisterName, 1> for TscAux {
1446    fn names(&self) -> &'static [HvX64RegisterName; 1] {
1447        &[HvX64RegisterName::TscAux]
1448    }
1449
1450    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1451        for (dest, src) in it.zip([self.value]) {
1452            *dest = src.into();
1453        }
1454    }
1455
1456    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1457        for (src, dest) in it.zip([&mut self.value]) {
1458            *dest = src.as_u64();
1459        }
1460    }
1461}
1462
1463impl StateElement<X86PartitionCapabilities, X86VpInfo> for TscAux {
1464    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1465        caps.tsc_aux
1466    }
1467
1468    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1469        Default::default()
1470    }
1471}
1472
1473#[repr(C)]
1474#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1475#[mesh(package = "virt.x86")]
1476pub struct Tsc {
1477    #[mesh(1)]
1478    #[inspect(hex)]
1479    pub value: u64,
1480}
1481
1482impl HvRegisterState<HvX64RegisterName, 1> for Tsc {
1483    fn names(&self) -> &'static [HvX64RegisterName; 1] {
1484        &[HvX64RegisterName::Tsc]
1485    }
1486
1487    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1488        for (dest, src) in it.zip([self.value]) {
1489            *dest = src.into();
1490        }
1491    }
1492
1493    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1494        for (src, dest) in it.zip([&mut self.value]) {
1495            *dest = src.as_u64();
1496        }
1497    }
1498}
1499
1500impl StateElement<X86PartitionCapabilities, X86VpInfo> for Tsc {
1501    fn is_present(_caps: &X86PartitionCapabilities) -> bool {
1502        true
1503    }
1504
1505    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1506        Self { value: 0 }
1507    }
1508
1509    fn can_compare(caps: &X86PartitionCapabilities) -> bool {
1510        caps.can_freeze_time
1511    }
1512}
1513
1514#[repr(C)]
1515#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1516#[mesh(package = "virt.x86")]
1517pub struct Cet {
1518    #[mesh(1)]
1519    #[inspect(hex)]
1520    pub scet: u64,
1521    // Ucet is part of xsave state.
1522}
1523
1524impl HvRegisterState<HvX64RegisterName, 1> for Cet {
1525    fn names(&self) -> &'static [HvX64RegisterName; 1] {
1526        &[HvX64RegisterName::SCet]
1527    }
1528
1529    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1530        for (dest, src) in it.zip([self.scet]) {
1531            *dest = src.into();
1532        }
1533    }
1534
1535    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1536        for (src, dest) in it.zip([&mut self.scet]) {
1537            *dest = src.as_u64();
1538        }
1539    }
1540}
1541
1542impl StateElement<X86PartitionCapabilities, X86VpInfo> for Cet {
1543    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1544        caps.cet
1545    }
1546
1547    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1548        Self { scet: 0 }
1549    }
1550}
1551
1552#[repr(C)]
1553#[derive(Default, Debug, PartialEq, Eq, Protobuf, Inspect)]
1554#[mesh(package = "virt.x86")]
1555#[inspect(hex)]
1556pub struct CetSs {
1557    #[mesh(1)]
1558    pub ssp: u64,
1559    #[mesh(2)]
1560    pub interrupt_ssp_table_addr: u64,
1561    // Plx_ssp are part of xsave state.
1562}
1563
1564impl HvRegisterState<HvX64RegisterName, 2> for CetSs {
1565    fn names(&self) -> &'static [HvX64RegisterName; 2] {
1566        &[
1567            HvX64RegisterName::Ssp,
1568            HvX64RegisterName::InterruptSspTableAddr,
1569        ]
1570    }
1571
1572    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1573        for (dest, src) in it.zip([self.ssp, self.interrupt_ssp_table_addr]) {
1574            *dest = src.into();
1575        }
1576    }
1577
1578    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1579        for (src, dest) in it.zip([&mut self.ssp, &mut self.interrupt_ssp_table_addr]) {
1580            *dest = src.as_u64();
1581        }
1582    }
1583}
1584
1585impl StateElement<X86PartitionCapabilities, X86VpInfo> for CetSs {
1586    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1587        caps.cet_ss
1588    }
1589
1590    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1591        Default::default()
1592    }
1593}
1594
1595#[repr(C)]
1596#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1597#[mesh(package = "virt.x86")]
1598#[inspect(hex)]
1599pub struct SyntheticMsrs {
1600    #[mesh(1)]
1601    pub vp_assist_page: u64,
1602    #[mesh(2)]
1603    pub scontrol: u64,
1604    #[mesh(3)]
1605    pub siefp: u64,
1606    #[mesh(4)]
1607    pub simp: u64,
1608    #[mesh(5)]
1609    #[inspect(iter_by_index)]
1610    pub sint: [u64; 16],
1611}
1612
1613impl HvRegisterState<HvX64RegisterName, 20> for SyntheticMsrs {
1614    fn names(&self) -> &'static [HvX64RegisterName; 20] {
1615        &[
1616            HvX64RegisterName::VpAssistPage,
1617            HvX64RegisterName::Scontrol,
1618            HvX64RegisterName::Sifp,
1619            HvX64RegisterName::Sipp,
1620            HvX64RegisterName::Sint0,
1621            HvX64RegisterName::Sint1,
1622            HvX64RegisterName::Sint2,
1623            HvX64RegisterName::Sint3,
1624            HvX64RegisterName::Sint4,
1625            HvX64RegisterName::Sint5,
1626            HvX64RegisterName::Sint6,
1627            HvX64RegisterName::Sint7,
1628            HvX64RegisterName::Sint8,
1629            HvX64RegisterName::Sint9,
1630            HvX64RegisterName::Sint10,
1631            HvX64RegisterName::Sint11,
1632            HvX64RegisterName::Sint12,
1633            HvX64RegisterName::Sint13,
1634            HvX64RegisterName::Sint14,
1635            HvX64RegisterName::Sint15,
1636        ]
1637    }
1638    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
1639        for (dest, src) in it.zip(
1640            [self.vp_assist_page, self.scontrol, self.siefp, self.simp]
1641                .into_iter()
1642                .chain(self.sint),
1643        ) {
1644            *dest = src.into();
1645        }
1646    }
1647
1648    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
1649        for (src, dest) in it.zip(
1650            [
1651                &mut self.vp_assist_page,
1652                &mut self.scontrol,
1653                &mut self.siefp,
1654                &mut self.simp,
1655            ]
1656            .into_iter()
1657            .chain(&mut self.sint),
1658        ) {
1659            *dest = src.as_u64();
1660        }
1661    }
1662}
1663
1664impl StateElement<X86PartitionCapabilities, X86VpInfo> for SyntheticMsrs {
1665    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1666        caps.hv1
1667    }
1668
1669    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1670        Self {
1671            vp_assist_page: 0,
1672            scontrol: 1,
1673            siefp: 0,
1674            simp: 0,
1675            sint: [0x10000; 16],
1676        }
1677    }
1678}
1679
1680#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Protobuf, Inspect)]
1681#[mesh(package = "virt.x86")]
1682#[inspect(hex)]
1683pub struct SynicTimer {
1684    #[mesh(1)]
1685    pub config: u64,
1686    #[mesh(2)]
1687    pub count: u64,
1688    #[mesh(3)]
1689    pub adjustment: u64,
1690    #[mesh(4)]
1691    pub undelivered_message_expiration_time: Option<u64>,
1692}
1693
1694#[derive(Debug, Copy, Clone, Eq, PartialEq, Protobuf, Inspect)]
1695#[mesh(package = "virt.x86")]
1696pub struct SynicTimers {
1697    #[mesh(1)]
1698    #[inspect(iter_by_index)]
1699    pub timers: [SynicTimer; 4],
1700}
1701
1702impl SynicTimers {
1703    pub fn as_hv(&self) -> hvdef::HvSyntheticTimersState {
1704        let timers = self.timers.map(|timer| hvdef::HvStimerState {
1705            undelivered_message_pending: timer.undelivered_message_expiration_time.is_some().into(),
1706            reserved: 0,
1707            config: timer.config,
1708            count: timer.count,
1709            adjustment: timer.adjustment,
1710            undelivered_expiration_time: timer.undelivered_message_expiration_time.unwrap_or(0),
1711        });
1712
1713        hvdef::HvSyntheticTimersState {
1714            timers,
1715            reserved: [0; 5],
1716        }
1717    }
1718
1719    pub fn from_hv(state: hvdef::HvSyntheticTimersState) -> Self {
1720        let timers = state.timers.map(|timer| SynicTimer {
1721            config: timer.config,
1722            count: timer.count,
1723            adjustment: timer.adjustment,
1724            undelivered_message_expiration_time: (timer.undelivered_message_pending & 1 != 0)
1725                .then_some(timer.undelivered_expiration_time),
1726        });
1727        Self { timers }
1728    }
1729}
1730
1731impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicTimers {
1732    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1733        caps.hv1
1734    }
1735
1736    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1737        Self {
1738            timers: [SynicTimer::default(); 4],
1739        }
1740    }
1741
1742    fn can_compare(_caps: &X86PartitionCapabilities) -> bool {
1743        // These can't be compared, since the hypervisor may choose to
1744        // immediately deliver the undelivered message.
1745        false
1746    }
1747}
1748
1749#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
1750#[mesh(package = "virt.x86")]
1751pub struct SynicMessageQueues {
1752    #[mesh(1)]
1753    #[inspect(with = "|x| inspect::iter_by_index(x.iter().map(Vec::len))")]
1754    pub queues: [Vec<[u8; HV_MESSAGE_SIZE]>; 16],
1755}
1756
1757impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicMessageQueues {
1758    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1759        caps.hv1
1760    }
1761
1762    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1763        Default::default()
1764    }
1765}
1766
1767#[derive(Debug, Copy, Clone, PartialEq, Eq, Protobuf, Inspect)]
1768#[mesh(package = "virt.x86")]
1769#[inspect(skip)]
1770pub struct SynicMessagePage {
1771    #[mesh(1)]
1772    pub data: [u8; 4096],
1773}
1774
1775impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicMessagePage {
1776    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1777        caps.hv1
1778    }
1779
1780    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1781        Self { data: [0; 4096] }
1782    }
1783}
1784
1785#[derive(Debug, Copy, Clone, PartialEq, Eq, Protobuf, Inspect)]
1786#[mesh(package = "virt.x86")]
1787#[inspect(skip)]
1788pub struct SynicEventFlagsPage {
1789    #[mesh(1)]
1790    pub data: [u8; 4096],
1791}
1792
1793impl StateElement<X86PartitionCapabilities, X86VpInfo> for SynicEventFlagsPage {
1794    fn is_present(caps: &X86PartitionCapabilities) -> bool {
1795        caps.hv1
1796    }
1797
1798    fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
1799        Self { data: [0; 4096] }
1800    }
1801}
1802
1803state_trait! {
1804    "Per-VP state",
1805    AccessVpState,
1806    X86PartitionCapabilities,
1807    X86VpInfo,
1808    VpSavedState,
1809    "virt.x86",
1810    (1, "registers", registers, set_registers, Registers),
1811    (2, "activity", activity, set_activity, Activity),
1812    (3, "xsave", xsave, set_xsave, Xsave),
1813    (4, "apic", apic, set_apic, Apic),
1814    (5, "xcr", xcr, set_xcr, Xcr0),
1815    (6, "xss", xss, set_xss, Xss),
1816    (7, "mtrrs", mtrrs, set_mtrrs, Mtrrs),
1817    (8, "pat", pat, set_pat, Pat),
1818    (9, "msrs", virtual_msrs, set_virtual_msrs, VirtualMsrs),
1819    (10, "drs", debug_regs, set_debug_regs, DebugRegisters),
1820    (11, "tsc", tsc, set_tsc, Tsc),
1821    (12, "cet", cet, set_cet, Cet),
1822    (13, "cet_ss", cet_ss, set_cet_ss, CetSs),
1823    (14, "tsc_aux", tsc_aux, set_tsc_aux, TscAux),
1824
1825    // Synic state
1826    (100, "synic", synic_msrs, set_synic_msrs, SyntheticMsrs),
1827    // The simp page contents must come after synic MSRs so that the SIMP page
1828    // register is set, but before the message queues and timers in case the
1829    // hypervisor decides to flush a pending message to the message page during
1830    // restore.
1831    (
1832        101,
1833        "simp",
1834        synic_message_page,
1835        set_synic_message_page,
1836        SynicMessagePage
1837    ),
1838    (
1839        102,
1840        "siefp",
1841        synic_event_flags_page,
1842        set_synic_event_flags_page,
1843        SynicEventFlagsPage
1844    ),
1845    (
1846        103,
1847        "synic_message_queues",
1848        synic_message_queues,
1849        set_synic_message_queues,
1850        SynicMessageQueues
1851    ),
1852    (104, "synic_timers", synic_timers, set_synic_timers, SynicTimers),
1853}
1854
1855/// Resets register state for an x86 INIT via the APIC.
1856pub fn x86_init<T: AccessVpState>(access: &mut T, vp_info: &X86VpInfo) -> Result<(), T::Error> {
1857    // Reset core register and debug register state, but preserve a few bits of cr0.
1858    let cr0 = access.registers()?.cr0;
1859    let mut regs = Registers::at_reset(access.caps(), vp_info);
1860    let cr0_mask = X64_CR0_NW | X64_CR0_CD;
1861    regs.cr0 = (cr0 & cr0_mask) | (regs.cr0 & !cr0_mask);
1862    access.set_registers(&regs)?;
1863    access.set_debug_regs(&StateElement::at_reset(access.caps(), vp_info))?;
1864
1865    // Reset the APIC state, leaving the APIC base address and APIC ID intact.
1866    //
1867    // Note that there may be still be pending interrupt requests in the APIC
1868    // (e.g. an incoming SIPI), which this should not affect.
1869    let current_apic = access.apic()?;
1870    let mut apic = Apic::at_reset(access.caps(), vp_info);
1871    apic.registers[x86defs::apic::ApicRegister::ID.0 as usize] =
1872        current_apic.registers[x86defs::apic::ApicRegister::ID.0 as usize];
1873    apic.apic_base = current_apic.apic_base;
1874    access.set_apic(&apic)?;
1875
1876    // Enable the wait-for-SIPI state.
1877    if !vp_info.base.is_bsp() {
1878        let mut activity = access.activity()?;
1879        activity.mp_state = MpState::WaitForSipi;
1880        access.set_activity(&activity)?;
1881    }
1882
1883    Ok(())
1884}