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