Skip to main content

virt/aarch64/
vp.rs

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