• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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