1use super::X86PartitionCapabilities;
7use crate::state::HvRegisterState;
8use crate::state::StateElement;
9use crate::state::state_trait;
10use hvdef::HvRegisterValue;
11use hvdef::HvX64RegisterName;
12use inspect::Inspect;
13use mesh_protobuf::Protobuf;
14use vm_topology::processor::x86::X86VpInfo;
15
16#[repr(C)]
17#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
18#[mesh(package = "virt.x86")]
19pub struct HypercallMsrs {
20 #[mesh(1)]
21 #[inspect(hex)]
22 pub guest_os_id: u64,
23 #[mesh(2)]
24 #[inspect(hex)]
25 pub hypercall: u64,
26}
27
28impl HvRegisterState<HvX64RegisterName, 2> for HypercallMsrs {
29 fn names(&self) -> &'static [HvX64RegisterName; 2] {
30 &[HvX64RegisterName::GuestOsId, HvX64RegisterName::Hypercall]
31 }
32
33 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
34 for (dest, src) in it.zip([self.guest_os_id, self.hypercall]) {
35 *dest = src.into();
36 }
37 }
38
39 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
40 for (src, dest) in it.zip([&mut self.guest_os_id, &mut self.hypercall]) {
41 *dest = src.as_u64();
42 }
43 }
44}
45
46impl StateElement<X86PartitionCapabilities, X86VpInfo> for HypercallMsrs {
47 fn is_present(caps: &X86PartitionCapabilities) -> bool {
48 caps.hv1
49 }
50
51 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
52 Self::default()
53 }
54}
55
56#[repr(C)]
57#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
58#[mesh(package = "virt.x86")]
59pub struct ReferenceTscPage {
60 #[mesh(1)]
61 #[inspect(hex)]
62 pub tsc_reference_page: u64,
63}
64
65impl HvRegisterState<HvX64RegisterName, 1> for ReferenceTscPage {
66 fn names(&self) -> &'static [HvX64RegisterName; 1] {
67 &[HvX64RegisterName::ReferenceTsc]
68 }
69
70 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
71 for (dest, src) in it.zip([self.tsc_reference_page]) {
72 *dest = src.into();
73 }
74 }
75
76 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
77 for (src, dest) in it.zip([&mut self.tsc_reference_page]) {
78 *dest = src.as_u64();
79 }
80 }
81}
82
83impl StateElement<X86PartitionCapabilities, X86VpInfo> for ReferenceTscPage {
84 fn is_present(caps: &X86PartitionCapabilities) -> bool {
85 caps.hv1_reference_tsc_page
86 }
87
88 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
89 Self::default()
90 }
91}
92
93#[repr(C)]
94#[derive(Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
95#[mesh(package = "virt.x86")]
96pub struct ReferenceTime {
97 #[mesh(1)]
98 #[inspect(hex)]
99 pub value: u64,
100}
101
102impl HvRegisterState<HvX64RegisterName, 1> for ReferenceTime {
103 fn names(&self) -> &'static [HvX64RegisterName; 1] {
104 &[HvX64RegisterName::TimeRefCount]
105 }
106
107 fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
108 for (dest, src) in it.zip([self.value]) {
109 *dest = src.into();
110 }
111 }
112
113 fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
114 for (src, dest) in it.zip([&mut self.value]) {
115 *dest = src.as_u64();
116 }
117 }
118}
119
120impl StateElement<X86PartitionCapabilities, X86VpInfo> for ReferenceTime {
121 fn is_present(caps: &X86PartitionCapabilities) -> bool {
122 caps.hv1
123 }
124
125 fn at_reset(_caps: &X86PartitionCapabilities, _vp_info: &X86VpInfo) -> Self {
126 Self { value: 0 }
127 }
128
129 fn can_compare(caps: &X86PartitionCapabilities) -> bool {
130 caps.can_freeze_time
131 }
132}
133
134state_trait!(
135 "Access to per-VM state.",
136 AccessVmState,
137 X86PartitionCapabilities,
138 X86VpInfo,
139 VmSavedState,
140 "virt.x86",
141 (1, "hypercall", hypercall, set_hypercall, HypercallMsrs),
142 (2, "reftime", reftime, set_reftime, ReferenceTime),
143 (
144 3,
145 "reference_tsc_page",
146 reference_tsc_page,
147 set_reference_tsc_page,
148 ReferenceTscPage,
149 ),
150);