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(®) {
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(®) {
854 self.demux_register(®)?.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(®) {
868 KvmVcpuRegister::try_from(reg)?
869 } else if let Some(r) = self.demux_register(®)? {
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