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