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