xref: /aosp_15_r20/external/crosvm/hypervisor/src/aarch64.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryFrom;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Debug;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use base::Error;
10*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
11*bb4ee6a4SAndroid Build Coastguard Worker use cros_fdt::Fdt;
12*bb4ee6a4SAndroid Build Coastguard Worker use downcast_rs::impl_downcast;
13*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL;
14*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
15*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
16*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
17*bb4ee6a4SAndroid Build Coastguard Worker 
18*bb4ee6a4SAndroid Build Coastguard Worker use crate::Hypervisor;
19*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqRoute;
20*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqSource;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqSourceChip;
22*bb4ee6a4SAndroid Build Coastguard Worker use crate::Vcpu;
23*bb4ee6a4SAndroid Build Coastguard Worker use crate::Vm;
24*bb4ee6a4SAndroid Build Coastguard Worker 
25*bb4ee6a4SAndroid Build Coastguard Worker /// Represents a version of Power State Coordination Interface (PSCI).
26*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Eq, Ord, PartialEq, PartialOrd)]
27*bb4ee6a4SAndroid Build Coastguard Worker pub struct PsciVersion {
28*bb4ee6a4SAndroid Build Coastguard Worker     pub major: u16,
29*bb4ee6a4SAndroid Build Coastguard Worker     pub minor: u16,
30*bb4ee6a4SAndroid Build Coastguard Worker }
31*bb4ee6a4SAndroid Build Coastguard Worker 
32*bb4ee6a4SAndroid Build Coastguard Worker impl PsciVersion {
new(major: u16, minor: u16) -> Result<Self>33*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(major: u16, minor: u16) -> Result<Self> {
34*bb4ee6a4SAndroid Build Coastguard Worker         if (major as i16) < 0 {
35*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::new(EINVAL))
36*bb4ee6a4SAndroid Build Coastguard Worker         } else {
37*bb4ee6a4SAndroid Build Coastguard Worker             Ok(Self { major, minor })
38*bb4ee6a4SAndroid Build Coastguard Worker         }
39*bb4ee6a4SAndroid Build Coastguard Worker     }
40*bb4ee6a4SAndroid Build Coastguard Worker }
41*bb4ee6a4SAndroid Build Coastguard Worker 
42*bb4ee6a4SAndroid Build Coastguard Worker impl TryFrom<u32> for PsciVersion {
43*bb4ee6a4SAndroid Build Coastguard Worker     type Error = base::Error;
44*bb4ee6a4SAndroid Build Coastguard Worker 
try_from(item: u32) -> Result<Self>45*bb4ee6a4SAndroid Build Coastguard Worker     fn try_from(item: u32) -> Result<Self> {
46*bb4ee6a4SAndroid Build Coastguard Worker         Self::new((item >> 16) as u16, item as u16)
47*bb4ee6a4SAndroid Build Coastguard Worker     }
48*bb4ee6a4SAndroid Build Coastguard Worker }
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker // Aarch64 does not provide a concrete number as to how many registers exist.
51*bb4ee6a4SAndroid Build Coastguard Worker // The list of registers available exceeds 600 registers
52*bb4ee6a4SAndroid Build Coastguard Worker pub const AARCH64_MAX_REG_COUNT: usize = 1024;
53*bb4ee6a4SAndroid Build Coastguard Worker 
54*bb4ee6a4SAndroid Build Coastguard Worker pub const PSCI_0_2: PsciVersion = PsciVersion { major: 0, minor: 2 };
55*bb4ee6a4SAndroid Build Coastguard Worker pub const PSCI_1_0: PsciVersion = PsciVersion { major: 1, minor: 0 };
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker /// AArch64 system register as used in MSR/MRS instructions.
58*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize)]
59*bb4ee6a4SAndroid Build Coastguard Worker #[serde(transparent)]
60*bb4ee6a4SAndroid Build Coastguard Worker pub struct AArch64SysRegId(u16);
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker impl AArch64SysRegId {
63*bb4ee6a4SAndroid Build Coastguard Worker     /// Construct a system register ID from Op0, Op1, CRn, CRm, Op2.
64*bb4ee6a4SAndroid Build Coastguard Worker     ///
65*bb4ee6a4SAndroid Build Coastguard Worker     /// The meanings of the arguments are described in the ARMv8 Architecture Reference Manual
66*bb4ee6a4SAndroid Build Coastguard Worker     /// "System instruction class encoding overview" section.
new(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8) -> Result<Self>67*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8) -> Result<Self> {
68*bb4ee6a4SAndroid Build Coastguard Worker         if op0 > 0b11 || op1 > 0b111 || crn > 0b1111 || crm > 0b1111 || op2 > 0b111 {
69*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(EINVAL));
70*bb4ee6a4SAndroid Build Coastguard Worker         }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Self::new_unchecked(op0, op1, crn, crm, op2))
73*bb4ee6a4SAndroid Build Coastguard Worker     }
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker     /// Construct a system register ID from Op0, Op1, CRn, CRm, Op2.
76*bb4ee6a4SAndroid Build Coastguard Worker     ///
77*bb4ee6a4SAndroid Build Coastguard Worker     /// Out-of-range values will be silently truncated.
new_unchecked(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8) -> Self78*bb4ee6a4SAndroid Build Coastguard Worker     pub const fn new_unchecked(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8) -> Self {
79*bb4ee6a4SAndroid Build Coastguard Worker         let op0 = (op0 as u16 & 0b11) << 14;
80*bb4ee6a4SAndroid Build Coastguard Worker         let op1 = (op1 as u16 & 0b111) << 11;
81*bb4ee6a4SAndroid Build Coastguard Worker         let crn = (crn as u16 & 0b1111) << 7;
82*bb4ee6a4SAndroid Build Coastguard Worker         let crm = (crm as u16 & 0b1111) << 3;
83*bb4ee6a4SAndroid Build Coastguard Worker         let op2 = op2 as u16 & 0b111;
84*bb4ee6a4SAndroid Build Coastguard Worker         Self(op0 | op1 | crn | crm | op2)
85*bb4ee6a4SAndroid Build Coastguard Worker     }
86*bb4ee6a4SAndroid Build Coastguard Worker 
from_encoded(v: u16) -> Self87*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_encoded(v: u16) -> Self {
88*bb4ee6a4SAndroid Build Coastguard Worker         Self(v)
89*bb4ee6a4SAndroid Build Coastguard Worker     }
90*bb4ee6a4SAndroid Build Coastguard Worker 
91*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
op0(&self) -> u892*bb4ee6a4SAndroid Build Coastguard Worker     pub const fn op0(&self) -> u8 {
93*bb4ee6a4SAndroid Build Coastguard Worker         ((self.0 >> 14) & 0b11) as u8
94*bb4ee6a4SAndroid Build Coastguard Worker     }
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
op1(&self) -> u897*bb4ee6a4SAndroid Build Coastguard Worker     pub const fn op1(&self) -> u8 {
98*bb4ee6a4SAndroid Build Coastguard Worker         ((self.0 >> 11) & 0b111) as u8
99*bb4ee6a4SAndroid Build Coastguard Worker     }
100*bb4ee6a4SAndroid Build Coastguard Worker 
101*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
crn(&self) -> u8102*bb4ee6a4SAndroid Build Coastguard Worker     pub const fn crn(&self) -> u8 {
103*bb4ee6a4SAndroid Build Coastguard Worker         ((self.0 >> 7) & 0b1111) as u8
104*bb4ee6a4SAndroid Build Coastguard Worker     }
105*bb4ee6a4SAndroid Build Coastguard Worker 
106*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
crm(&self) -> u8107*bb4ee6a4SAndroid Build Coastguard Worker     pub const fn crm(&self) -> u8 {
108*bb4ee6a4SAndroid Build Coastguard Worker         ((self.0 >> 3) & 0b1111) as u8
109*bb4ee6a4SAndroid Build Coastguard Worker     }
110*bb4ee6a4SAndroid Build Coastguard Worker 
111*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
op2(&self) -> u8112*bb4ee6a4SAndroid Build Coastguard Worker     pub const fn op2(&self) -> u8 {
113*bb4ee6a4SAndroid Build Coastguard Worker         (self.0 & 0b111) as u8
114*bb4ee6a4SAndroid Build Coastguard Worker     }
115*bb4ee6a4SAndroid Build Coastguard Worker 
116*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the system register as encoded in bits 5-20 of MRS and MSR instructions.
encoded(&self) -> u16117*bb4ee6a4SAndroid Build Coastguard Worker     pub const fn encoded(&self) -> u16 {
118*bb4ee6a4SAndroid Build Coastguard Worker         self.0
119*bb4ee6a4SAndroid Build Coastguard Worker     }
120*bb4ee6a4SAndroid Build Coastguard Worker }
121*bb4ee6a4SAndroid Build Coastguard Worker 
122*bb4ee6a4SAndroid Build Coastguard Worker impl Debug for AArch64SysRegId {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result123*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124*bb4ee6a4SAndroid Build Coastguard Worker         f.debug_struct("AArch64SysRegId")
125*bb4ee6a4SAndroid Build Coastguard Worker             .field("Op0", &self.op0())
126*bb4ee6a4SAndroid Build Coastguard Worker             .field("Op1", &self.op1())
127*bb4ee6a4SAndroid Build Coastguard Worker             .field("CRn", &self.crn())
128*bb4ee6a4SAndroid Build Coastguard Worker             .field("CRm", &self.crm())
129*bb4ee6a4SAndroid Build Coastguard Worker             .field("Op2", &self.op2())
130*bb4ee6a4SAndroid Build Coastguard Worker             .finish()
131*bb4ee6a4SAndroid Build Coastguard Worker     }
132*bb4ee6a4SAndroid Build Coastguard Worker }
133*bb4ee6a4SAndroid Build Coastguard Worker 
134*bb4ee6a4SAndroid Build Coastguard Worker #[rustfmt::skip]
135*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_upper_case_globals)]
136*bb4ee6a4SAndroid Build Coastguard Worker impl AArch64SysRegId {
137*bb4ee6a4SAndroid Build Coastguard Worker     //                                                         Op0    Op1     CRn     CRm    Op2
138*bb4ee6a4SAndroid Build Coastguard Worker     pub const MPIDR_EL1: Self           = Self::new_unchecked(0b11, 0b000, 0b0000, 0b0000, 0b101);
139*bb4ee6a4SAndroid Build Coastguard Worker     pub const CCSIDR_EL1: Self          = Self::new_unchecked(0b11, 0b001, 0b0000, 0b0000, 0b000);
140*bb4ee6a4SAndroid Build Coastguard Worker     pub const CSSELR_EL1: Self          = Self::new_unchecked(0b11, 0b010, 0b0000, 0b0000, 0b000);
141*bb4ee6a4SAndroid Build Coastguard Worker     pub const FPCR: Self                = Self::new_unchecked(0b11, 0b011, 0b0100, 0b0100, 0b000);
142*bb4ee6a4SAndroid Build Coastguard Worker     pub const FPSR: Self                = Self::new_unchecked(0b11, 0b011, 0b0100, 0b0100, 0b001);
143*bb4ee6a4SAndroid Build Coastguard Worker     pub const SPSR_EL1: Self            = Self::new_unchecked(0b11, 0b000, 0b0100, 0b0000, 0b000);
144*bb4ee6a4SAndroid Build Coastguard Worker     pub const SPSR_irq: Self            = Self::new_unchecked(0b11, 0b100, 0b0100, 0b0011, 0b000);
145*bb4ee6a4SAndroid Build Coastguard Worker     pub const SPSR_abt: Self            = Self::new_unchecked(0b11, 0b100, 0b0100, 0b0011, 0b001);
146*bb4ee6a4SAndroid Build Coastguard Worker     pub const SPSR_und: Self            = Self::new_unchecked(0b11, 0b100, 0b0100, 0b0011, 0b010);
147*bb4ee6a4SAndroid Build Coastguard Worker     pub const SPSR_fiq: Self            = Self::new_unchecked(0b11, 0b100, 0b0100, 0b0011, 0b011);
148*bb4ee6a4SAndroid Build Coastguard Worker     pub const ELR_EL1: Self             = Self::new_unchecked(0b11, 0b000, 0b0100, 0b0000, 0b001);
149*bb4ee6a4SAndroid Build Coastguard Worker     pub const SP_EL1: Self              = Self::new_unchecked(0b11, 0b100, 0b0100, 0b0001, 0b000);
150*bb4ee6a4SAndroid Build Coastguard Worker     pub const CNTVCT_EL0: Self          = Self::new_unchecked(0b11, 0b011, 0b1110, 0b0000, 0b010);
151*bb4ee6a4SAndroid Build Coastguard Worker     pub const CNTV_CVAL_EL0: Self       = Self::new_unchecked(0b11, 0b011, 0b1110, 0b0011, 0b010);
152*bb4ee6a4SAndroid Build Coastguard Worker }
153*bb4ee6a4SAndroid Build Coastguard Worker 
154*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
155*bb4ee6a4SAndroid Build Coastguard Worker pub enum VcpuRegAArch64 {
156*bb4ee6a4SAndroid Build Coastguard Worker     X(u8),
157*bb4ee6a4SAndroid Build Coastguard Worker     Sp,
158*bb4ee6a4SAndroid Build Coastguard Worker     Pc,
159*bb4ee6a4SAndroid Build Coastguard Worker     Pstate,
160*bb4ee6a4SAndroid Build Coastguard Worker     System(AArch64SysRegId),
161*bb4ee6a4SAndroid Build Coastguard Worker }
162*bb4ee6a4SAndroid Build Coastguard Worker 
163*bb4ee6a4SAndroid Build Coastguard Worker /// A wrapper for using a VM on aarch64 and getting/setting its state.
164*bb4ee6a4SAndroid Build Coastguard Worker pub trait VmAArch64: Vm {
165*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the `Hypervisor` that created this VM.
get_hypervisor(&self) -> &dyn Hypervisor166*bb4ee6a4SAndroid Build Coastguard Worker     fn get_hypervisor(&self) -> &dyn Hypervisor;
167*bb4ee6a4SAndroid Build Coastguard Worker 
168*bb4ee6a4SAndroid Build Coastguard Worker     /// Load pVM firmware for the VM, creating a memslot for it as needed.
169*bb4ee6a4SAndroid Build Coastguard Worker     ///
170*bb4ee6a4SAndroid Build Coastguard Worker     /// Only works on protected VMs (i.e. those that support `VmCap::Protected`).
load_protected_vm_firmware(&mut self, fw_addr: GuestAddress, fw_max_size: u64) -> Result<()>171*bb4ee6a4SAndroid Build Coastguard Worker     fn load_protected_vm_firmware(&mut self, fw_addr: GuestAddress, fw_max_size: u64)
172*bb4ee6a4SAndroid Build Coastguard Worker         -> Result<()>;
173*bb4ee6a4SAndroid Build Coastguard Worker 
174*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a Vcpu with the specified Vcpu ID.
create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>>175*bb4ee6a4SAndroid Build Coastguard Worker     fn create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>>;
176*bb4ee6a4SAndroid Build Coastguard Worker 
177*bb4ee6a4SAndroid Build Coastguard Worker     /// Create DT configuration node for the hypervisor.
178*bb4ee6a4SAndroid Build Coastguard Worker     /// `fdt` - Fdt initialized at the root node.
179*bb4ee6a4SAndroid Build Coastguard Worker     /// `phandles` - Map of strings to a phandle.
create_fdt(&self, fdt: &mut Fdt, phandles: &BTreeMap<&str, u32>) -> cros_fdt::Result<()>180*bb4ee6a4SAndroid Build Coastguard Worker     fn create_fdt(&self, fdt: &mut Fdt, phandles: &BTreeMap<&str, u32>) -> cros_fdt::Result<()>;
181*bb4ee6a4SAndroid Build Coastguard Worker 
182*bb4ee6a4SAndroid Build Coastguard Worker     // Initialize a VM. Called after building the VM. Presently called before vCPUs are initialized.
init_arch( &self, payload_entry_address: GuestAddress, fdt_address: GuestAddress, fdt_size: usize, ) -> Result<()>183*bb4ee6a4SAndroid Build Coastguard Worker     fn init_arch(
184*bb4ee6a4SAndroid Build Coastguard Worker         &self,
185*bb4ee6a4SAndroid Build Coastguard Worker         payload_entry_address: GuestAddress,
186*bb4ee6a4SAndroid Build Coastguard Worker         fdt_address: GuestAddress,
187*bb4ee6a4SAndroid Build Coastguard Worker         fdt_size: usize,
188*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()>;
189*bb4ee6a4SAndroid Build Coastguard Worker 
190*bb4ee6a4SAndroid Build Coastguard Worker     /// Set an offset that describes a number of counter cycles that are subtracted from both
191*bb4ee6a4SAndroid Build Coastguard Worker     /// virtual and physical counter views.
set_counter_offset(&self, _offset: u64) -> Result<()>192*bb4ee6a4SAndroid Build Coastguard Worker     fn set_counter_offset(&self, _offset: u64) -> Result<()> {
193*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::new(libc::ENOSYS))
194*bb4ee6a4SAndroid Build Coastguard Worker     }
195*bb4ee6a4SAndroid Build Coastguard Worker }
196*bb4ee6a4SAndroid Build Coastguard Worker 
197*bb4ee6a4SAndroid Build Coastguard Worker /// A wrapper around creating and using a VCPU on aarch64.
198*bb4ee6a4SAndroid Build Coastguard Worker pub trait VcpuAArch64: Vcpu {
199*bb4ee6a4SAndroid Build Coastguard Worker     /// Does ARM-specific initialization of this VCPU.  Inits the VCPU with the preferred target
200*bb4ee6a4SAndroid Build Coastguard Worker     /// VCPU type and the specified `features`, and resets the value of all registers to defaults.
201*bb4ee6a4SAndroid Build Coastguard Worker     /// All VCPUs should be created before calling this function.
init(&self, features: &[VcpuFeature]) -> Result<()>202*bb4ee6a4SAndroid Build Coastguard Worker     fn init(&self, features: &[VcpuFeature]) -> Result<()>;
203*bb4ee6a4SAndroid Build Coastguard Worker 
204*bb4ee6a4SAndroid Build Coastguard Worker     /// Initializes the ARM Performance Monitor Unit v3 on this VCPU, with overflow interrupt number
205*bb4ee6a4SAndroid Build Coastguard Worker     /// `irq`.
init_pmu(&self, irq: u64) -> Result<()>206*bb4ee6a4SAndroid Build Coastguard Worker     fn init_pmu(&self, irq: u64) -> Result<()>;
207*bb4ee6a4SAndroid Build Coastguard Worker 
208*bb4ee6a4SAndroid Build Coastguard Worker     /// Checks if ARM ParaVirtualized Time is supported on this VCPU
has_pvtime_support(&self) -> bool209*bb4ee6a4SAndroid Build Coastguard Worker     fn has_pvtime_support(&self) -> bool;
210*bb4ee6a4SAndroid Build Coastguard Worker 
211*bb4ee6a4SAndroid Build Coastguard Worker     /// Initializes the ARM ParaVirtualized Time on this VCPU, with base address of the stolen time
212*bb4ee6a4SAndroid Build Coastguard Worker     /// structure as `pvtime_ipa`.
init_pvtime(&self, pvtime_ipa: u64) -> Result<()>213*bb4ee6a4SAndroid Build Coastguard Worker     fn init_pvtime(&self, pvtime_ipa: u64) -> Result<()>;
214*bb4ee6a4SAndroid Build Coastguard Worker 
215*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the value of a register on this VCPU.
set_one_reg(&self, reg_id: VcpuRegAArch64, data: u64) -> Result<()>216*bb4ee6a4SAndroid Build Coastguard Worker     fn set_one_reg(&self, reg_id: VcpuRegAArch64, data: u64) -> Result<()>;
217*bb4ee6a4SAndroid Build Coastguard Worker 
218*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the value of a register on this VCPU.
get_one_reg(&self, reg_id: VcpuRegAArch64) -> Result<u64>219*bb4ee6a4SAndroid Build Coastguard Worker     fn get_one_reg(&self, reg_id: VcpuRegAArch64) -> Result<u64>;
220*bb4ee6a4SAndroid Build Coastguard Worker 
221*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the value of a Neon vector register (V0-V31) on this VCPU.
set_vector_reg(&self, reg_num: u8, data: u128) -> Result<()>222*bb4ee6a4SAndroid Build Coastguard Worker     fn set_vector_reg(&self, reg_num: u8, data: u128) -> Result<()>;
223*bb4ee6a4SAndroid Build Coastguard Worker 
224*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the value of a Neon vector register (V0-V31) on this VCPU.
get_vector_reg(&self, reg_num: u8) -> Result<u128>225*bb4ee6a4SAndroid Build Coastguard Worker     fn get_vector_reg(&self, reg_num: u8) -> Result<u128>;
226*bb4ee6a4SAndroid Build Coastguard Worker 
227*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the set of system registers accessible by the hypervisor
get_system_regs(&self) -> Result<BTreeMap<AArch64SysRegId, u64>>228*bb4ee6a4SAndroid Build Coastguard Worker     fn get_system_regs(&self) -> Result<BTreeMap<AArch64SysRegId, u64>>;
229*bb4ee6a4SAndroid Build Coastguard Worker 
230*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the hypervisor specific data for snapshot
hypervisor_specific_snapshot(&self) -> anyhow::Result<serde_json::Value>231*bb4ee6a4SAndroid Build Coastguard Worker     fn hypervisor_specific_snapshot(&self) -> anyhow::Result<serde_json::Value>;
232*bb4ee6a4SAndroid Build Coastguard Worker 
233*bb4ee6a4SAndroid Build Coastguard Worker     /// Restores the hypervisor specific data
hypervisor_specific_restore(&self, _data: serde_json::Value) -> anyhow::Result<()>234*bb4ee6a4SAndroid Build Coastguard Worker     fn hypervisor_specific_restore(&self, _data: serde_json::Value) -> anyhow::Result<()>;
235*bb4ee6a4SAndroid Build Coastguard Worker 
236*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the value of MPIDR_EL1 on this VCPU.
get_mpidr(&self) -> Result<u64>237*bb4ee6a4SAndroid Build Coastguard Worker     fn get_mpidr(&self) -> Result<u64> {
238*bb4ee6a4SAndroid Build Coastguard Worker         const RES1: u64 = 1 << 31;
239*bb4ee6a4SAndroid Build Coastguard Worker 
240*bb4ee6a4SAndroid Build Coastguard Worker         // Assume that MPIDR_EL1.{U,MT} = {0,0}.
241*bb4ee6a4SAndroid Build Coastguard Worker 
242*bb4ee6a4SAndroid Build Coastguard Worker         let aff = u64::try_from(self.id()).unwrap();
243*bb4ee6a4SAndroid Build Coastguard Worker 
244*bb4ee6a4SAndroid Build Coastguard Worker         Ok(RES1 | aff)
245*bb4ee6a4SAndroid Build Coastguard Worker     }
246*bb4ee6a4SAndroid Build Coastguard Worker 
247*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the current PSCI version.
get_psci_version(&self) -> Result<PsciVersion>248*bb4ee6a4SAndroid Build Coastguard Worker     fn get_psci_version(&self) -> Result<PsciVersion>;
249*bb4ee6a4SAndroid Build Coastguard Worker 
250*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets up debug registers and configure vcpu for handling guest debug events.
set_guest_debug(&self, addrs: &[GuestAddress], enable_singlestep: bool) -> Result<()>251*bb4ee6a4SAndroid Build Coastguard Worker     fn set_guest_debug(&self, addrs: &[GuestAddress], enable_singlestep: bool) -> Result<()>;
252*bb4ee6a4SAndroid Build Coastguard Worker 
253*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the max number of hardware breakpoints.
get_max_hw_bps(&self) -> Result<usize>254*bb4ee6a4SAndroid Build Coastguard Worker     fn get_max_hw_bps(&self) -> Result<usize>;
255*bb4ee6a4SAndroid Build Coastguard Worker 
256*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the cache architecture information for all cache levels.
257*bb4ee6a4SAndroid Build Coastguard Worker     /// The keys of the map are the lower 4 lower significant bits of CSSELR_EL1, which represents
258*bb4ee6a4SAndroid Build Coastguard Worker     /// the cache level. cache level is actually located in bits [3:1], but the value saves also
259*bb4ee6a4SAndroid Build Coastguard Worker     /// if the cache is an instruction or data.
260*bb4ee6a4SAndroid Build Coastguard Worker     /// The values of the map are CCSIDR_EL1, which is the configuration of the cache.
get_cache_info(&self) -> Result<BTreeMap<u8, u64>>261*bb4ee6a4SAndroid Build Coastguard Worker     fn get_cache_info(&self) -> Result<BTreeMap<u8, u64>>;
262*bb4ee6a4SAndroid Build Coastguard Worker 
263*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the cache architecture information for all cache levels.
set_cache_info(&self, cache_info: BTreeMap<u8, u64>) -> Result<()>264*bb4ee6a4SAndroid Build Coastguard Worker     fn set_cache_info(&self, cache_info: BTreeMap<u8, u64>) -> Result<()>;
265*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot(&self) -> anyhow::Result<VcpuSnapshot>266*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot(&self) -> anyhow::Result<VcpuSnapshot> {
267*bb4ee6a4SAndroid Build Coastguard Worker         let mut snap = VcpuSnapshot {
268*bb4ee6a4SAndroid Build Coastguard Worker             vcpu_id: self.id(),
269*bb4ee6a4SAndroid Build Coastguard Worker             sp: self.get_one_reg(VcpuRegAArch64::Sp)?,
270*bb4ee6a4SAndroid Build Coastguard Worker             pc: self.get_one_reg(VcpuRegAArch64::Pc)?,
271*bb4ee6a4SAndroid Build Coastguard Worker             pstate: self.get_one_reg(VcpuRegAArch64::Pstate)?,
272*bb4ee6a4SAndroid Build Coastguard Worker             hypervisor_data: self.hypervisor_specific_snapshot()?,
273*bb4ee6a4SAndroid Build Coastguard Worker             sys: self.get_system_regs()?,
274*bb4ee6a4SAndroid Build Coastguard Worker             cache_arch_info: self.get_cache_info()?,
275*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
276*bb4ee6a4SAndroid Build Coastguard Worker         };
277*bb4ee6a4SAndroid Build Coastguard Worker 
278*bb4ee6a4SAndroid Build Coastguard Worker         for (n, xn) in snap.x.iter_mut().enumerate() {
279*bb4ee6a4SAndroid Build Coastguard Worker             *xn = self.get_one_reg(VcpuRegAArch64::X(n as u8))?;
280*bb4ee6a4SAndroid Build Coastguard Worker         }
281*bb4ee6a4SAndroid Build Coastguard Worker 
282*bb4ee6a4SAndroid Build Coastguard Worker         for (n, vn) in snap.v.iter_mut().enumerate() {
283*bb4ee6a4SAndroid Build Coastguard Worker             *vn = self.get_vector_reg(n as u8)?;
284*bb4ee6a4SAndroid Build Coastguard Worker         }
285*bb4ee6a4SAndroid Build Coastguard Worker 
286*bb4ee6a4SAndroid Build Coastguard Worker         Ok(snap)
287*bb4ee6a4SAndroid Build Coastguard Worker     }
288*bb4ee6a4SAndroid Build Coastguard Worker 
289*bb4ee6a4SAndroid Build Coastguard Worker     /// Restore VCPU
restore(&self, snapshot: &VcpuSnapshot) -> anyhow::Result<()>290*bb4ee6a4SAndroid Build Coastguard Worker     fn restore(&self, snapshot: &VcpuSnapshot) -> anyhow::Result<()> {
291*bb4ee6a4SAndroid Build Coastguard Worker         self.set_one_reg(VcpuRegAArch64::Sp, snapshot.sp)?;
292*bb4ee6a4SAndroid Build Coastguard Worker         self.set_one_reg(VcpuRegAArch64::Pc, snapshot.pc)?;
293*bb4ee6a4SAndroid Build Coastguard Worker         self.set_one_reg(VcpuRegAArch64::Pstate, snapshot.pstate)?;
294*bb4ee6a4SAndroid Build Coastguard Worker 
295*bb4ee6a4SAndroid Build Coastguard Worker         for (n, xn) in snapshot.x.iter().enumerate() {
296*bb4ee6a4SAndroid Build Coastguard Worker             self.set_one_reg(VcpuRegAArch64::X(n as u8), *xn)?;
297*bb4ee6a4SAndroid Build Coastguard Worker         }
298*bb4ee6a4SAndroid Build Coastguard Worker         for (n, vn) in snapshot.v.iter().enumerate() {
299*bb4ee6a4SAndroid Build Coastguard Worker             self.set_vector_reg(n as u8, *vn)?;
300*bb4ee6a4SAndroid Build Coastguard Worker         }
301*bb4ee6a4SAndroid Build Coastguard Worker         for (id, val) in &snapshot.sys {
302*bb4ee6a4SAndroid Build Coastguard Worker             self.set_one_reg(VcpuRegAArch64::System(*id), *val)?;
303*bb4ee6a4SAndroid Build Coastguard Worker         }
304*bb4ee6a4SAndroid Build Coastguard Worker         self.set_cache_info(snapshot.cache_arch_info.clone())?;
305*bb4ee6a4SAndroid Build Coastguard Worker         self.hypervisor_specific_restore(snapshot.hypervisor_data.clone())?;
306*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
307*bb4ee6a4SAndroid Build Coastguard Worker     }
308*bb4ee6a4SAndroid Build Coastguard Worker }
309*bb4ee6a4SAndroid Build Coastguard Worker 
310*bb4ee6a4SAndroid Build Coastguard Worker /// Aarch64 specific vCPU snapshot.
311*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, Default, Serialize, Deserialize)]
312*bb4ee6a4SAndroid Build Coastguard Worker pub struct VcpuSnapshot {
313*bb4ee6a4SAndroid Build Coastguard Worker     pub vcpu_id: usize,
314*bb4ee6a4SAndroid Build Coastguard Worker     pub sp: u64,
315*bb4ee6a4SAndroid Build Coastguard Worker     pub pc: u64,
316*bb4ee6a4SAndroid Build Coastguard Worker     pub pstate: u64,
317*bb4ee6a4SAndroid Build Coastguard Worker     pub x: [u64; 31],
318*bb4ee6a4SAndroid Build Coastguard Worker     pub v: [u128; 32],
319*bb4ee6a4SAndroid Build Coastguard Worker     pub sys: BTreeMap<AArch64SysRegId, u64>,
320*bb4ee6a4SAndroid Build Coastguard Worker     pub cache_arch_info: BTreeMap<u8, u64>,
321*bb4ee6a4SAndroid Build Coastguard Worker     pub hypervisor_data: serde_json::Value,
322*bb4ee6a4SAndroid Build Coastguard Worker }
323*bb4ee6a4SAndroid Build Coastguard Worker 
324*bb4ee6a4SAndroid Build Coastguard Worker impl_downcast!(VcpuAArch64);
325*bb4ee6a4SAndroid Build Coastguard Worker 
326*bb4ee6a4SAndroid Build Coastguard Worker /// Initial register state for AArch64 VCPUs.
327*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Default)]
328*bb4ee6a4SAndroid Build Coastguard Worker pub struct VcpuInitAArch64 {
329*bb4ee6a4SAndroid Build Coastguard Worker     /// Initial register state as a map of register name to value pairs. Registers that do not have
330*bb4ee6a4SAndroid Build Coastguard Worker     /// a value specified in this map will retain the original value provided by the hypervisor.
331*bb4ee6a4SAndroid Build Coastguard Worker     pub regs: BTreeMap<VcpuRegAArch64, u64>,
332*bb4ee6a4SAndroid Build Coastguard Worker }
333*bb4ee6a4SAndroid Build Coastguard Worker 
334*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq, Eq)]
335*bb4ee6a4SAndroid Build Coastguard Worker pub struct CpuConfigAArch64 {}
336*bb4ee6a4SAndroid Build Coastguard Worker 
337*bb4ee6a4SAndroid Build Coastguard Worker // Convenience constructors for IrqRoutes
338*bb4ee6a4SAndroid Build Coastguard Worker impl IrqRoute {
gic_irq_route(irq_num: u32) -> IrqRoute339*bb4ee6a4SAndroid Build Coastguard Worker     pub fn gic_irq_route(irq_num: u32) -> IrqRoute {
340*bb4ee6a4SAndroid Build Coastguard Worker         IrqRoute {
341*bb4ee6a4SAndroid Build Coastguard Worker             gsi: irq_num,
342*bb4ee6a4SAndroid Build Coastguard Worker             source: IrqSource::Irqchip {
343*bb4ee6a4SAndroid Build Coastguard Worker                 chip: IrqSourceChip::Gic,
344*bb4ee6a4SAndroid Build Coastguard Worker                 pin: irq_num,
345*bb4ee6a4SAndroid Build Coastguard Worker             },
346*bb4ee6a4SAndroid Build Coastguard Worker         }
347*bb4ee6a4SAndroid Build Coastguard Worker     }
348*bb4ee6a4SAndroid Build Coastguard Worker }
349*bb4ee6a4SAndroid Build Coastguard Worker 
350*bb4ee6a4SAndroid Build Coastguard Worker /// A feature that can be enabled on a VCPU with `VcpuAArch64::init`.
351*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug, PartialEq, Eq)]
352*bb4ee6a4SAndroid Build Coastguard Worker pub enum VcpuFeature {
353*bb4ee6a4SAndroid Build Coastguard Worker     /// Emulate PSCI v0.2 (or a future revision backward compatible with v0.2) for the VCPU.
354*bb4ee6a4SAndroid Build Coastguard Worker     PsciV0_2,
355*bb4ee6a4SAndroid Build Coastguard Worker     /// Emulate Performance Monitor Unit v3 for the VCPU.
356*bb4ee6a4SAndroid Build Coastguard Worker     PmuV3,
357*bb4ee6a4SAndroid Build Coastguard Worker     /// Starts the VCPU in a power-off state.
358*bb4ee6a4SAndroid Build Coastguard Worker     PowerOff,
359*bb4ee6a4SAndroid Build Coastguard Worker     /// Scalable Vector Extension support
360*bb4ee6a4SAndroid Build Coastguard Worker     Sve,
361*bb4ee6a4SAndroid Build Coastguard Worker }
362*bb4ee6a4SAndroid Build Coastguard Worker 
363*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
364*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
365*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
366*bb4ee6a4SAndroid Build Coastguard Worker 
367*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
sysreg_new()368*bb4ee6a4SAndroid Build Coastguard Worker     fn sysreg_new() {
369*bb4ee6a4SAndroid Build Coastguard Worker         let sysreg = AArch64SysRegId::new(1, 2, 3, 4, 5).unwrap();
370*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.op0(), 1);
371*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.op1(), 2);
372*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.crn(), 3);
373*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.crm(), 4);
374*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.op2(), 5);
375*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.encoded(), 0x51A5);
376*bb4ee6a4SAndroid Build Coastguard Worker     }
377*bb4ee6a4SAndroid Build Coastguard Worker 
378*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
sysreg_new_max()379*bb4ee6a4SAndroid Build Coastguard Worker     fn sysreg_new_max() {
380*bb4ee6a4SAndroid Build Coastguard Worker         let sysreg = AArch64SysRegId::new(0b11, 0b111, 0b1111, 0b1111, 0b111).unwrap();
381*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.op0(), 3);
382*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.op1(), 7);
383*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.crn(), 15);
384*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.crm(), 15);
385*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.op2(), 7);
386*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(sysreg.encoded(), 0xFFFF);
387*bb4ee6a4SAndroid Build Coastguard Worker     }
388*bb4ee6a4SAndroid Build Coastguard Worker 
389*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
sysreg_new_out_of_range()390*bb4ee6a4SAndroid Build Coastguard Worker     fn sysreg_new_out_of_range() {
391*bb4ee6a4SAndroid Build Coastguard Worker         AArch64SysRegId::new(4, 0, 0, 0, 0).expect_err("invalid Op0");
392*bb4ee6a4SAndroid Build Coastguard Worker         AArch64SysRegId::new(0, 8, 0, 0, 0).expect_err("invalid Op1");
393*bb4ee6a4SAndroid Build Coastguard Worker         AArch64SysRegId::new(0, 0, 16, 0, 0).expect_err("invalid CRn");
394*bb4ee6a4SAndroid Build Coastguard Worker         AArch64SysRegId::new(0, 0, 0, 16, 0).expect_err("invalid CRm");
395*bb4ee6a4SAndroid Build Coastguard Worker         AArch64SysRegId::new(0, 0, 0, 0, 8).expect_err("invalid Op2");
396*bb4ee6a4SAndroid Build Coastguard Worker     }
397*bb4ee6a4SAndroid Build Coastguard Worker 
398*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
sysreg_encoding_mpidr_el1()399*bb4ee6a4SAndroid Build Coastguard Worker     fn sysreg_encoding_mpidr_el1() {
400*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::MPIDR_EL1.op0(), 3);
401*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::MPIDR_EL1.op1(), 0);
402*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::MPIDR_EL1.crn(), 0);
403*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::MPIDR_EL1.crm(), 0);
404*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::MPIDR_EL1.op2(), 5);
405*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::MPIDR_EL1.encoded(), 0xC005);
406*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
407*bb4ee6a4SAndroid Build Coastguard Worker             AArch64SysRegId::MPIDR_EL1,
408*bb4ee6a4SAndroid Build Coastguard Worker             AArch64SysRegId::new(3, 0, 0, 0, 5).unwrap()
409*bb4ee6a4SAndroid Build Coastguard Worker         );
410*bb4ee6a4SAndroid Build Coastguard Worker     }
411*bb4ee6a4SAndroid Build Coastguard Worker 
412*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
sysreg_encoding_cntvct_el0()413*bb4ee6a4SAndroid Build Coastguard Worker     fn sysreg_encoding_cntvct_el0() {
414*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTVCT_EL0.op0(), 3);
415*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTVCT_EL0.op1(), 3);
416*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTVCT_EL0.crn(), 14);
417*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTVCT_EL0.crm(), 0);
418*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTVCT_EL0.op2(), 2);
419*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTVCT_EL0.encoded(), 0xDF02);
420*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
421*bb4ee6a4SAndroid Build Coastguard Worker             AArch64SysRegId::CNTVCT_EL0,
422*bb4ee6a4SAndroid Build Coastguard Worker             AArch64SysRegId::new(3, 3, 14, 0, 2).unwrap()
423*bb4ee6a4SAndroid Build Coastguard Worker         );
424*bb4ee6a4SAndroid Build Coastguard Worker     }
425*bb4ee6a4SAndroid Build Coastguard Worker 
426*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
sysreg_encoding_cntv_cval_el0()427*bb4ee6a4SAndroid Build Coastguard Worker     fn sysreg_encoding_cntv_cval_el0() {
428*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTV_CVAL_EL0.op0(), 3);
429*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTV_CVAL_EL0.op1(), 3);
430*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTV_CVAL_EL0.crn(), 14);
431*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTV_CVAL_EL0.crm(), 3);
432*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTV_CVAL_EL0.op2(), 2);
433*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(AArch64SysRegId::CNTV_CVAL_EL0.encoded(), 0xDF1A);
434*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
435*bb4ee6a4SAndroid Build Coastguard Worker             AArch64SysRegId::CNTV_CVAL_EL0,
436*bb4ee6a4SAndroid Build Coastguard Worker             AArch64SysRegId::new(3, 3, 14, 3, 2).unwrap()
437*bb4ee6a4SAndroid Build Coastguard Worker         );
438*bb4ee6a4SAndroid Build Coastguard Worker     }
439*bb4ee6a4SAndroid Build Coastguard Worker 
440*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
sysreg_debug()441*bb4ee6a4SAndroid Build Coastguard Worker     fn sysreg_debug() {
442*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
443*bb4ee6a4SAndroid Build Coastguard Worker             format!("{:?}", AArch64SysRegId::MPIDR_EL1),
444*bb4ee6a4SAndroid Build Coastguard Worker             "AArch64SysRegId { Op0: 3, Op1: 0, CRn: 0, CRm: 0, Op2: 5 }"
445*bb4ee6a4SAndroid Build Coastguard Worker         );
446*bb4ee6a4SAndroid Build Coastguard Worker     }
447*bb4ee6a4SAndroid Build Coastguard Worker }
448