virt/aarch64/
vp.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::aarch64::Aarch64PartitionCapabilities;
5use crate::state::HvRegisterState;
6use crate::state::StateElement;
7use crate::state::state_trait;
8use aarch64defs::Cpsr64;
9use aarch64defs::SctlrEl1;
10use hvdef::HvArm64RegisterName;
11use hvdef::HvRegisterValue;
12use inspect::Inspect;
13use mesh_protobuf::Protobuf;
14use vm_topology::processor::aarch64::Aarch64VpInfo;
15
16#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
17#[mesh(package = "virt.aarch64")]
18#[inspect(hex)]
19pub struct Registers {
20    #[mesh(1)]
21    pub x0: u64,
22    #[mesh(2)]
23    pub x1: u64,
24    #[mesh(3)]
25    pub x2: u64,
26    #[mesh(4)]
27    pub x3: u64,
28    #[mesh(5)]
29    pub x4: u64,
30    #[mesh(6)]
31    pub x5: u64,
32    #[mesh(7)]
33    pub x6: u64,
34    #[mesh(8)]
35    pub x7: u64,
36    #[mesh(9)]
37    pub x8: u64,
38    #[mesh(10)]
39    pub x9: u64,
40    #[mesh(11)]
41    pub x10: u64,
42    #[mesh(12)]
43    pub x11: u64,
44    #[mesh(13)]
45    pub x12: u64,
46    #[mesh(14)]
47    pub x13: u64,
48    #[mesh(15)]
49    pub x14: u64,
50    #[mesh(16)]
51    pub x15: u64,
52    #[mesh(17)]
53    pub x16: u64,
54    #[mesh(18)]
55    pub x17: u64,
56    #[mesh(19)]
57    pub x18: u64,
58    #[mesh(20)]
59    pub x19: u64,
60    #[mesh(21)]
61    pub x20: u64,
62    #[mesh(22)]
63    pub x21: u64,
64    #[mesh(23)]
65    pub x22: u64,
66    #[mesh(24)]
67    pub x23: u64,
68    #[mesh(25)]
69    pub x24: u64,
70    #[mesh(26)]
71    pub x25: u64,
72    #[mesh(27)]
73    pub x26: u64,
74    #[mesh(28)]
75    pub x27: u64,
76    #[mesh(29)]
77    pub x28: u64,
78    #[mesh(30)]
79    pub fp: u64,
80    #[mesh(31)]
81    pub lr: u64,
82    #[mesh(32)]
83    pub sp_el0: u64,
84    #[mesh(33)]
85    pub sp_el1: u64,
86    #[mesh(34)]
87    pub pc: u64,
88    #[mesh(35)]
89    pub cpsr: u64,
90}
91
92impl HvRegisterState<HvArm64RegisterName, 35> for Registers {
93    fn names(&self) -> &'static [HvArm64RegisterName; 35] {
94        &[
95            HvArm64RegisterName::X0,
96            HvArm64RegisterName::X1,
97            HvArm64RegisterName::X2,
98            HvArm64RegisterName::X3,
99            HvArm64RegisterName::X4,
100            HvArm64RegisterName::X5,
101            HvArm64RegisterName::X6,
102            HvArm64RegisterName::X7,
103            HvArm64RegisterName::X8,
104            HvArm64RegisterName::X9,
105            HvArm64RegisterName::X10,
106            HvArm64RegisterName::X11,
107            HvArm64RegisterName::X12,
108            HvArm64RegisterName::X13,
109            HvArm64RegisterName::X14,
110            HvArm64RegisterName::X15,
111            HvArm64RegisterName::X16,
112            HvArm64RegisterName::X17,
113            HvArm64RegisterName::X18,
114            HvArm64RegisterName::X19,
115            HvArm64RegisterName::X20,
116            HvArm64RegisterName::X21,
117            HvArm64RegisterName::X22,
118            HvArm64RegisterName::X23,
119            HvArm64RegisterName::X24,
120            HvArm64RegisterName::X25,
121            HvArm64RegisterName::X26,
122            HvArm64RegisterName::X27,
123            HvArm64RegisterName::X28,
124            HvArm64RegisterName::XFp,
125            HvArm64RegisterName::XLr,
126            HvArm64RegisterName::XSpEl0,
127            HvArm64RegisterName::XSpElx,
128            HvArm64RegisterName::XPc,
129            HvArm64RegisterName::Cpsr,
130        ]
131    }
132
133    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
134        let &Self {
135            x0,
136            x1,
137            x2,
138            x3,
139            x4,
140            x5,
141            x6,
142            x7,
143            x8,
144            x9,
145            x10,
146            x11,
147            x12,
148            x13,
149            x14,
150            x15,
151            x16,
152            x17,
153            x18,
154            x19,
155            x20,
156            x21,
157            x22,
158            x23,
159            x24,
160            x25,
161            x26,
162            x27,
163            x28,
164            fp,
165            lr,
166            sp_el0,
167            sp_el1,
168            pc,
169            cpsr,
170        } = self;
171        for (dest, src) in it.zip([
172            x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18,
173            x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, fp, lr, sp_el0, sp_el1, pc, cpsr,
174        ]) {
175            *dest = src.into()
176        }
177    }
178
179    fn set_values(&mut self, mut it: impl Iterator<Item = HvRegisterValue>) {
180        let Self {
181            x0,
182            x1,
183            x2,
184            x3,
185            x4,
186            x5,
187            x6,
188            x7,
189            x8,
190            x9,
191            x10,
192            x11,
193            x12,
194            x13,
195            x14,
196            x15,
197            x16,
198            x17,
199            x18,
200            x19,
201            x20,
202            x21,
203            x22,
204            x23,
205            x24,
206            x25,
207            x26,
208            x27,
209            x28,
210            fp,
211            lr,
212            sp_el0,
213            sp_el1,
214            pc,
215            cpsr,
216        } = self;
217        for (dest, src) in [
218            x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18,
219            x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, fp, lr, sp_el0, sp_el1, pc, cpsr,
220        ]
221        .into_iter()
222        .zip(&mut it)
223        {
224            *dest = src.as_u64();
225        }
226    }
227}
228
229impl StateElement<Aarch64PartitionCapabilities, Aarch64VpInfo> for Registers {
230    fn is_present(_caps: &Aarch64PartitionCapabilities) -> bool {
231        true
232    }
233
234    fn at_reset(_caps: &Aarch64PartitionCapabilities, _vp_info: &Aarch64VpInfo) -> Self {
235        Self {
236            x0: 0,
237            x1: 0,
238            x2: 0,
239            x3: 0,
240            x4: 0,
241            x5: 0,
242            x6: 0,
243            x7: 0,
244            x8: 0,
245            x9: 0,
246            x10: 0,
247            x11: 0,
248            x12: 0,
249            x13: 0,
250            x14: 0,
251            x15: 0,
252            x16: 0,
253            x17: 0,
254            x18: 0,
255            x19: 0,
256            x20: 0,
257            x21: 0,
258            x22: 0,
259            x23: 0,
260            x24: 0,
261            x25: 0,
262            x26: 0,
263            x27: 0,
264            x28: 0,
265            fp: 0,
266            lr: 0,
267            sp_el0: 0,
268            sp_el1: 0,
269            pc: 0,
270            cpsr: Cpsr64::new()
271                .with_sp(true)
272                .with_el(1)
273                .with_f(true)
274                .with_i(true)
275                .with_a(true)
276                .with_d(true)
277                .into(),
278        }
279    }
280}
281
282#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Protobuf, Inspect)]
283#[mesh(package = "virt.aarch64")]
284pub struct SystemRegisters {
285    #[inspect(hex)]
286    #[mesh(1)]
287    pub sctlr_el1: u64,
288    #[inspect(hex)]
289    #[mesh(2)]
290    pub ttbr0_el1: u64,
291    #[inspect(hex)]
292    #[mesh(3)]
293    pub ttbr1_el1: u64,
294    #[inspect(hex)]
295    #[mesh(4)]
296    pub tcr_el1: u64,
297    #[inspect(hex)]
298    #[mesh(5)]
299    pub esr_el1: u64,
300    #[inspect(hex)]
301    #[mesh(6)]
302    pub far_el1: u64,
303    #[inspect(hex)]
304    #[mesh(7)]
305    pub mair_el1: u64,
306    #[inspect(hex)]
307    #[mesh(8)]
308    pub elr_el1: u64,
309    #[inspect(hex)]
310    #[mesh(9)]
311    pub vbar_el1: u64,
312}
313
314impl HvRegisterState<HvArm64RegisterName, 9> for SystemRegisters {
315    fn names(&self) -> &'static [HvArm64RegisterName; 9] {
316        &[
317            HvArm64RegisterName::SctlrEl1,
318            HvArm64RegisterName::Ttbr0El1,
319            HvArm64RegisterName::Ttbr1El1,
320            HvArm64RegisterName::TcrEl1,
321            HvArm64RegisterName::EsrEl1,
322            HvArm64RegisterName::FarEl1,
323            HvArm64RegisterName::MairEl1,
324            HvArm64RegisterName::ElrEl1,
325            HvArm64RegisterName::VbarEl1,
326        ]
327    }
328
329    fn get_values<'a>(&self, it: impl Iterator<Item = &'a mut HvRegisterValue>) {
330        let &Self {
331            sctlr_el1,
332            ttbr0_el1,
333            ttbr1_el1,
334            tcr_el1,
335            esr_el1,
336            far_el1,
337            mair_el1,
338            elr_el1,
339            vbar_el1,
340        } = self;
341        for (dest, src) in it.zip([
342            sctlr_el1, ttbr0_el1, ttbr1_el1, tcr_el1, esr_el1, far_el1, mair_el1, elr_el1, vbar_el1,
343        ]) {
344            *dest = src.into();
345        }
346    }
347
348    fn set_values(&mut self, it: impl Iterator<Item = HvRegisterValue>) {
349        let Self {
350            sctlr_el1,
351            ttbr0_el1,
352            ttbr1_el1,
353            tcr_el1,
354            esr_el1,
355            far_el1,
356            mair_el1,
357            elr_el1,
358            vbar_el1,
359        } = self;
360        for (src, dest) in it.zip([
361            sctlr_el1, ttbr0_el1, ttbr1_el1, tcr_el1, esr_el1, far_el1, mair_el1, elr_el1, vbar_el1,
362        ]) {
363            *dest = src.as_u64();
364        }
365    }
366}
367
368impl StateElement<Aarch64PartitionCapabilities, Aarch64VpInfo> for SystemRegisters {
369    fn is_present(_caps: &Aarch64PartitionCapabilities) -> bool {
370        true
371    }
372
373    fn at_reset(_caps: &Aarch64PartitionCapabilities, _vp: &Aarch64VpInfo) -> Self {
374        Self {
375            // TODO-aarch64: the spec specifies additional 1 bits at reset, but
376            // mshv doesn't seem to match. Investigate.
377            sctlr_el1: u64::from(
378                SctlrEl1::new()
379                    .with_eos(true)
380                    .with_tscxt(true)
381                    .with_eis(true)
382                    .with_span(true)
383                    .with_n_tlsmd(true)
384                    .with_lsmaoe(true),
385            ),
386            ttbr0_el1: 0,
387            ttbr1_el1: 0,
388            tcr_el1: 0,
389            esr_el1: 0,
390            far_el1: 0,
391            mair_el1: 0,
392            elr_el1: 0,
393            vbar_el1: 0,
394        }
395    }
396}
397
398state_trait! {
399    "Per-VP state",
400    AccessVpState,
401    Aarch64PartitionCapabilities,
402    Aarch64VpInfo,
403    VpSavedState,
404    "virt.aarch64",
405    (1, "registers", registers, set_registers, Registers),
406    (2, "system_registers", system_registers, set_system_registers, SystemRegisters),
407}