1 // Copyright 2020 The Chromium OS Authors. All rights reserved. 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::convert::TryFrom; 6 7 use base::{Error, Result}; 8 use downcast_rs::impl_downcast; 9 use libc::EINVAL; 10 use vm_memory::GuestAddress; 11 12 use crate::{Hypervisor, IrqRoute, IrqSource, IrqSourceChip, Vcpu, Vm}; 13 14 /// Represents a version of Power State Coordination Interface (PSCI). 15 #[derive(Eq, Ord, PartialEq, PartialOrd)] 16 pub struct PsciVersion { 17 pub major: u16, 18 pub minor: u16, 19 } 20 21 impl PsciVersion { new(major: u16, minor: u16) -> Result<Self>22 pub fn new(major: u16, minor: u16) -> Result<Self> { 23 if (major as i16) < 0 { 24 Err(Error::new(EINVAL)) 25 } else { 26 Ok(Self { major, minor }) 27 } 28 } 29 } 30 31 impl TryFrom<u32> for PsciVersion { 32 type Error = base::Error; 33 try_from(item: u32) -> Result<Self>34 fn try_from(item: u32) -> Result<Self> { 35 Self::new((item >> 16) as u16, item as u16) 36 } 37 } 38 39 pub const PSCI_0_2: PsciVersion = PsciVersion { major: 0, minor: 2 }; 40 pub const PSCI_1_0: PsciVersion = PsciVersion { major: 1, minor: 0 }; 41 42 /// A wrapper for using a VM on aarch64 and getting/setting its state. 43 pub trait VmAArch64: Vm { 44 /// Gets the `Hypervisor` that created this VM. get_hypervisor(&self) -> &dyn Hypervisor45 fn get_hypervisor(&self) -> &dyn Hypervisor; 46 47 /// Load pVM firmware for the VM, creating a memslot for it as needed. 48 /// 49 /// 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<()>50 fn load_protected_vm_firmware(&mut self, fw_addr: GuestAddress, fw_max_size: u64) 51 -> Result<()>; 52 53 /// Create a Vcpu with the specified Vcpu ID. create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>>54 fn create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>>; 55 } 56 57 /// A wrapper around creating and using a VCPU on aarch64. 58 pub trait VcpuAArch64: Vcpu { 59 /// Does ARM-specific initialization of this VCPU. Inits the VCPU with the preferred target 60 /// VCPU type and the specified `features`, and resets the value of all registers to defaults. 61 /// All VCPUs should be created before calling this function. init(&self, features: &[VcpuFeature]) -> Result<()>62 fn init(&self, features: &[VcpuFeature]) -> Result<()>; 63 64 /// Initializes the ARM Performance Monitor Unit v3 on this VCPU, with overflow interrupt number 65 /// `irq`. init_pmu(&self, irq: u64) -> Result<()>66 fn init_pmu(&self, irq: u64) -> Result<()>; 67 68 /// Checks if ARM ParaVirtualized Time is supported on this VCPU has_pvtime_support(&self) -> bool69 fn has_pvtime_support(&self) -> bool; 70 71 /// Initializes the ARM ParaVirtualized Time on this VCPU, with base address of the stolen time 72 /// structure as `pvtime_ipa`. init_pvtime(&self, pvtime_ipa: u64) -> Result<()>73 fn init_pvtime(&self, pvtime_ipa: u64) -> Result<()>; 74 75 /// Sets the value of a register on this VCPU. `reg_id` is the register ID, as specified in the 76 /// KVM API documentation for KVM_SET_ONE_REG. set_one_reg(&self, reg_id: u64, data: u64) -> Result<()>77 fn set_one_reg(&self, reg_id: u64, data: u64) -> Result<()>; 78 79 /// Gets the value of a register on this VCPU. `reg_id` is the register ID, as specified in the 80 /// KVM API documentation for KVM_GET_ONE_REG. get_one_reg(&self, reg_id: u64) -> Result<u64>81 fn get_one_reg(&self, reg_id: u64) -> Result<u64>; 82 83 /// Gets the current PSCI version. get_psci_version(&self) -> Result<PsciVersion>84 fn get_psci_version(&self) -> Result<PsciVersion>; 85 } 86 87 impl_downcast!(VcpuAArch64); 88 89 // Convenience constructors for IrqRoutes 90 impl IrqRoute { gic_irq_route(irq_num: u32) -> IrqRoute91 pub fn gic_irq_route(irq_num: u32) -> IrqRoute { 92 IrqRoute { 93 gsi: irq_num, 94 source: IrqSource::Irqchip { 95 chip: IrqSourceChip::Gic, 96 pin: irq_num, 97 }, 98 } 99 } 100 } 101 102 /// A feature that can be enabled on a VCPU with `VcpuAArch64::init`. 103 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 104 pub enum VcpuFeature { 105 /// Emulate PSCI v0.2 (or a future revision backward compatible with v0.2) for the VCPU. 106 PsciV0_2, 107 /// Emulate Performance Monitor Unit v3 for the VCPU. 108 PmuV3, 109 /// Starts the VCPU in a power-off state. 110 PowerOff, 111 } 112