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 // We have u32 constants from bindings that are passed into archiitecture-dependent functions
6*bb4ee6a4SAndroid Build Coastguard Worker // taking u32/64 parameters. So on 32 bit platforms we may have needless casts.
7*bb4ee6a4SAndroid Build Coastguard Worker #![allow(clippy::useless_conversion)]
8*bb4ee6a4SAndroid Build Coastguard Worker
9*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryFrom;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::offset_of;
12*bb4ee6a4SAndroid Build Coastguard Worker
13*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::errno_result;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_mut_ref;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_ref;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_val;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::Error;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
22*bb4ee6a4SAndroid Build Coastguard Worker use cros_fdt::Fdt;
23*bb4ee6a4SAndroid Build Coastguard Worker use data_model::vec_with_array_field;
24*bb4ee6a4SAndroid Build Coastguard Worker use kvm_sys::*;
25*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL;
26*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOMEM;
27*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOTSUP;
28*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENXIO;
29*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
30*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
31*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
32*bb4ee6a4SAndroid Build Coastguard Worker
33*bb4ee6a4SAndroid Build Coastguard Worker use super::Config;
34*bb4ee6a4SAndroid Build Coastguard Worker use super::Kvm;
35*bb4ee6a4SAndroid Build Coastguard Worker use super::KvmCap;
36*bb4ee6a4SAndroid Build Coastguard Worker use super::KvmVcpu;
37*bb4ee6a4SAndroid Build Coastguard Worker use super::KvmVm;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::AArch64SysRegId;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::ClockState;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceKind;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::Hypervisor;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqSourceChip;
43*bb4ee6a4SAndroid Build Coastguard Worker use crate::ProtectionType;
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::PsciVersion;
45*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuAArch64;
46*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuExit;
47*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuFeature;
48*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuRegAArch64;
49*bb4ee6a4SAndroid Build Coastguard Worker use crate::VmAArch64;
50*bb4ee6a4SAndroid Build Coastguard Worker use crate::VmCap;
51*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_MAX_REG_COUNT;
52*bb4ee6a4SAndroid Build Coastguard Worker use crate::PSCI_0_2;
53*bb4ee6a4SAndroid Build Coastguard Worker
54*bb4ee6a4SAndroid Build Coastguard Worker impl Kvm {
55*bb4ee6a4SAndroid Build Coastguard Worker // Compute the machine type, which should be the IPA range for the VM
56*bb4ee6a4SAndroid Build Coastguard Worker // Ideally, this would take a description of the memory map and return
57*bb4ee6a4SAndroid Build Coastguard Worker // the closest machine type for this VM. Here, we just return the maximum
58*bb4ee6a4SAndroid Build Coastguard Worker // the kernel support.
get_vm_type(&self, protection_type: ProtectionType) -> Result<u32>59*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_vm_type(&self, protection_type: ProtectionType) -> Result<u32> {
60*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
61*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know self is a real kvm fd
62*bb4ee6a4SAndroid Build Coastguard Worker let ipa_size = match unsafe {
63*bb4ee6a4SAndroid Build Coastguard Worker ioctl_with_val(self, KVM_CHECK_EXTENSION, KVM_CAP_ARM_VM_IPA_SIZE.into())
64*bb4ee6a4SAndroid Build Coastguard Worker } {
65*bb4ee6a4SAndroid Build Coastguard Worker // Not supported? Use 0 as the machine type, which implies 40bit IPA
66*bb4ee6a4SAndroid Build Coastguard Worker ret if ret < 0 => 0,
67*bb4ee6a4SAndroid Build Coastguard Worker ipa => ipa as u32,
68*bb4ee6a4SAndroid Build Coastguard Worker };
69*bb4ee6a4SAndroid Build Coastguard Worker let protection_flag = if protection_type.isolates_memory() {
70*bb4ee6a4SAndroid Build Coastguard Worker KVM_VM_TYPE_ARM_PROTECTED
71*bb4ee6a4SAndroid Build Coastguard Worker } else {
72*bb4ee6a4SAndroid Build Coastguard Worker 0
73*bb4ee6a4SAndroid Build Coastguard Worker };
74*bb4ee6a4SAndroid Build Coastguard Worker // Use the lower 8 bits representing the IPA space as the machine type
75*bb4ee6a4SAndroid Build Coastguard Worker Ok((ipa_size & KVM_VM_TYPE_ARM_IPA_SIZE_MASK) | protection_flag)
76*bb4ee6a4SAndroid Build Coastguard Worker }
77*bb4ee6a4SAndroid Build Coastguard Worker
78*bb4ee6a4SAndroid Build Coastguard Worker /// Get the size of guest physical addresses (IPA) in bits.
get_guest_phys_addr_bits(&self) -> u879*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_guest_phys_addr_bits(&self) -> u8 {
80*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
81*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know self is a real kvm fd
82*bb4ee6a4SAndroid Build Coastguard Worker match unsafe { ioctl_with_val(self, KVM_CHECK_EXTENSION, KVM_CAP_ARM_VM_IPA_SIZE.into()) } {
83*bb4ee6a4SAndroid Build Coastguard Worker // Default physical address size is 40 bits if the extension is not supported.
84*bb4ee6a4SAndroid Build Coastguard Worker ret if ret <= 0 => 40,
85*bb4ee6a4SAndroid Build Coastguard Worker ipa => ipa as u8,
86*bb4ee6a4SAndroid Build Coastguard Worker }
87*bb4ee6a4SAndroid Build Coastguard Worker }
88*bb4ee6a4SAndroid Build Coastguard Worker }
89*bb4ee6a4SAndroid Build Coastguard Worker
90*bb4ee6a4SAndroid Build Coastguard Worker impl KvmVm {
91*bb4ee6a4SAndroid Build Coastguard Worker /// Does platform specific initialization for the KvmVm.
init_arch(&self, cfg: &Config) -> Result<()>92*bb4ee6a4SAndroid Build Coastguard Worker pub fn init_arch(&self, cfg: &Config) -> Result<()> {
93*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "aarch64")]
94*bb4ee6a4SAndroid Build Coastguard Worker if cfg.mte {
95*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
96*bb4ee6a4SAndroid Build Coastguard Worker // Safe because it does not take pointer arguments.
97*bb4ee6a4SAndroid Build Coastguard Worker unsafe { self.enable_raw_capability(KvmCap::ArmMte, 0, &[0, 0, 0, 0])? }
98*bb4ee6a4SAndroid Build Coastguard Worker }
99*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(target_arch = "aarch64"))]
100*bb4ee6a4SAndroid Build Coastguard Worker {
101*bb4ee6a4SAndroid Build Coastguard Worker // Suppress warning.
102*bb4ee6a4SAndroid Build Coastguard Worker let _ = cfg;
103*bb4ee6a4SAndroid Build Coastguard Worker }
104*bb4ee6a4SAndroid Build Coastguard Worker
105*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
106*bb4ee6a4SAndroid Build Coastguard Worker }
107*bb4ee6a4SAndroid Build Coastguard Worker
108*bb4ee6a4SAndroid Build Coastguard Worker /// Whether running under pKVM.
is_pkvm(&self) -> bool109*bb4ee6a4SAndroid Build Coastguard Worker pub fn is_pkvm(&self) -> bool {
110*bb4ee6a4SAndroid Build Coastguard Worker self.get_protected_vm_info().is_ok()
111*bb4ee6a4SAndroid Build Coastguard Worker }
112*bb4ee6a4SAndroid Build Coastguard Worker
113*bb4ee6a4SAndroid Build Coastguard Worker /// Checks if a particular `VmCap` is available, or returns None if arch-independent
114*bb4ee6a4SAndroid Build Coastguard Worker /// Vm.check_capability() should handle the check.
check_capability_arch(&self, _c: VmCap) -> Option<bool>115*bb4ee6a4SAndroid Build Coastguard Worker pub fn check_capability_arch(&self, _c: VmCap) -> Option<bool> {
116*bb4ee6a4SAndroid Build Coastguard Worker None
117*bb4ee6a4SAndroid Build Coastguard Worker }
118*bb4ee6a4SAndroid Build Coastguard Worker
119*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the params to pass to KVM_CREATE_DEVICE for a `kind` device on this arch, or None to
120*bb4ee6a4SAndroid Build Coastguard Worker /// let the arch-independent `KvmVm::create_device` handle it.
get_device_params_arch(&self, kind: DeviceKind) -> Option<kvm_create_device>121*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_device_params_arch(&self, kind: DeviceKind) -> Option<kvm_create_device> {
122*bb4ee6a4SAndroid Build Coastguard Worker match kind {
123*bb4ee6a4SAndroid Build Coastguard Worker DeviceKind::ArmVgicV2 => Some(kvm_create_device {
124*bb4ee6a4SAndroid Build Coastguard Worker type_: kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2,
125*bb4ee6a4SAndroid Build Coastguard Worker fd: 0,
126*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
127*bb4ee6a4SAndroid Build Coastguard Worker }),
128*bb4ee6a4SAndroid Build Coastguard Worker DeviceKind::ArmVgicV3 => Some(kvm_create_device {
129*bb4ee6a4SAndroid Build Coastguard Worker type_: kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3,
130*bb4ee6a4SAndroid Build Coastguard Worker fd: 0,
131*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
132*bb4ee6a4SAndroid Build Coastguard Worker }),
133*bb4ee6a4SAndroid Build Coastguard Worker _ => None,
134*bb4ee6a4SAndroid Build Coastguard Worker }
135*bb4ee6a4SAndroid Build Coastguard Worker }
136*bb4ee6a4SAndroid Build Coastguard Worker
137*bb4ee6a4SAndroid Build Coastguard Worker /// Arch-specific implementation of `Vm::get_pvclock`. Always returns an error on AArch64.
get_pvclock_arch(&self) -> Result<ClockState>138*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_pvclock_arch(&self) -> Result<ClockState> {
139*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(ENXIO))
140*bb4ee6a4SAndroid Build Coastguard Worker }
141*bb4ee6a4SAndroid Build Coastguard Worker
142*bb4ee6a4SAndroid Build Coastguard Worker /// Arch-specific implementation of `Vm::set_pvclock`. Always returns an error on AArch64.
set_pvclock_arch(&self, _state: &ClockState) -> Result<()>143*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_pvclock_arch(&self, _state: &ClockState) -> Result<()> {
144*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(ENXIO))
145*bb4ee6a4SAndroid Build Coastguard Worker }
146*bb4ee6a4SAndroid Build Coastguard Worker
147*bb4ee6a4SAndroid Build Coastguard Worker /// Get pKVM hypervisor details, e.g. the firmware size.
148*bb4ee6a4SAndroid Build Coastguard Worker ///
149*bb4ee6a4SAndroid Build Coastguard Worker /// Returns `Err` if not running under pKVM.
150*bb4ee6a4SAndroid Build Coastguard Worker ///
151*bb4ee6a4SAndroid Build Coastguard Worker /// Uses `KVM_ENABLE_CAP` internally, but it is only a getter, there should be no side effects
152*bb4ee6a4SAndroid Build Coastguard Worker /// in KVM.
get_protected_vm_info(&self) -> Result<KvmProtectedVmInfo>153*bb4ee6a4SAndroid Build Coastguard Worker fn get_protected_vm_info(&self) -> Result<KvmProtectedVmInfo> {
154*bb4ee6a4SAndroid Build Coastguard Worker let mut info = KvmProtectedVmInfo {
155*bb4ee6a4SAndroid Build Coastguard Worker firmware_size: 0,
156*bb4ee6a4SAndroid Build Coastguard Worker reserved: [0; 7],
157*bb4ee6a4SAndroid Build Coastguard Worker };
158*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
159*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel won't write beyond the end of
160*bb4ee6a4SAndroid Build Coastguard Worker // the struct or keep a pointer to it.
161*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
162*bb4ee6a4SAndroid Build Coastguard Worker self.enable_raw_capability(
163*bb4ee6a4SAndroid Build Coastguard Worker KvmCap::ArmProtectedVm,
164*bb4ee6a4SAndroid Build Coastguard Worker KVM_CAP_ARM_PROTECTED_VM_FLAGS_INFO,
165*bb4ee6a4SAndroid Build Coastguard Worker &[&mut info as *mut KvmProtectedVmInfo as u64, 0, 0, 0],
166*bb4ee6a4SAndroid Build Coastguard Worker )
167*bb4ee6a4SAndroid Build Coastguard Worker }?;
168*bb4ee6a4SAndroid Build Coastguard Worker Ok(info)
169*bb4ee6a4SAndroid Build Coastguard Worker }
170*bb4ee6a4SAndroid Build Coastguard Worker
set_protected_vm_firmware_ipa(&self, fw_addr: GuestAddress) -> Result<()>171*bb4ee6a4SAndroid Build Coastguard Worker fn set_protected_vm_firmware_ipa(&self, fw_addr: GuestAddress) -> Result<()> {
172*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
173*bb4ee6a4SAndroid Build Coastguard Worker // Safe because none of the args are pointers.
174*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
175*bb4ee6a4SAndroid Build Coastguard Worker self.enable_raw_capability(
176*bb4ee6a4SAndroid Build Coastguard Worker KvmCap::ArmProtectedVm,
177*bb4ee6a4SAndroid Build Coastguard Worker KVM_CAP_ARM_PROTECTED_VM_FLAGS_SET_FW_IPA,
178*bb4ee6a4SAndroid Build Coastguard Worker &[fw_addr.0, 0, 0, 0],
179*bb4ee6a4SAndroid Build Coastguard Worker )
180*bb4ee6a4SAndroid Build Coastguard Worker }
181*bb4ee6a4SAndroid Build Coastguard Worker }
182*bb4ee6a4SAndroid Build Coastguard Worker }
183*bb4ee6a4SAndroid Build Coastguard Worker
184*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
185*bb4ee6a4SAndroid Build Coastguard Worker struct KvmProtectedVmInfo {
186*bb4ee6a4SAndroid Build Coastguard Worker firmware_size: u64,
187*bb4ee6a4SAndroid Build Coastguard Worker reserved: [u64; 7],
188*bb4ee6a4SAndroid Build Coastguard Worker }
189*bb4ee6a4SAndroid Build Coastguard Worker
190*bb4ee6a4SAndroid Build Coastguard Worker impl VmAArch64 for KvmVm {
get_hypervisor(&self) -> &dyn Hypervisor191*bb4ee6a4SAndroid Build Coastguard Worker fn get_hypervisor(&self) -> &dyn Hypervisor {
192*bb4ee6a4SAndroid Build Coastguard Worker &self.kvm
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker
load_protected_vm_firmware( &mut self, fw_addr: GuestAddress, fw_max_size: u64, ) -> Result<()>195*bb4ee6a4SAndroid Build Coastguard Worker fn load_protected_vm_firmware(
196*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
197*bb4ee6a4SAndroid Build Coastguard Worker fw_addr: GuestAddress,
198*bb4ee6a4SAndroid Build Coastguard Worker fw_max_size: u64,
199*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
200*bb4ee6a4SAndroid Build Coastguard Worker let info = self.get_protected_vm_info()?;
201*bb4ee6a4SAndroid Build Coastguard Worker if info.firmware_size == 0 {
202*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(EINVAL))
203*bb4ee6a4SAndroid Build Coastguard Worker } else {
204*bb4ee6a4SAndroid Build Coastguard Worker if info.firmware_size > fw_max_size {
205*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(ENOMEM));
206*bb4ee6a4SAndroid Build Coastguard Worker }
207*bb4ee6a4SAndroid Build Coastguard Worker self.set_protected_vm_firmware_ipa(fw_addr)
208*bb4ee6a4SAndroid Build Coastguard Worker }
209*bb4ee6a4SAndroid Build Coastguard Worker }
210*bb4ee6a4SAndroid Build Coastguard Worker
create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>>211*bb4ee6a4SAndroid Build Coastguard Worker fn create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuAArch64>> {
212*bb4ee6a4SAndroid Build Coastguard Worker // create_vcpu is declared separately in VmAArch64 and VmX86, so it can return VcpuAArch64
213*bb4ee6a4SAndroid Build Coastguard Worker // or VcpuX86. But both use the same implementation in KvmVm::create_kvm_vcpu.
214*bb4ee6a4SAndroid Build Coastguard Worker Ok(Box::new(self.create_kvm_vcpu(id)?))
215*bb4ee6a4SAndroid Build Coastguard Worker }
216*bb4ee6a4SAndroid Build Coastguard Worker
create_fdt(&self, _fdt: &mut Fdt, _phandles: &BTreeMap<&str, u32>) -> cros_fdt::Result<()>217*bb4ee6a4SAndroid Build Coastguard Worker fn create_fdt(&self, _fdt: &mut Fdt, _phandles: &BTreeMap<&str, u32>) -> cros_fdt::Result<()> {
218*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
219*bb4ee6a4SAndroid Build Coastguard Worker }
220*bb4ee6a4SAndroid Build Coastguard Worker
init_arch( &self, _payload_entry_address: GuestAddress, _fdt_address: GuestAddress, _fdt_size: usize, ) -> Result<()>221*bb4ee6a4SAndroid Build Coastguard Worker fn init_arch(
222*bb4ee6a4SAndroid Build Coastguard Worker &self,
223*bb4ee6a4SAndroid Build Coastguard Worker _payload_entry_address: GuestAddress,
224*bb4ee6a4SAndroid Build Coastguard Worker _fdt_address: GuestAddress,
225*bb4ee6a4SAndroid Build Coastguard Worker _fdt_size: usize,
226*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
227*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
228*bb4ee6a4SAndroid Build Coastguard Worker }
229*bb4ee6a4SAndroid Build Coastguard Worker
set_counter_offset(&self, offset: u64) -> Result<()>230*bb4ee6a4SAndroid Build Coastguard Worker fn set_counter_offset(&self, offset: u64) -> Result<()> {
231*bb4ee6a4SAndroid Build Coastguard Worker let off = kvm_arm_counter_offset {
232*bb4ee6a4SAndroid Build Coastguard Worker counter_offset: offset,
233*bb4ee6a4SAndroid Build Coastguard Worker reserved: 0,
234*bb4ee6a4SAndroid Build Coastguard Worker };
235*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: self.vm is a valid KVM fd
236*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(&self.vm, KVM_ARM_SET_COUNTER_OFFSET, &off) };
237*bb4ee6a4SAndroid Build Coastguard Worker if ret != 0 {
238*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
239*bb4ee6a4SAndroid Build Coastguard Worker }
240*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
241*bb4ee6a4SAndroid Build Coastguard Worker }
242*bb4ee6a4SAndroid Build Coastguard Worker }
243*bb4ee6a4SAndroid Build Coastguard Worker
244*bb4ee6a4SAndroid Build Coastguard Worker impl KvmVcpu {
245*bb4ee6a4SAndroid Build Coastguard Worker /// Handles a `KVM_EXIT_SYSTEM_EVENT` with event type `KVM_SYSTEM_EVENT_RESET` with the given
246*bb4ee6a4SAndroid Build Coastguard Worker /// event flags and returns the appropriate `VcpuExit` value for the run loop to handle.
247*bb4ee6a4SAndroid Build Coastguard Worker ///
248*bb4ee6a4SAndroid Build Coastguard Worker /// `event_flags` should be one or more of the `KVM_SYSTEM_EVENT_RESET_FLAG_*` values defined by
249*bb4ee6a4SAndroid Build Coastguard Worker /// KVM.
system_event_reset(&self, event_flags: u64) -> Result<VcpuExit>250*bb4ee6a4SAndroid Build Coastguard Worker pub fn system_event_reset(&self, event_flags: u64) -> Result<VcpuExit> {
251*bb4ee6a4SAndroid Build Coastguard Worker if event_flags & u64::from(KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2) != 0 {
252*bb4ee6a4SAndroid Build Coastguard Worker // Read reset_type and cookie from x1 and x2.
253*bb4ee6a4SAndroid Build Coastguard Worker let reset_type = self.get_one_reg(VcpuRegAArch64::X(1))?;
254*bb4ee6a4SAndroid Build Coastguard Worker let cookie = self.get_one_reg(VcpuRegAArch64::X(2))?;
255*bb4ee6a4SAndroid Build Coastguard Worker warn!(
256*bb4ee6a4SAndroid Build Coastguard Worker "PSCI SYSTEM_RESET2 with reset_type={:#x}, cookie={:#x}",
257*bb4ee6a4SAndroid Build Coastguard Worker reset_type, cookie
258*bb4ee6a4SAndroid Build Coastguard Worker );
259*bb4ee6a4SAndroid Build Coastguard Worker }
260*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuExit::SystemEventReset)
261*bb4ee6a4SAndroid Build Coastguard Worker }
262*bb4ee6a4SAndroid Build Coastguard Worker
kvm_reg_id(&self, reg: VcpuRegAArch64) -> Result<KvmVcpuRegister>263*bb4ee6a4SAndroid Build Coastguard Worker fn kvm_reg_id(&self, reg: VcpuRegAArch64) -> Result<KvmVcpuRegister> {
264*bb4ee6a4SAndroid Build Coastguard Worker match reg {
265*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::X(n @ 0..=30) => Ok(KvmVcpuRegister::X(n)),
266*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::Sp => Ok(KvmVcpuRegister::Sp),
267*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::Pc => Ok(KvmVcpuRegister::Pc),
268*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::Pstate => Ok(KvmVcpuRegister::Pstate),
269*bb4ee6a4SAndroid Build Coastguard Worker // Special case for multiplexed KVM registers
270*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::System(AArch64SysRegId::CCSIDR_EL1) => {
271*bb4ee6a4SAndroid Build Coastguard Worker let csselr =
272*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_reg(VcpuRegAArch64::System(AArch64SysRegId::CSSELR_EL1))?;
273*bb4ee6a4SAndroid Build Coastguard Worker Ok(KvmVcpuRegister::Ccsidr(csselr as u8))
274*bb4ee6a4SAndroid Build Coastguard Worker }
275*bb4ee6a4SAndroid Build Coastguard Worker VcpuRegAArch64::System(sysreg) => Ok(KvmVcpuRegister::System(sysreg)),
276*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(Error::new(EINVAL)),
277*bb4ee6a4SAndroid Build Coastguard Worker }
278*bb4ee6a4SAndroid Build Coastguard Worker }
279*bb4ee6a4SAndroid Build Coastguard Worker
set_one_kvm_reg_u32(&self, kvm_reg_id: KvmVcpuRegister, data: u32) -> Result<()>280*bb4ee6a4SAndroid Build Coastguard Worker fn set_one_kvm_reg_u32(&self, kvm_reg_id: KvmVcpuRegister, data: u32) -> Result<()> {
281*bb4ee6a4SAndroid Build Coastguard Worker self.set_one_kvm_reg(kvm_reg_id, data.to_ne_bytes().as_slice())
282*bb4ee6a4SAndroid Build Coastguard Worker }
283*bb4ee6a4SAndroid Build Coastguard Worker
set_one_kvm_reg_u64(&self, kvm_reg_id: KvmVcpuRegister, data: u64) -> Result<()>284*bb4ee6a4SAndroid Build Coastguard Worker fn set_one_kvm_reg_u64(&self, kvm_reg_id: KvmVcpuRegister, data: u64) -> Result<()> {
285*bb4ee6a4SAndroid Build Coastguard Worker self.set_one_kvm_reg(kvm_reg_id, data.to_ne_bytes().as_slice())
286*bb4ee6a4SAndroid Build Coastguard Worker }
287*bb4ee6a4SAndroid Build Coastguard Worker
set_one_kvm_reg_u128(&self, kvm_reg_id: KvmVcpuRegister, data: u128) -> Result<()>288*bb4ee6a4SAndroid Build Coastguard Worker fn set_one_kvm_reg_u128(&self, kvm_reg_id: KvmVcpuRegister, data: u128) -> Result<()> {
289*bb4ee6a4SAndroid Build Coastguard Worker self.set_one_kvm_reg(kvm_reg_id, data.to_ne_bytes().as_slice())
290*bb4ee6a4SAndroid Build Coastguard Worker }
291*bb4ee6a4SAndroid Build Coastguard Worker
set_one_kvm_reg(&self, kvm_reg_id: KvmVcpuRegister, data: &[u8]) -> Result<()>292*bb4ee6a4SAndroid Build Coastguard Worker fn set_one_kvm_reg(&self, kvm_reg_id: KvmVcpuRegister, data: &[u8]) -> Result<()> {
293*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(kvm_reg_id.size(), data.len());
294*bb4ee6a4SAndroid Build Coastguard Worker let id: u64 = kvm_reg_id.into();
295*bb4ee6a4SAndroid Build Coastguard Worker let onereg = kvm_one_reg {
296*bb4ee6a4SAndroid Build Coastguard Worker id,
297*bb4ee6a4SAndroid Build Coastguard Worker addr: (data.as_ptr() as usize)
298*bb4ee6a4SAndroid Build Coastguard Worker .try_into()
299*bb4ee6a4SAndroid Build Coastguard Worker .expect("can't represent usize as u64"),
300*bb4ee6a4SAndroid Build Coastguard Worker };
301*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
302*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
303*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
304*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, KVM_SET_ONE_REG, &onereg) };
305*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
306*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
307*bb4ee6a4SAndroid Build Coastguard Worker } else {
308*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
309*bb4ee6a4SAndroid Build Coastguard Worker }
310*bb4ee6a4SAndroid Build Coastguard Worker }
311*bb4ee6a4SAndroid Build Coastguard Worker
get_one_kvm_reg_u32(&self, kvm_reg_id: KvmVcpuRegister) -> Result<u32>312*bb4ee6a4SAndroid Build Coastguard Worker fn get_one_kvm_reg_u32(&self, kvm_reg_id: KvmVcpuRegister) -> Result<u32> {
313*bb4ee6a4SAndroid Build Coastguard Worker let mut bytes = 0u32.to_ne_bytes();
314*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_kvm_reg(kvm_reg_id, bytes.as_mut_slice())?;
315*bb4ee6a4SAndroid Build Coastguard Worker Ok(u32::from_ne_bytes(bytes))
316*bb4ee6a4SAndroid Build Coastguard Worker }
317*bb4ee6a4SAndroid Build Coastguard Worker
get_one_kvm_reg_u64(&self, kvm_reg_id: KvmVcpuRegister) -> Result<u64>318*bb4ee6a4SAndroid Build Coastguard Worker fn get_one_kvm_reg_u64(&self, kvm_reg_id: KvmVcpuRegister) -> Result<u64> {
319*bb4ee6a4SAndroid Build Coastguard Worker let mut bytes = 0u64.to_ne_bytes();
320*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_kvm_reg(kvm_reg_id, bytes.as_mut_slice())?;
321*bb4ee6a4SAndroid Build Coastguard Worker Ok(u64::from_ne_bytes(bytes))
322*bb4ee6a4SAndroid Build Coastguard Worker }
323*bb4ee6a4SAndroid Build Coastguard Worker
get_one_kvm_reg_u128(&self, kvm_reg_id: KvmVcpuRegister) -> Result<u128>324*bb4ee6a4SAndroid Build Coastguard Worker fn get_one_kvm_reg_u128(&self, kvm_reg_id: KvmVcpuRegister) -> Result<u128> {
325*bb4ee6a4SAndroid Build Coastguard Worker let mut bytes = 0u128.to_ne_bytes();
326*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_kvm_reg(kvm_reg_id, bytes.as_mut_slice())?;
327*bb4ee6a4SAndroid Build Coastguard Worker Ok(u128::from_ne_bytes(bytes))
328*bb4ee6a4SAndroid Build Coastguard Worker }
329*bb4ee6a4SAndroid Build Coastguard Worker
get_one_kvm_reg(&self, kvm_reg_id: KvmVcpuRegister, data: &mut [u8]) -> Result<()>330*bb4ee6a4SAndroid Build Coastguard Worker fn get_one_kvm_reg(&self, kvm_reg_id: KvmVcpuRegister, data: &mut [u8]) -> Result<()> {
331*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(kvm_reg_id.size(), data.len());
332*bb4ee6a4SAndroid Build Coastguard Worker let id: u64 = kvm_reg_id.into();
333*bb4ee6a4SAndroid Build Coastguard Worker let onereg = kvm_one_reg {
334*bb4ee6a4SAndroid Build Coastguard Worker id,
335*bb4ee6a4SAndroid Build Coastguard Worker addr: (data.as_mut_ptr() as usize)
336*bb4ee6a4SAndroid Build Coastguard Worker .try_into()
337*bb4ee6a4SAndroid Build Coastguard Worker .expect("can't represent usize as u64"),
338*bb4ee6a4SAndroid Build Coastguard Worker };
339*bb4ee6a4SAndroid Build Coastguard Worker
340*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
341*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
342*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
343*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, KVM_GET_ONE_REG, &onereg) };
344*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
345*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
346*bb4ee6a4SAndroid Build Coastguard Worker } else {
347*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
348*bb4ee6a4SAndroid Build Coastguard Worker }
349*bb4ee6a4SAndroid Build Coastguard Worker }
350*bb4ee6a4SAndroid Build Coastguard Worker
351*bb4ee6a4SAndroid Build Coastguard Worker #[inline]
handle_vm_exit_arch(&self, _run: &mut kvm_run) -> Option<VcpuExit>352*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn handle_vm_exit_arch(&self, _run: &mut kvm_run) -> Option<VcpuExit> {
353*bb4ee6a4SAndroid Build Coastguard Worker // No aarch64-specific exits (for now)
354*bb4ee6a4SAndroid Build Coastguard Worker None
355*bb4ee6a4SAndroid Build Coastguard Worker }
356*bb4ee6a4SAndroid Build Coastguard Worker
get_reg_list(&self) -> Result<Vec<u64>>357*bb4ee6a4SAndroid Build Coastguard Worker fn get_reg_list(&self) -> Result<Vec<u64>> {
358*bb4ee6a4SAndroid Build Coastguard Worker let mut kvm_reg_list = vec_with_array_field::<kvm_reg_list, u64>(AARCH64_MAX_REG_COUNT);
359*bb4ee6a4SAndroid Build Coastguard Worker kvm_reg_list[0].n = AARCH64_MAX_REG_COUNT as u64;
360*bb4ee6a4SAndroid Build Coastguard Worker let ret =
361*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
362*bb4ee6a4SAndroid Build Coastguard Worker // We trust the kernel not to read/write past the end of kvm_reg_list struct.
363*bb4ee6a4SAndroid Build Coastguard Worker unsafe { ioctl_with_mut_ref(self, KVM_GET_REG_LIST, &mut kvm_reg_list[0]) };
364*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
365*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
366*bb4ee6a4SAndroid Build Coastguard Worker }
367*bb4ee6a4SAndroid Build Coastguard Worker let n = kvm_reg_list[0].n;
368*bb4ee6a4SAndroid Build Coastguard Worker assert!(
369*bb4ee6a4SAndroid Build Coastguard Worker n <= AARCH64_MAX_REG_COUNT as u64,
370*bb4ee6a4SAndroid Build Coastguard Worker "Get reg list returned more registers than possible"
371*bb4ee6a4SAndroid Build Coastguard Worker );
372*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
373*bb4ee6a4SAndroid Build Coastguard Worker // Mapping the unsized array to a slice is unsafe because the length isn't known.
374*bb4ee6a4SAndroid Build Coastguard Worker // Providing the length used to create the struct guarantees the entire slice is valid.
375*bb4ee6a4SAndroid Build Coastguard Worker let reg_list: &[u64] = unsafe { kvm_reg_list[0].reg.as_slice(n as usize) };
376*bb4ee6a4SAndroid Build Coastguard Worker Ok(reg_list.to_vec())
377*bb4ee6a4SAndroid Build Coastguard Worker }
378*bb4ee6a4SAndroid Build Coastguard Worker
get_features_bitmap(&self, features: &[VcpuFeature]) -> Result<u32>379*bb4ee6a4SAndroid Build Coastguard Worker fn get_features_bitmap(&self, features: &[VcpuFeature]) -> Result<u32> {
380*bb4ee6a4SAndroid Build Coastguard Worker let mut all_features = 0;
381*bb4ee6a4SAndroid Build Coastguard Worker let check_extension = |ext: u32| -> bool {
382*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
383*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know self.vm is a real kvm fd
384*bb4ee6a4SAndroid Build Coastguard Worker unsafe { ioctl_with_val(&self.vm, KVM_CHECK_EXTENSION, ext.into()) == 1 }
385*bb4ee6a4SAndroid Build Coastguard Worker };
386*bb4ee6a4SAndroid Build Coastguard Worker
387*bb4ee6a4SAndroid Build Coastguard Worker for f in features {
388*bb4ee6a4SAndroid Build Coastguard Worker let shift = match f {
389*bb4ee6a4SAndroid Build Coastguard Worker VcpuFeature::PsciV0_2 => KVM_ARM_VCPU_PSCI_0_2,
390*bb4ee6a4SAndroid Build Coastguard Worker VcpuFeature::PmuV3 => KVM_ARM_VCPU_PMU_V3,
391*bb4ee6a4SAndroid Build Coastguard Worker VcpuFeature::PowerOff => KVM_ARM_VCPU_POWER_OFF,
392*bb4ee6a4SAndroid Build Coastguard Worker VcpuFeature::Sve => {
393*bb4ee6a4SAndroid Build Coastguard Worker if !check_extension(KVM_CAP_ARM_SVE) {
394*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(ENOTSUP));
395*bb4ee6a4SAndroid Build Coastguard Worker }
396*bb4ee6a4SAndroid Build Coastguard Worker KVM_ARM_VCPU_SVE
397*bb4ee6a4SAndroid Build Coastguard Worker }
398*bb4ee6a4SAndroid Build Coastguard Worker };
399*bb4ee6a4SAndroid Build Coastguard Worker all_features |= 1 << shift;
400*bb4ee6a4SAndroid Build Coastguard Worker }
401*bb4ee6a4SAndroid Build Coastguard Worker
402*bb4ee6a4SAndroid Build Coastguard Worker if check_extension(KVM_CAP_ARM_PTRAUTH_ADDRESS)
403*bb4ee6a4SAndroid Build Coastguard Worker && check_extension(KVM_CAP_ARM_PTRAUTH_GENERIC)
404*bb4ee6a4SAndroid Build Coastguard Worker {
405*bb4ee6a4SAndroid Build Coastguard Worker all_features |= 1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS;
406*bb4ee6a4SAndroid Build Coastguard Worker all_features |= 1 << KVM_ARM_VCPU_PTRAUTH_GENERIC;
407*bb4ee6a4SAndroid Build Coastguard Worker }
408*bb4ee6a4SAndroid Build Coastguard Worker
409*bb4ee6a4SAndroid Build Coastguard Worker Ok(all_features)
410*bb4ee6a4SAndroid Build Coastguard Worker }
411*bb4ee6a4SAndroid Build Coastguard Worker
412*bb4ee6a4SAndroid Build Coastguard Worker /// Finalize VCPU features setup. This does not affect features that do not make use of
413*bb4ee6a4SAndroid Build Coastguard Worker /// finalize.
finalize(&self, features: u32) -> Result<()>414*bb4ee6a4SAndroid Build Coastguard Worker fn finalize(&self, features: u32) -> Result<()> {
415*bb4ee6a4SAndroid Build Coastguard Worker if (features & 1 << KVM_ARM_VCPU_SVE) != 0 {
416*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
417*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we know that our file is a Vcpu fd and we verify the return result.
418*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe {
419*bb4ee6a4SAndroid Build Coastguard Worker ioctl_with_ref(
420*bb4ee6a4SAndroid Build Coastguard Worker self,
421*bb4ee6a4SAndroid Build Coastguard Worker KVM_ARM_VCPU_FINALIZE,
422*bb4ee6a4SAndroid Build Coastguard Worker &std::os::raw::c_int::try_from(KVM_ARM_VCPU_SVE)
423*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| Error::new(EINVAL))?,
424*bb4ee6a4SAndroid Build Coastguard Worker )
425*bb4ee6a4SAndroid Build Coastguard Worker };
426*bb4ee6a4SAndroid Build Coastguard Worker if ret != 0 {
427*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
428*bb4ee6a4SAndroid Build Coastguard Worker }
429*bb4ee6a4SAndroid Build Coastguard Worker }
430*bb4ee6a4SAndroid Build Coastguard Worker
431*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
432*bb4ee6a4SAndroid Build Coastguard Worker }
433*bb4ee6a4SAndroid Build Coastguard Worker }
434*bb4ee6a4SAndroid Build Coastguard Worker
435*bb4ee6a4SAndroid Build Coastguard Worker /// KVM registers as used by the `GET_ONE_REG`/`SET_ONE_REG` ioctl API
436*bb4ee6a4SAndroid Build Coastguard Worker ///
437*bb4ee6a4SAndroid Build Coastguard Worker /// These variants represent the registers as exposed by KVM which must be different from
438*bb4ee6a4SAndroid Build Coastguard Worker /// `VcpuRegAArch64` to support registers which don't have an architectural definition such as
439*bb4ee6a4SAndroid Build Coastguard Worker /// pseudo-registers (`Firmware`) and multiplexed registers (`Ccsidr`).
440*bb4ee6a4SAndroid Build Coastguard Worker ///
441*bb4ee6a4SAndroid Build Coastguard Worker /// See https://docs.kernel.org/virt/kvm/api.html for more details.
442*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone, Serialize, Deserialize)]
443*bb4ee6a4SAndroid Build Coastguard Worker pub enum KvmVcpuRegister {
444*bb4ee6a4SAndroid Build Coastguard Worker /// General Purpose Registers X0-X30
445*bb4ee6a4SAndroid Build Coastguard Worker X(u8),
446*bb4ee6a4SAndroid Build Coastguard Worker /// Stack Pointer
447*bb4ee6a4SAndroid Build Coastguard Worker Sp,
448*bb4ee6a4SAndroid Build Coastguard Worker /// Program Counter
449*bb4ee6a4SAndroid Build Coastguard Worker Pc,
450*bb4ee6a4SAndroid Build Coastguard Worker /// Processor State
451*bb4ee6a4SAndroid Build Coastguard Worker Pstate,
452*bb4ee6a4SAndroid Build Coastguard Worker /// FP & SIMD Registers V0-V31
453*bb4ee6a4SAndroid Build Coastguard Worker V(u8),
454*bb4ee6a4SAndroid Build Coastguard Worker /// KVM Firmware Pseudo-Registers
455*bb4ee6a4SAndroid Build Coastguard Worker Firmware(u16),
456*bb4ee6a4SAndroid Build Coastguard Worker /// System Registers
457*bb4ee6a4SAndroid Build Coastguard Worker System(AArch64SysRegId),
458*bb4ee6a4SAndroid Build Coastguard Worker /// CCSIDR_EL1 Demultiplexed by CSSELR_EL1
459*bb4ee6a4SAndroid Build Coastguard Worker Ccsidr(u8),
460*bb4ee6a4SAndroid Build Coastguard Worker }
461*bb4ee6a4SAndroid Build Coastguard Worker
462*bb4ee6a4SAndroid Build Coastguard Worker impl KvmVcpuRegister {
463*bb4ee6a4SAndroid Build Coastguard Worker // Firmware pseudo-registers are part of the ARM KVM interface:
464*bb4ee6a4SAndroid Build Coastguard Worker // https://docs.kernel.org/virt/kvm/arm/hypercalls.html
465*bb4ee6a4SAndroid Build Coastguard Worker pub const PSCI_VERSION: Self = Self::Firmware(0);
466*bb4ee6a4SAndroid Build Coastguard Worker pub const SMCCC_ARCH_WORKAROUND_1: Self = Self::Firmware(1);
467*bb4ee6a4SAndroid Build Coastguard Worker pub const SMCCC_ARCH_WORKAROUND_2: Self = Self::Firmware(2);
468*bb4ee6a4SAndroid Build Coastguard Worker pub const SMCCC_ARCH_WORKAROUND_3: Self = Self::Firmware(3);
469*bb4ee6a4SAndroid Build Coastguard Worker
470*bb4ee6a4SAndroid Build Coastguard Worker /// Size of this register in bytes.
size(&self) -> usize471*bb4ee6a4SAndroid Build Coastguard Worker pub fn size(&self) -> usize {
472*bb4ee6a4SAndroid Build Coastguard Worker let kvm_reg = u64::from(*self);
473*bb4ee6a4SAndroid Build Coastguard Worker let size_field = kvm_reg & KVM_REG_SIZE_MASK;
474*bb4ee6a4SAndroid Build Coastguard Worker const REG_SIZE_U8: u64 = KVM_REG_SIZE_U8 as u64; // cast from bindgen's u32 to u64
475*bb4ee6a4SAndroid Build Coastguard Worker match size_field {
476*bb4ee6a4SAndroid Build Coastguard Worker REG_SIZE_U8 => 1,
477*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_SIZE_U16 => 2,
478*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_SIZE_U32 => 4,
479*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_SIZE_U64 => 8,
480*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_SIZE_U128 => 16,
481*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_SIZE_U256 => 32,
482*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_SIZE_U512 => 64,
483*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_SIZE_U1024 => 128,
484*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_SIZE_U2048 => 256,
485*bb4ee6a4SAndroid Build Coastguard Worker // `From<KvmVcpuRegister> for u64` should always include a valid size.
486*bb4ee6a4SAndroid Build Coastguard Worker _ => panic!("invalid size field {}", size_field),
487*bb4ee6a4SAndroid Build Coastguard Worker }
488*bb4ee6a4SAndroid Build Coastguard Worker }
489*bb4ee6a4SAndroid Build Coastguard Worker }
490*bb4ee6a4SAndroid Build Coastguard Worker
491*bb4ee6a4SAndroid Build Coastguard Worker /// Gives the `u64` register ID expected by the `GET_ONE_REG`/`SET_ONE_REG` ioctl API.
492*bb4ee6a4SAndroid Build Coastguard Worker ///
493*bb4ee6a4SAndroid Build Coastguard Worker /// See the KVM documentation of those ioctls for details about the format of the register ID.
494*bb4ee6a4SAndroid Build Coastguard Worker impl From<KvmVcpuRegister> for u64 {
from(register: KvmVcpuRegister) -> Self495*bb4ee6a4SAndroid Build Coastguard Worker fn from(register: KvmVcpuRegister) -> Self {
496*bb4ee6a4SAndroid Build Coastguard Worker const fn reg(size: u64, kind: u64, fields: u64) -> u64 {
497*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_ARM64 | size | kind | fields
498*bb4ee6a4SAndroid Build Coastguard Worker }
499*bb4ee6a4SAndroid Build Coastguard Worker
500*bb4ee6a4SAndroid Build Coastguard Worker const fn kvm_regs_reg(size: u64, offset: usize) -> u64 {
501*bb4ee6a4SAndroid Build Coastguard Worker let offset = offset / std::mem::size_of::<u32>();
502*bb4ee6a4SAndroid Build Coastguard Worker
503*bb4ee6a4SAndroid Build Coastguard Worker reg(size, KVM_REG_ARM_CORE as u64, offset as u64)
504*bb4ee6a4SAndroid Build Coastguard Worker }
505*bb4ee6a4SAndroid Build Coastguard Worker
506*bb4ee6a4SAndroid Build Coastguard Worker const fn kvm_reg(offset: usize) -> u64 {
507*bb4ee6a4SAndroid Build Coastguard Worker kvm_regs_reg(KVM_REG_SIZE_U64, offset)
508*bb4ee6a4SAndroid Build Coastguard Worker }
509*bb4ee6a4SAndroid Build Coastguard Worker
510*bb4ee6a4SAndroid Build Coastguard Worker fn spsr_reg(spsr_reg: u32) -> u64 {
511*bb4ee6a4SAndroid Build Coastguard Worker let n = std::mem::size_of::<u64>() * (spsr_reg as usize);
512*bb4ee6a4SAndroid Build Coastguard Worker kvm_reg(offset_of!(kvm_regs, spsr) + n)
513*bb4ee6a4SAndroid Build Coastguard Worker }
514*bb4ee6a4SAndroid Build Coastguard Worker
515*bb4ee6a4SAndroid Build Coastguard Worker fn user_pt_reg(offset: usize) -> u64 {
516*bb4ee6a4SAndroid Build Coastguard Worker kvm_regs_reg(KVM_REG_SIZE_U64, offset_of!(kvm_regs, regs) + offset)
517*bb4ee6a4SAndroid Build Coastguard Worker }
518*bb4ee6a4SAndroid Build Coastguard Worker
519*bb4ee6a4SAndroid Build Coastguard Worker fn user_fpsimd_state_reg(size: u64, offset: usize) -> u64 {
520*bb4ee6a4SAndroid Build Coastguard Worker kvm_regs_reg(size, offset_of!(kvm_regs, fp_regs) + offset)
521*bb4ee6a4SAndroid Build Coastguard Worker }
522*bb4ee6a4SAndroid Build Coastguard Worker
523*bb4ee6a4SAndroid Build Coastguard Worker const fn reg_u64(kind: u64, fields: u64) -> u64 {
524*bb4ee6a4SAndroid Build Coastguard Worker reg(KVM_REG_SIZE_U64, kind, fields)
525*bb4ee6a4SAndroid Build Coastguard Worker }
526*bb4ee6a4SAndroid Build Coastguard Worker
527*bb4ee6a4SAndroid Build Coastguard Worker const fn demux_reg(size: u64, index: u64, value: u64) -> u64 {
528*bb4ee6a4SAndroid Build Coastguard Worker let index = (index << KVM_REG_ARM_DEMUX_ID_SHIFT) & (KVM_REG_ARM_DEMUX_ID_MASK as u64);
529*bb4ee6a4SAndroid Build Coastguard Worker let value =
530*bb4ee6a4SAndroid Build Coastguard Worker (value << KVM_REG_ARM_DEMUX_VAL_SHIFT) & (KVM_REG_ARM_DEMUX_VAL_MASK as u64);
531*bb4ee6a4SAndroid Build Coastguard Worker
532*bb4ee6a4SAndroid Build Coastguard Worker reg(size, KVM_REG_ARM_DEMUX as u64, index | value)
533*bb4ee6a4SAndroid Build Coastguard Worker }
534*bb4ee6a4SAndroid Build Coastguard Worker
535*bb4ee6a4SAndroid Build Coastguard Worker match register {
536*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::X(n @ 0..=30) => {
537*bb4ee6a4SAndroid Build Coastguard Worker let n = std::mem::size_of::<u64>() * (n as usize);
538*bb4ee6a4SAndroid Build Coastguard Worker
539*bb4ee6a4SAndroid Build Coastguard Worker user_pt_reg(offset_of!(user_pt_regs, regs) + n)
540*bb4ee6a4SAndroid Build Coastguard Worker }
541*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::X(n) => unreachable!("invalid KvmVcpuRegister Xn index: {n}"),
542*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::Sp => user_pt_reg(offset_of!(user_pt_regs, sp)),
543*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::Pc => user_pt_reg(offset_of!(user_pt_regs, pc)),
544*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::Pstate => user_pt_reg(offset_of!(user_pt_regs, pstate)),
545*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::V(n @ 0..=31) => {
546*bb4ee6a4SAndroid Build Coastguard Worker let n = std::mem::size_of::<u128>() * (n as usize);
547*bb4ee6a4SAndroid Build Coastguard Worker
548*bb4ee6a4SAndroid Build Coastguard Worker user_fpsimd_state_reg(KVM_REG_SIZE_U128, offset_of!(user_fpsimd_state, vregs) + n)
549*bb4ee6a4SAndroid Build Coastguard Worker }
550*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::V(n) => unreachable!("invalid KvmVcpuRegister Vn index: {n}"),
551*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::FPSR) => {
552*bb4ee6a4SAndroid Build Coastguard Worker user_fpsimd_state_reg(KVM_REG_SIZE_U32, offset_of!(user_fpsimd_state, fpsr))
553*bb4ee6a4SAndroid Build Coastguard Worker }
554*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::FPCR) => {
555*bb4ee6a4SAndroid Build Coastguard Worker user_fpsimd_state_reg(KVM_REG_SIZE_U32, offset_of!(user_fpsimd_state, fpcr))
556*bb4ee6a4SAndroid Build Coastguard Worker }
557*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::SPSR_EL1) => spsr_reg(KVM_SPSR_EL1),
558*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::SPSR_abt) => spsr_reg(KVM_SPSR_ABT),
559*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::SPSR_und) => spsr_reg(KVM_SPSR_UND),
560*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::SPSR_irq) => spsr_reg(KVM_SPSR_IRQ),
561*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::SPSR_fiq) => spsr_reg(KVM_SPSR_FIQ),
562*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::SP_EL1) => {
563*bb4ee6a4SAndroid Build Coastguard Worker kvm_reg(offset_of!(kvm_regs, sp_el1))
564*bb4ee6a4SAndroid Build Coastguard Worker }
565*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::ELR_EL1) => {
566*bb4ee6a4SAndroid Build Coastguard Worker kvm_reg(offset_of!(kvm_regs, elr_el1))
567*bb4ee6a4SAndroid Build Coastguard Worker }
568*bb4ee6a4SAndroid Build Coastguard Worker // The KVM API accidentally swapped CNTV_CVAL_EL0 and CNTVCT_EL0.
569*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::CNTV_CVAL_EL0) => reg_u64(
570*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_ARM64_SYSREG.into(),
571*bb4ee6a4SAndroid Build Coastguard Worker AArch64SysRegId::CNTVCT_EL0.encoded().into(),
572*bb4ee6a4SAndroid Build Coastguard Worker ),
573*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(AArch64SysRegId::CNTVCT_EL0) => reg_u64(
574*bb4ee6a4SAndroid Build Coastguard Worker KVM_REG_ARM64_SYSREG.into(),
575*bb4ee6a4SAndroid Build Coastguard Worker AArch64SysRegId::CNTV_CVAL_EL0.encoded().into(),
576*bb4ee6a4SAndroid Build Coastguard Worker ),
577*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::System(sysreg) => {
578*bb4ee6a4SAndroid Build Coastguard Worker reg_u64(KVM_REG_ARM64_SYSREG.into(), sysreg.encoded().into())
579*bb4ee6a4SAndroid Build Coastguard Worker }
580*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::Firmware(n) => reg_u64(KVM_REG_ARM_FW.into(), n.into()),
581*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::Ccsidr(n) => demux_reg(KVM_REG_SIZE_U32, 0, n.into()),
582*bb4ee6a4SAndroid Build Coastguard Worker }
583*bb4ee6a4SAndroid Build Coastguard Worker }
584*bb4ee6a4SAndroid Build Coastguard Worker }
585*bb4ee6a4SAndroid Build Coastguard Worker
586*bb4ee6a4SAndroid Build Coastguard Worker impl VcpuAArch64 for KvmVcpu {
init(&self, features: &[VcpuFeature]) -> Result<()>587*bb4ee6a4SAndroid Build Coastguard Worker fn init(&self, features: &[VcpuFeature]) -> Result<()> {
588*bb4ee6a4SAndroid Build Coastguard Worker let mut kvi = kvm_vcpu_init {
589*bb4ee6a4SAndroid Build Coastguard Worker target: KVM_ARM_TARGET_GENERIC_V8,
590*bb4ee6a4SAndroid Build Coastguard Worker features: [0; 7],
591*bb4ee6a4SAndroid Build Coastguard Worker };
592*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
593*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will write exactly the size
594*bb4ee6a4SAndroid Build Coastguard Worker // of the struct.
595*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_mut_ref(&self.vm, KVM_ARM_PREFERRED_TARGET, &mut kvi) };
596*bb4ee6a4SAndroid Build Coastguard Worker if ret != 0 {
597*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
598*bb4ee6a4SAndroid Build Coastguard Worker }
599*bb4ee6a4SAndroid Build Coastguard Worker
600*bb4ee6a4SAndroid Build Coastguard Worker kvi.features[0] = self.get_features_bitmap(features)?;
601*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
602*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
603*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
604*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, KVM_ARM_VCPU_INIT, &kvi) };
605*bb4ee6a4SAndroid Build Coastguard Worker if ret != 0 {
606*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
607*bb4ee6a4SAndroid Build Coastguard Worker }
608*bb4ee6a4SAndroid Build Coastguard Worker
609*bb4ee6a4SAndroid Build Coastguard Worker self.finalize(kvi.features[0])?;
610*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
611*bb4ee6a4SAndroid Build Coastguard Worker }
612*bb4ee6a4SAndroid Build Coastguard Worker
init_pmu(&self, irq: u64) -> Result<()>613*bb4ee6a4SAndroid Build Coastguard Worker fn init_pmu(&self, irq: u64) -> Result<()> {
614*bb4ee6a4SAndroid Build Coastguard Worker let irq_addr = &irq as *const u64;
615*bb4ee6a4SAndroid Build Coastguard Worker
616*bb4ee6a4SAndroid Build Coastguard Worker // The in-kernel PMU virtualization is initialized by setting the irq
617*bb4ee6a4SAndroid Build Coastguard Worker // with KVM_ARM_VCPU_PMU_V3_IRQ and then by KVM_ARM_VCPU_PMU_V3_INIT.
618*bb4ee6a4SAndroid Build Coastguard Worker
619*bb4ee6a4SAndroid Build Coastguard Worker let irq_attr = kvm_device_attr {
620*bb4ee6a4SAndroid Build Coastguard Worker group: KVM_ARM_VCPU_PMU_V3_CTRL,
621*bb4ee6a4SAndroid Build Coastguard Worker attr: KVM_ARM_VCPU_PMU_V3_IRQ as u64,
622*bb4ee6a4SAndroid Build Coastguard Worker addr: irq_addr as u64,
623*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
624*bb4ee6a4SAndroid Build Coastguard Worker };
625*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
626*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
627*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
628*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, kvm_sys::KVM_HAS_DEVICE_ATTR, &irq_attr) };
629*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
630*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
631*bb4ee6a4SAndroid Build Coastguard Worker }
632*bb4ee6a4SAndroid Build Coastguard Worker
633*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
634*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
635*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
636*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, kvm_sys::KVM_SET_DEVICE_ATTR, &irq_attr) };
637*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
638*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
639*bb4ee6a4SAndroid Build Coastguard Worker }
640*bb4ee6a4SAndroid Build Coastguard Worker
641*bb4ee6a4SAndroid Build Coastguard Worker let init_attr = kvm_device_attr {
642*bb4ee6a4SAndroid Build Coastguard Worker group: KVM_ARM_VCPU_PMU_V3_CTRL,
643*bb4ee6a4SAndroid Build Coastguard Worker attr: KVM_ARM_VCPU_PMU_V3_INIT as u64,
644*bb4ee6a4SAndroid Build Coastguard Worker addr: 0,
645*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
646*bb4ee6a4SAndroid Build Coastguard Worker };
647*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
648*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
649*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
650*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, kvm_sys::KVM_SET_DEVICE_ATTR, &init_attr) };
651*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
652*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
653*bb4ee6a4SAndroid Build Coastguard Worker }
654*bb4ee6a4SAndroid Build Coastguard Worker
655*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
656*bb4ee6a4SAndroid Build Coastguard Worker }
657*bb4ee6a4SAndroid Build Coastguard Worker
has_pvtime_support(&self) -> bool658*bb4ee6a4SAndroid Build Coastguard Worker fn has_pvtime_support(&self) -> bool {
659*bb4ee6a4SAndroid Build Coastguard Worker // The in-kernel PV time structure is initialized by setting the base
660*bb4ee6a4SAndroid Build Coastguard Worker // address with KVM_ARM_VCPU_PVTIME_IPA
661*bb4ee6a4SAndroid Build Coastguard Worker let pvtime_attr = kvm_device_attr {
662*bb4ee6a4SAndroid Build Coastguard Worker group: KVM_ARM_VCPU_PVTIME_CTRL,
663*bb4ee6a4SAndroid Build Coastguard Worker attr: KVM_ARM_VCPU_PVTIME_IPA as u64,
664*bb4ee6a4SAndroid Build Coastguard Worker addr: 0,
665*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
666*bb4ee6a4SAndroid Build Coastguard Worker };
667*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
668*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
669*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
670*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, kvm_sys::KVM_HAS_DEVICE_ATTR, &pvtime_attr) };
671*bb4ee6a4SAndroid Build Coastguard Worker ret >= 0
672*bb4ee6a4SAndroid Build Coastguard Worker }
673*bb4ee6a4SAndroid Build Coastguard Worker
init_pvtime(&self, pvtime_ipa: u64) -> Result<()>674*bb4ee6a4SAndroid Build Coastguard Worker fn init_pvtime(&self, pvtime_ipa: u64) -> Result<()> {
675*bb4ee6a4SAndroid Build Coastguard Worker let pvtime_ipa_addr = &pvtime_ipa as *const u64;
676*bb4ee6a4SAndroid Build Coastguard Worker
677*bb4ee6a4SAndroid Build Coastguard Worker // The in-kernel PV time structure is initialized by setting the base
678*bb4ee6a4SAndroid Build Coastguard Worker // address with KVM_ARM_VCPU_PVTIME_IPA
679*bb4ee6a4SAndroid Build Coastguard Worker let pvtime_attr = kvm_device_attr {
680*bb4ee6a4SAndroid Build Coastguard Worker group: KVM_ARM_VCPU_PVTIME_CTRL,
681*bb4ee6a4SAndroid Build Coastguard Worker attr: KVM_ARM_VCPU_PVTIME_IPA as u64,
682*bb4ee6a4SAndroid Build Coastguard Worker addr: pvtime_ipa_addr as u64,
683*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
684*bb4ee6a4SAndroid Build Coastguard Worker };
685*bb4ee6a4SAndroid Build Coastguard Worker
686*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
687*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we allocated the struct and we know the kernel will read exactly the size of
688*bb4ee6a4SAndroid Build Coastguard Worker // the struct.
689*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, kvm_sys::KVM_SET_DEVICE_ATTR, &pvtime_attr) };
690*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
691*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
692*bb4ee6a4SAndroid Build Coastguard Worker }
693*bb4ee6a4SAndroid Build Coastguard Worker
694*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
695*bb4ee6a4SAndroid Build Coastguard Worker }
696*bb4ee6a4SAndroid Build Coastguard Worker
set_one_reg(&self, reg_id: VcpuRegAArch64, data: u64) -> Result<()>697*bb4ee6a4SAndroid Build Coastguard Worker fn set_one_reg(&self, reg_id: VcpuRegAArch64, data: u64) -> Result<()> {
698*bb4ee6a4SAndroid Build Coastguard Worker let kvm_reg = self.kvm_reg_id(reg_id)?;
699*bb4ee6a4SAndroid Build Coastguard Worker match kvm_reg.size() {
700*bb4ee6a4SAndroid Build Coastguard Worker 4 => self.set_one_kvm_reg_u32(kvm_reg, data as u32),
701*bb4ee6a4SAndroid Build Coastguard Worker 8 => self.set_one_kvm_reg_u64(kvm_reg, data),
702*bb4ee6a4SAndroid Build Coastguard Worker size => panic!("bad reg size {size}"),
703*bb4ee6a4SAndroid Build Coastguard Worker }
704*bb4ee6a4SAndroid Build Coastguard Worker }
705*bb4ee6a4SAndroid Build Coastguard Worker
get_one_reg(&self, reg_id: VcpuRegAArch64) -> Result<u64>706*bb4ee6a4SAndroid Build Coastguard Worker fn get_one_reg(&self, reg_id: VcpuRegAArch64) -> Result<u64> {
707*bb4ee6a4SAndroid Build Coastguard Worker let kvm_reg = self.kvm_reg_id(reg_id)?;
708*bb4ee6a4SAndroid Build Coastguard Worker match kvm_reg.size() {
709*bb4ee6a4SAndroid Build Coastguard Worker 4 => self.get_one_kvm_reg_u32(kvm_reg).map(u64::from),
710*bb4ee6a4SAndroid Build Coastguard Worker 8 => self.get_one_kvm_reg_u64(kvm_reg),
711*bb4ee6a4SAndroid Build Coastguard Worker size => panic!("bad reg size {size}"),
712*bb4ee6a4SAndroid Build Coastguard Worker }
713*bb4ee6a4SAndroid Build Coastguard Worker }
714*bb4ee6a4SAndroid Build Coastguard Worker
set_vector_reg(&self, reg_num: u8, data: u128) -> Result<()>715*bb4ee6a4SAndroid Build Coastguard Worker fn set_vector_reg(&self, reg_num: u8, data: u128) -> Result<()> {
716*bb4ee6a4SAndroid Build Coastguard Worker if reg_num > 31 {
717*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(EINVAL));
718*bb4ee6a4SAndroid Build Coastguard Worker }
719*bb4ee6a4SAndroid Build Coastguard Worker self.set_one_kvm_reg_u128(KvmVcpuRegister::V(reg_num), data)
720*bb4ee6a4SAndroid Build Coastguard Worker }
721*bb4ee6a4SAndroid Build Coastguard Worker
get_vector_reg(&self, reg_num: u8) -> Result<u128>722*bb4ee6a4SAndroid Build Coastguard Worker fn get_vector_reg(&self, reg_num: u8) -> Result<u128> {
723*bb4ee6a4SAndroid Build Coastguard Worker if reg_num > 31 {
724*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(EINVAL));
725*bb4ee6a4SAndroid Build Coastguard Worker }
726*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_kvm_reg_u128(KvmVcpuRegister::V(reg_num))
727*bb4ee6a4SAndroid Build Coastguard Worker }
728*bb4ee6a4SAndroid Build Coastguard Worker
get_mpidr(&self) -> Result<u64>729*bb4ee6a4SAndroid Build Coastguard Worker fn get_mpidr(&self) -> Result<u64> {
730*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_reg(VcpuRegAArch64::System(AArch64SysRegId::MPIDR_EL1))
731*bb4ee6a4SAndroid Build Coastguard Worker }
732*bb4ee6a4SAndroid Build Coastguard Worker
get_psci_version(&self) -> Result<PsciVersion>733*bb4ee6a4SAndroid Build Coastguard Worker fn get_psci_version(&self) -> Result<PsciVersion> {
734*bb4ee6a4SAndroid Build Coastguard Worker let version = if let Ok(v) = self.get_one_kvm_reg_u64(KvmVcpuRegister::PSCI_VERSION) {
735*bb4ee6a4SAndroid Build Coastguard Worker let v = u32::try_from(v).map_err(|_| Error::new(EINVAL))?;
736*bb4ee6a4SAndroid Build Coastguard Worker PsciVersion::try_from(v)?
737*bb4ee6a4SAndroid Build Coastguard Worker } else {
738*bb4ee6a4SAndroid Build Coastguard Worker // When `KVM_REG_ARM_PSCI_VERSION` is not supported, we can return PSCI 0.2, as vCPU
739*bb4ee6a4SAndroid Build Coastguard Worker // has been initialized with `KVM_ARM_VCPU_PSCI_0_2` successfully.
740*bb4ee6a4SAndroid Build Coastguard Worker PSCI_0_2
741*bb4ee6a4SAndroid Build Coastguard Worker };
742*bb4ee6a4SAndroid Build Coastguard Worker
743*bb4ee6a4SAndroid Build Coastguard Worker if version < PSCI_0_2 {
744*bb4ee6a4SAndroid Build Coastguard Worker // PSCI v0.1 isn't currently supported for guests
745*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::new(ENOTSUP))
746*bb4ee6a4SAndroid Build Coastguard Worker } else {
747*bb4ee6a4SAndroid Build Coastguard Worker Ok(version)
748*bb4ee6a4SAndroid Build Coastguard Worker }
749*bb4ee6a4SAndroid Build Coastguard Worker }
750*bb4ee6a4SAndroid Build Coastguard Worker
get_max_hw_bps(&self) -> Result<usize>751*bb4ee6a4SAndroid Build Coastguard Worker fn get_max_hw_bps(&self) -> Result<usize> {
752*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
753*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the kernel will only return the result of the ioctl.
754*bb4ee6a4SAndroid Build Coastguard Worker let max_hw_bps = unsafe {
755*bb4ee6a4SAndroid Build Coastguard Worker ioctl_with_val(
756*bb4ee6a4SAndroid Build Coastguard Worker &self.vm,
757*bb4ee6a4SAndroid Build Coastguard Worker KVM_CHECK_EXTENSION,
758*bb4ee6a4SAndroid Build Coastguard Worker KVM_CAP_GUEST_DEBUG_HW_BPS.into(),
759*bb4ee6a4SAndroid Build Coastguard Worker )
760*bb4ee6a4SAndroid Build Coastguard Worker };
761*bb4ee6a4SAndroid Build Coastguard Worker
762*bb4ee6a4SAndroid Build Coastguard Worker if max_hw_bps < 0 {
763*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
764*bb4ee6a4SAndroid Build Coastguard Worker } else {
765*bb4ee6a4SAndroid Build Coastguard Worker Ok(max_hw_bps.try_into().expect("can't represent u64 as usize"))
766*bb4ee6a4SAndroid Build Coastguard Worker }
767*bb4ee6a4SAndroid Build Coastguard Worker }
768*bb4ee6a4SAndroid Build Coastguard Worker
get_system_regs(&self) -> Result<BTreeMap<AArch64SysRegId, u64>>769*bb4ee6a4SAndroid Build Coastguard Worker fn get_system_regs(&self) -> Result<BTreeMap<AArch64SysRegId, u64>> {
770*bb4ee6a4SAndroid Build Coastguard Worker let reg_list = self.get_reg_list()?;
771*bb4ee6a4SAndroid Build Coastguard Worker let cntvct_el0: u16 = AArch64SysRegId::CNTVCT_EL0.encoded();
772*bb4ee6a4SAndroid Build Coastguard Worker let cntv_cval_el0: u16 = AArch64SysRegId::CNTV_CVAL_EL0.encoded();
773*bb4ee6a4SAndroid Build Coastguard Worker let mut sys_regs = BTreeMap::new();
774*bb4ee6a4SAndroid Build Coastguard Worker for reg in reg_list {
775*bb4ee6a4SAndroid Build Coastguard Worker if (reg as u32) & KVM_REG_ARM_COPROC_MASK == KVM_REG_ARM64_SYSREG {
776*bb4ee6a4SAndroid Build Coastguard Worker let r = if reg as u16 == cntvct_el0 {
777*bb4ee6a4SAndroid Build Coastguard Worker AArch64SysRegId::CNTV_CVAL_EL0
778*bb4ee6a4SAndroid Build Coastguard Worker } else if reg as u16 == cntv_cval_el0 {
779*bb4ee6a4SAndroid Build Coastguard Worker AArch64SysRegId::CNTVCT_EL0
780*bb4ee6a4SAndroid Build Coastguard Worker } else {
781*bb4ee6a4SAndroid Build Coastguard Worker AArch64SysRegId::from_encoded((reg & 0xFFFF) as u16)
782*bb4ee6a4SAndroid Build Coastguard Worker };
783*bb4ee6a4SAndroid Build Coastguard Worker sys_regs.insert(r, self.get_one_reg(VcpuRegAArch64::System(r))?);
784*bb4ee6a4SAndroid Build Coastguard Worker // The register representations are tricky. Double check they round trip correctly.
785*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
786*bb4ee6a4SAndroid Build Coastguard Worker Ok(reg),
787*bb4ee6a4SAndroid Build Coastguard Worker self.kvm_reg_id(VcpuRegAArch64::System(r)).map(u64::from),
788*bb4ee6a4SAndroid Build Coastguard Worker );
789*bb4ee6a4SAndroid Build Coastguard Worker }
790*bb4ee6a4SAndroid Build Coastguard Worker }
791*bb4ee6a4SAndroid Build Coastguard Worker Ok(sys_regs)
792*bb4ee6a4SAndroid Build Coastguard Worker }
793*bb4ee6a4SAndroid Build Coastguard Worker
get_cache_info(&self) -> Result<BTreeMap<u8, u64>>794*bb4ee6a4SAndroid Build Coastguard Worker fn get_cache_info(&self) -> Result<BTreeMap<u8, u64>> {
795*bb4ee6a4SAndroid Build Coastguard Worker const KVM_REG_CCSIDR: u64 = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | (KVM_REG_ARM_DEMUX as u64);
796*bb4ee6a4SAndroid Build Coastguard Worker const CCSIDR_INDEX_MASK: u64 = 0xFF;
797*bb4ee6a4SAndroid Build Coastguard Worker let reg_list = self.get_reg_list()?;
798*bb4ee6a4SAndroid Build Coastguard Worker let mut cache_info = BTreeMap::new();
799*bb4ee6a4SAndroid Build Coastguard Worker for reg in reg_list {
800*bb4ee6a4SAndroid Build Coastguard Worker if (reg & !CCSIDR_INDEX_MASK) == KVM_REG_CCSIDR {
801*bb4ee6a4SAndroid Build Coastguard Worker let idx = reg as u8;
802*bb4ee6a4SAndroid Build Coastguard Worker cache_info.insert(
803*bb4ee6a4SAndroid Build Coastguard Worker idx,
804*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_kvm_reg_u32(KvmVcpuRegister::Ccsidr(idx))?
805*bb4ee6a4SAndroid Build Coastguard Worker .into(),
806*bb4ee6a4SAndroid Build Coastguard Worker );
807*bb4ee6a4SAndroid Build Coastguard Worker }
808*bb4ee6a4SAndroid Build Coastguard Worker }
809*bb4ee6a4SAndroid Build Coastguard Worker Ok(cache_info)
810*bb4ee6a4SAndroid Build Coastguard Worker }
811*bb4ee6a4SAndroid Build Coastguard Worker
set_cache_info(&self, cache_info: BTreeMap<u8, u64>) -> Result<()>812*bb4ee6a4SAndroid Build Coastguard Worker fn set_cache_info(&self, cache_info: BTreeMap<u8, u64>) -> Result<()> {
813*bb4ee6a4SAndroid Build Coastguard Worker for (idx, val) in cache_info {
814*bb4ee6a4SAndroid Build Coastguard Worker self.set_one_kvm_reg_u32(
815*bb4ee6a4SAndroid Build Coastguard Worker KvmVcpuRegister::Ccsidr(idx),
816*bb4ee6a4SAndroid Build Coastguard Worker val.try_into()
817*bb4ee6a4SAndroid Build Coastguard Worker .expect("trying to set a u32 register with a u64 value"),
818*bb4ee6a4SAndroid Build Coastguard Worker )?;
819*bb4ee6a4SAndroid Build Coastguard Worker }
820*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
821*bb4ee6a4SAndroid Build Coastguard Worker }
822*bb4ee6a4SAndroid Build Coastguard Worker
hypervisor_specific_snapshot(&self) -> anyhow::Result<serde_json::Value>823*bb4ee6a4SAndroid Build Coastguard Worker fn hypervisor_specific_snapshot(&self) -> anyhow::Result<serde_json::Value> {
824*bb4ee6a4SAndroid Build Coastguard Worker let reg_list = self.get_reg_list()?;
825*bb4ee6a4SAndroid Build Coastguard Worker let mut firmware_regs = BTreeMap::new();
826*bb4ee6a4SAndroid Build Coastguard Worker for reg in reg_list {
827*bb4ee6a4SAndroid Build Coastguard Worker if (reg as u32) & KVM_REG_ARM_COPROC_MASK == KVM_REG_ARM_FW {
828*bb4ee6a4SAndroid Build Coastguard Worker firmware_regs.insert(
829*bb4ee6a4SAndroid Build Coastguard Worker reg as u16,
830*bb4ee6a4SAndroid Build Coastguard Worker self.get_one_kvm_reg_u64(KvmVcpuRegister::Firmware(reg as u16))?,
831*bb4ee6a4SAndroid Build Coastguard Worker );
832*bb4ee6a4SAndroid Build Coastguard Worker }
833*bb4ee6a4SAndroid Build Coastguard Worker }
834*bb4ee6a4SAndroid Build Coastguard Worker
835*bb4ee6a4SAndroid Build Coastguard Worker serde_json::to_value(KvmSnapshot { firmware_regs })
836*bb4ee6a4SAndroid Build Coastguard Worker .context("Failed to serialize KVM specific data")
837*bb4ee6a4SAndroid Build Coastguard Worker }
838*bb4ee6a4SAndroid Build Coastguard Worker
hypervisor_specific_restore(&self, data: serde_json::Value) -> anyhow::Result<()>839*bb4ee6a4SAndroid Build Coastguard Worker fn hypervisor_specific_restore(&self, data: serde_json::Value) -> anyhow::Result<()> {
840*bb4ee6a4SAndroid Build Coastguard Worker let deser: KvmSnapshot =
841*bb4ee6a4SAndroid Build Coastguard Worker serde_json::from_value(data).context("Failed to deserialize KVM specific data")?;
842*bb4ee6a4SAndroid Build Coastguard Worker // TODO: need to set firmware registers before "create_fdt" is called, earlier in the
843*bb4ee6a4SAndroid Build Coastguard Worker // stack.
844*bb4ee6a4SAndroid Build Coastguard Worker for (id, val) in &deser.firmware_regs {
845*bb4ee6a4SAndroid Build Coastguard Worker self.set_one_kvm_reg_u64(KvmVcpuRegister::Firmware(*id), *val)?;
846*bb4ee6a4SAndroid Build Coastguard Worker }
847*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
848*bb4ee6a4SAndroid Build Coastguard Worker }
849*bb4ee6a4SAndroid Build Coastguard Worker
850*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::unusual_byte_groupings)]
set_guest_debug(&self, addrs: &[GuestAddress], enable_singlestep: bool) -> Result<()>851*bb4ee6a4SAndroid Build Coastguard Worker fn set_guest_debug(&self, addrs: &[GuestAddress], enable_singlestep: bool) -> Result<()> {
852*bb4ee6a4SAndroid Build Coastguard Worker let mut dbg = kvm_guest_debug {
853*bb4ee6a4SAndroid Build Coastguard Worker control: KVM_GUESTDBG_ENABLE,
854*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
855*bb4ee6a4SAndroid Build Coastguard Worker };
856*bb4ee6a4SAndroid Build Coastguard Worker
857*bb4ee6a4SAndroid Build Coastguard Worker if enable_singlestep {
858*bb4ee6a4SAndroid Build Coastguard Worker dbg.control |= KVM_GUESTDBG_SINGLESTEP;
859*bb4ee6a4SAndroid Build Coastguard Worker }
860*bb4ee6a4SAndroid Build Coastguard Worker if !addrs.is_empty() {
861*bb4ee6a4SAndroid Build Coastguard Worker dbg.control |= KVM_GUESTDBG_USE_HW;
862*bb4ee6a4SAndroid Build Coastguard Worker }
863*bb4ee6a4SAndroid Build Coastguard Worker
864*bb4ee6a4SAndroid Build Coastguard Worker for (i, guest_addr) in addrs.iter().enumerate() {
865*bb4ee6a4SAndroid Build Coastguard Worker // From the ARMv8 Architecture Reference Manual (DDI0487H.a) D31.3.{2,3}:
866*bb4ee6a4SAndroid Build Coastguard Worker // When DBGBCR<n>_EL1.BT == 0b000x:
867*bb4ee6a4SAndroid Build Coastguard Worker // DBGBVR<n>_EL1, Bits [1:0]: Reserved, RES0
868*bb4ee6a4SAndroid Build Coastguard Worker if guest_addr.0 & 0b11 != 0 {
869*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(EINVAL));
870*bb4ee6a4SAndroid Build Coastguard Worker }
871*bb4ee6a4SAndroid Build Coastguard Worker let sign_ext = 15;
872*bb4ee6a4SAndroid Build Coastguard Worker // DBGBVR<n>_EL1.RESS[14:0], bits [63:49]: Reserved, Sign extended
873*bb4ee6a4SAndroid Build Coastguard Worker dbg.arch.dbg_bvr[i] = (((guest_addr.0 << sign_ext) as i64) >> sign_ext) as u64;
874*bb4ee6a4SAndroid Build Coastguard Worker // DBGBCR<n>_EL1.BT, bits [23:20]: Breakpoint Type
875*bb4ee6a4SAndroid Build Coastguard Worker // 0b0000: Unlinked instruction address match.
876*bb4ee6a4SAndroid Build Coastguard Worker // DBGBVR<n>_EL1 is the address of an instruction.
877*bb4ee6a4SAndroid Build Coastguard Worker // DBGBCR<n>_EL1.BAS, bits [8:5]: Byte address select
878*bb4ee6a4SAndroid Build Coastguard Worker // 0b1111: Use for A64 and A32 instructions
879*bb4ee6a4SAndroid Build Coastguard Worker // DBGBCR<n>_EL1.PMC, bits [2:1]: Privilege mode control
880*bb4ee6a4SAndroid Build Coastguard Worker // 0b11: EL1 & EL0
881*bb4ee6a4SAndroid Build Coastguard Worker // DBGBCR<n>_EL1.E, bit [0]: Enable breakpoint
882*bb4ee6a4SAndroid Build Coastguard Worker // 0b1: Enabled
883*bb4ee6a4SAndroid Build Coastguard Worker dbg.arch.dbg_bcr[i] = 0b1111_11_1;
884*bb4ee6a4SAndroid Build Coastguard Worker }
885*bb4ee6a4SAndroid Build Coastguard Worker
886*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
887*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the kernel won't read past the end of the kvm_guest_debug struct.
888*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { ioctl_with_ref(self, KVM_SET_GUEST_DEBUG, &dbg) };
889*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 {
890*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
891*bb4ee6a4SAndroid Build Coastguard Worker } else {
892*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
893*bb4ee6a4SAndroid Build Coastguard Worker }
894*bb4ee6a4SAndroid Build Coastguard Worker }
895*bb4ee6a4SAndroid Build Coastguard Worker }
896*bb4ee6a4SAndroid Build Coastguard Worker
897*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Serialize, Deserialize)]
898*bb4ee6a4SAndroid Build Coastguard Worker struct KvmSnapshot {
899*bb4ee6a4SAndroid Build Coastguard Worker firmware_regs: BTreeMap<u16, u64>,
900*bb4ee6a4SAndroid Build Coastguard Worker }
901*bb4ee6a4SAndroid Build Coastguard Worker
902*bb4ee6a4SAndroid Build Coastguard Worker // This function translates an IrqSrouceChip to the kvm u32 equivalent. It has a different
903*bb4ee6a4SAndroid Build Coastguard Worker // implementation between x86_64 and aarch64 because the irqchip KVM constants are not defined on
904*bb4ee6a4SAndroid Build Coastguard Worker // all architectures.
chip_to_kvm_chip(chip: IrqSourceChip) -> u32905*bb4ee6a4SAndroid Build Coastguard Worker pub(super) fn chip_to_kvm_chip(chip: IrqSourceChip) -> u32 {
906*bb4ee6a4SAndroid Build Coastguard Worker match chip {
907*bb4ee6a4SAndroid Build Coastguard Worker // ARM does not have a constant for this, but the default routing
908*bb4ee6a4SAndroid Build Coastguard Worker // setup seems to set this to 0
909*bb4ee6a4SAndroid Build Coastguard Worker IrqSourceChip::Gic => 0,
910*bb4ee6a4SAndroid Build Coastguard Worker _ => {
911*bb4ee6a4SAndroid Build Coastguard Worker error!("Invalid IrqChipSource for ARM {:?}", chip);
912*bb4ee6a4SAndroid Build Coastguard Worker 0
913*bb4ee6a4SAndroid Build Coastguard Worker }
914*bb4ee6a4SAndroid Build Coastguard Worker }
915*bb4ee6a4SAndroid Build Coastguard Worker }
916*bb4ee6a4SAndroid Build Coastguard Worker
917*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
918*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
919*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
920*bb4ee6a4SAndroid Build Coastguard Worker
921*bb4ee6a4SAndroid Build Coastguard Worker #[test]
system_timer_register_mixup()922*bb4ee6a4SAndroid Build Coastguard Worker fn system_timer_register_mixup() {
923*bb4ee6a4SAndroid Build Coastguard Worker // Per https://docs.kernel.org/virt/kvm/api.html ARM64 system register encoding docs,
924*bb4ee6a4SAndroid Build Coastguard Worker // KVM_REG_ARM_TIMER_CVAL and KVM_REG_ARM_TIMER_CNT were accidentally defined backwards.
925*bb4ee6a4SAndroid Build Coastguard Worker // Ensure the AArch64SysRegId to KvmVcpuRegister encoding maps these to the expected
926*bb4ee6a4SAndroid Build Coastguard Worker // values.
927*bb4ee6a4SAndroid Build Coastguard Worker
928*bb4ee6a4SAndroid Build Coastguard Worker const KVM_REG_ARM_TIMER_CVAL: u64 = 0x6030_0000_0013_DF02;
929*bb4ee6a4SAndroid Build Coastguard Worker let cntv_cval_el0_kvm = KvmVcpuRegister::System(AArch64SysRegId::CNTV_CVAL_EL0);
930*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(u64::from(cntv_cval_el0_kvm), KVM_REG_ARM_TIMER_CVAL);
931*bb4ee6a4SAndroid Build Coastguard Worker
932*bb4ee6a4SAndroid Build Coastguard Worker const KVM_REG_ARM_TIMER_CNT: u64 = 0x6030_0000_0013_DF1A;
933*bb4ee6a4SAndroid Build Coastguard Worker let cntvct_el0_kvm = KvmVcpuRegister::System(AArch64SysRegId::CNTVCT_EL0);
934*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(u64::from(cntvct_el0_kvm), KVM_REG_ARM_TIMER_CNT);
935*bb4ee6a4SAndroid Build Coastguard Worker }
936*bb4ee6a4SAndroid Build Coastguard Worker }
937