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 base::Result;
6 use downcast_rs::impl_downcast;
7 use vm_memory::GuestAddress;
8 
9 use crate::{Hypervisor, IrqRoute, IrqSource, IrqSourceChip, Vcpu, Vm};
10 
11 /// Represents a version of Power State Coordination Interface (PSCI).
12 pub struct PsciVersion {
13     pub major: u32,
14     pub minor: u32,
15 }
16 
17 /// A wrapper for using a VM on aarch64 and getting/setting its state.
18 pub trait VmAArch64: Vm {
19     /// Gets the `Hypervisor` that created this VM.
get_hypervisor(&self) -> &dyn Hypervisor20     fn get_hypervisor(&self) -> &dyn Hypervisor;
21 
22     /// Enables protected mode for the VM, creating a memslot for the firmware as needed.
23     /// Only works on VMs that support `VmCap::Protected`.
enable_protected_vm(&mut self, fw_addr: GuestAddress, fw_max_size: u64) -> Result<()>24     fn enable_protected_vm(&mut self, fw_addr: GuestAddress, fw_max_size: u64) -> Result<()>;
25 
26     /// Create a Vcpu with the specified Vcpu ID.
create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>>27     fn create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>>;
28 }
29 
30 /// A wrapper around creating and using a VCPU on aarch64.
31 pub trait VcpuAArch64: Vcpu {
32     /// Does ARM-specific initialization of this VCPU.  Inits the VCPU with the preferred target
33     /// VCPU type and the specified `features`, and resets the value of all registers to defaults.
34     /// All VCPUs should be created before calling this function.
init(&self, features: &[VcpuFeature]) -> Result<()>35     fn init(&self, features: &[VcpuFeature]) -> Result<()>;
36 
37     /// Initializes the ARM Performance Monitor Unit v3 on this VCPU, with overflow interrupt number
38     /// `irq`.
init_pmu(&self, irq: u64) -> Result<()>39     fn init_pmu(&self, irq: u64) -> Result<()>;
40 
41     /// Sets the value of a register on this VCPU.  `reg_id` is the register ID, as specified in the
42     /// KVM API documentation for KVM_SET_ONE_REG.
set_one_reg(&self, reg_id: u64, data: u64) -> Result<()>43     fn set_one_reg(&self, reg_id: u64, data: u64) -> Result<()>;
44 
45     /// Gets the value of a register on this VCPU.  `reg_id` is the register ID, as specified in the
46     /// KVM API documentation for KVM_GET_ONE_REG.
get_one_reg(&self, reg_id: u64) -> Result<u64>47     fn get_one_reg(&self, reg_id: u64) -> Result<u64>;
48 
49     /// Gets the current PSCI version.
get_psci_version(&self) -> Result<PsciVersion>50     fn get_psci_version(&self) -> Result<PsciVersion>;
51 }
52 
53 impl_downcast!(VcpuAArch64);
54 
55 // Convenience constructors for IrqRoutes
56 impl IrqRoute {
gic_irq_route(irq_num: u32) -> IrqRoute57     pub fn gic_irq_route(irq_num: u32) -> IrqRoute {
58         IrqRoute {
59             gsi: irq_num,
60             source: IrqSource::Irqchip {
61                 chip: IrqSourceChip::Gic,
62                 pin: irq_num,
63             },
64         }
65     }
66 }
67 
68 /// A feature that can be enabled on a VCPU with `VcpuAArch64::init`.
69 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
70 pub enum VcpuFeature {
71     /// Emulate PSCI v0.2 (or a future revision backward compatible with v0.2) for the VCPU.
72     PsciV0_2,
73     /// Emulate Performance Monitor Unit v3 for the VCPU.
74     PmuV3,
75     /// Starts the VCPU in a power-off state.
76     PowerOff,
77 }
78