Fixes KVM_CAP_ONE_REG is not supported on x86-64 (#1000)

This commit is contained in:
Putta Khunchalee 2024-09-28 14:53:54 +07:00 committed by GitHub
parent 80dde69731
commit 165fd9d253
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 16 additions and 8 deletions

View File

@ -5,6 +5,7 @@ pub const KVM_CREATE_VM: c_ulong = _IO(KVMIO, 0x01);
pub const KVM_CHECK_EXTENSION: c_ulong = _IO(KVMIO, 0x03);
pub const KVM_GET_VCPU_MMAP_SIZE: c_ulong = _IO(KVMIO, 0x04);
pub const KVM_CREATE_VCPU: c_ulong = _IO(KVMIO, 0x41);
#[cfg(target_arch = "aarch64")]
pub const KVM_GET_ONE_REG: c_ulong = _IOW::<KvmOneReg<()>>(KVMIO, 0xab);
#[cfg(target_arch = "aarch64")]
pub const KVM_ARM_VCPU_INIT: c_ulong = _IOW::<KvmVcpuInit>(KVMIO, 0xae);
@ -14,6 +15,7 @@ pub const KVM_ARM_PREFERRED_TARGET: c_ulong = _IOR::<KvmVcpuInit>(KVMIO, 0xaf);
pub const KVM_API_VERSION: c_int = 12;
pub const KVM_CAP_MAX_VCPUS: c_int = 66;
#[cfg(target_arch = "aarch64")]
pub const KVM_CAP_ONE_REG: c_int = 70;
#[cfg(target_arch = "aarch64")]
pub const KVM_CAP_ARM_VM_IPA_SIZE: c_int = 165;
@ -74,6 +76,7 @@ const fn _IOC(dir: c_ulong, ty: c_ulong, nr: c_ulong, size: c_ulong) -> c_ulong
| (size << _IOC_SIZESHIFT)
}
#[cfg(target_arch = "aarch64")]
#[repr(C)]
pub struct KvmOneReg<'a, T> {
pub id: u64,

View File

@ -1,9 +1,8 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
use self::cpu::KvmCpu;
use self::ffi::{
kvm_set_user_memory_region, KvmOneReg, KVM_API_VERSION, KVM_CAP_MAX_VCPUS, KVM_CAP_ONE_REG,
KVM_CHECK_EXTENSION, KVM_CREATE_VCPU, KVM_CREATE_VM, KVM_GET_API_VERSION, KVM_GET_ONE_REG,
KVM_GET_VCPU_MMAP_SIZE,
kvm_set_user_memory_region, KVM_API_VERSION, KVM_CAP_MAX_VCPUS, KVM_CHECK_EXTENSION,
KVM_CREATE_VCPU, KVM_CREATE_VM, KVM_GET_API_VERSION, KVM_GET_VCPU_MMAP_SIZE,
};
use super::{CpuFeats, Hypervisor};
use crate::vmm::ram::Ram;
@ -48,9 +47,15 @@ pub fn new(cpu: usize, ram: Ram) -> Result<impl Hypervisor, VmmError> {
return Err(VmmError::MaxCpuTooLow);
}
// Check KVM_CAP_ONE_REG. KVM_SET_ONE_REG and KVM_GET_ONE_REG are the only API that support all
// architectures.
if unsafe { ioctl(kvm.as_raw_fd(), KVM_CHECK_EXTENSION, KVM_CAP_ONE_REG) <= 0 } {
// On AArch64 we need KVM_SET_ONE_REG and KVM_GET_ONE_REG.
#[cfg(target_arch = "aarch64")]
if unsafe {
ioctl(
kvm.as_raw_fd(),
KVM_CHECK_EXTENSION,
self::ffi::KVM_CAP_ONE_REG,
) <= 0
} {
return Err(VmmError::NoKvmOneReg);
}
@ -189,7 +194,7 @@ impl Hypervisor for Kvm {
#[cfg(target_arch = "aarch64")]
fn cpu_features(&mut self) -> Result<CpuFeats, Self::CpuErr> {
use self::ffi::ARM64_SYS_REG;
use self::ffi::{KvmOneReg, ARM64_SYS_REG, KVM_GET_ONE_REG};
use crate::vmm::hv::{Mmfr0, Mmfr1, Mmfr2};
use std::arch::asm;

View File

@ -698,7 +698,7 @@ enum VmmError {
#[error("unexpected KVM version")]
KvmVersionMismatched,
#[cfg(target_os = "linux")]
#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
#[error("your OS does not support KVM_CAP_ONE_REG")]
NoKvmOneReg,