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