diff --git a/src/devices/src/legacy/kvmapi.rs b/src/devices/src/legacy/kvmapi.rs new file mode 100644 index 000000000..11289c048 --- /dev/null +++ b/src/devices/src/legacy/kvmapi.rs @@ -0,0 +1,43 @@ +use kvm_ioctls::{Error, VmFd}; + +#[cfg(all(target_os = "linux", target_arch = "riscv64"))] +use crate::legacy::KvmAia; +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] +use crate::legacy::KvmIoapic; +#[cfg(all(target_os = "linux", target_arch = "aarch64"))] +use crate::legacy::{KvmGicV2, KvmGicV3}; + +pub enum KvmApi { + #[cfg(all(target_os = "linux", target_arch = "x86_64"))] + KvmIoapic(KvmIoapic), + #[cfg(all(target_os = "linux", target_arch = "aarch64"))] + KvmGicV2(KvmGicV2), + #[cfg(all(target_os = "linux", target_arch = "aarch64"))] + KvmGicV3(KvmGicV3), + #[cfg(all(target_os = "linux", target_arch = "riscv64"))] + KvmAia(KvmAia), +} + +impl KvmApi { + #[cfg(all(target_os = "linux", target_arch = "riscv64"))] + pub fn new(vm: &VmFd, vcpu_count: u64) -> Result { + let kvmaia = KvmAia::new(vm, vcpu_count as _).unwrap(); + Ok(Self::KvmAia(kvmaia)) + } + + #[cfg(all(target_os = "linux", target_arch = "x86_64"))] + pub fn new(vm: &VmFd, _vcpu_count: u64) -> Result { + let kvmioapic = KvmIoapic::new(vm).unwrap(); + Ok(Self::KvmIoapic(kvmioapic)) + } + + #[cfg(all(target_os = "linux", target_arch = "aarch64"))] + pub fn new(vm: &VmFd, vcpu_count: u64) -> Result { + if let Ok(v3) = KvmGicV3::new(vm, vcpu_count.into()) { + Ok(Self::KvmGicV3(v3)) + } else { + log::warn!("GICv3 creation failed, falling back to GICv2"); + Ok(Self::KvmGicV2(KvmGicV2::new(vm, vcpu_count.into()))) + } + } +} diff --git a/src/devices/src/legacy/mod.rs b/src/devices/src/legacy/mod.rs index 1662f9b7d..71c520739 100644 --- a/src/devices/src/legacy/mod.rs +++ b/src/devices/src/legacy/mod.rs @@ -17,6 +17,7 @@ mod ioapic; mod irqchip; #[cfg(all(target_os = "linux", target_arch = "riscv64"))] mod kvmaia; +mod kvmapi; #[cfg(all(target_os = "linux", target_arch = "aarch64"))] mod kvmgicv2; #[cfg(all(target_os = "linux", target_arch = "aarch64"))] @@ -57,6 +58,7 @@ pub use self::irqchip::test_utils::DummyIrqChip; pub use self::irqchip::{IrqChip, IrqChipDevice, IrqChipT}; #[cfg(all(target_os = "linux", target_arch = "riscv64"))] pub use self::kvmaia::KvmAia; +pub use self::kvmapi::KvmApi; #[cfg(all(target_os = "linux", target_arch = "aarch64"))] pub use self::kvmgicv2::KvmGicV2; #[cfg(all(target_os = "linux", target_arch = "aarch64"))] diff --git a/src/vmm/src/device_manager/kvm/mmio.rs b/src/vmm/src/device_manager/kvm/mmio.rs index 56d1ae05b..77c0a5712 100644 --- a/src/vmm/src/device_manager/kvm/mmio.rs +++ b/src/vmm/src/device_manager/kvm/mmio.rs @@ -315,11 +315,10 @@ mod tests { use super::*; use arch; use devices::legacy::DummyIrqChip; + use devices::legacy::KvmApi; use devices::virtio::InterruptTransport; - use devices::{ - legacy::KvmIoapic, - virtio::{ActivateResult, Queue, VirtioDevice}, - }; + + use devices::virtio::{ActivateResult, Queue, VirtioDevice}; use std::sync::Arc; use utils::errno; use utils::eventfd::EventFd; @@ -333,7 +332,7 @@ mod tests { vm: &VmFd, guest_mem: GuestMemoryMmap, device: Arc>, - cmdline: &mut kernel_cmdline::Cmdline, + _cmdline: &mut kernel_cmdline::Cmdline, type_id: u32, device_id: &str, ) -> Result { @@ -343,7 +342,7 @@ mod tests { let (mmio_base, _irq) = self.register_mmio_device(vm, mmio_device, type_id, device_id.to_string())?; #[cfg(target_arch = "x86_64")] - self.add_device_to_cmdline(cmdline, mmio_base, _irq)?; + self.add_device_to_cmdline(_cmdline, mmio_base, _irq)?; Ok(mmio_base) } } @@ -435,7 +434,7 @@ mod tests { let vm = builder::setup_vm(&guest_mem, false).unwrap(); let mut device_manager = MMIODeviceManager::new(&mut 0xd000_0000, (arch::IRQ_BASE, arch::IRQ_MAX)); - let _kvmioapic = KvmIoapic::new(vm.fd()).unwrap(); + let _kvmapi = KvmApi::new(vm.fd(), vcpu_count.into()).unwrap(); let mut cmdline = kernel_cmdline::Cmdline::new(4096); let dummy = Arc::new(Mutex::new(DummyDevice::new())); @@ -455,7 +454,7 @@ mod tests { let vm = builder::setup_vm(&guest_mem, false).unwrap(); let mut device_manager = MMIODeviceManager::new(&mut 0xd000_0000, (arch::IRQ_BASE, arch::IRQ_MAX)); - let _kvmioapic = KvmIoapic::new(vm.fd()).unwrap(); + let _kvmapi = KvmApi::new(vm.fd(), vcpu_count.into()).unwrap(); let mut cmdline = kernel_cmdline::Cmdline::new(4096); @@ -552,7 +551,7 @@ mod tests { let start_addr2 = GuestAddress(0x1000); let guest_mem = GuestMemoryMmap::from_ranges(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]).unwrap(); - let vcpu_count = 1; + let _vcpu_count = 1; let vm = builder::setup_vm(&guest_mem, false).unwrap(); let mut device_manager = MMIODeviceManager::new(&mut 0xd000_0000, (arch::IRQ_BASE, arch::IRQ_MAX)); diff --git a/src/vmm/src/linux/vstate.rs b/src/vmm/src/linux/vstate.rs index 0948c669b..0e4f955be 100644 --- a/src/vmm/src/linux/vstate.rs +++ b/src/vmm/src/linux/vstate.rs @@ -1773,7 +1773,8 @@ mod tests { use super::*; use devices; - use devices::legacy::KvmIoapic; + #[cfg(all(target_os = "linux", target_arch = "x86_64"))] + use devices::legacy::KvmApi; use utils::signal::validate_signal_num; @@ -1795,7 +1796,9 @@ mod tests { let kvm = KvmContext::new().unwrap(); let gm = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), mem_size)]).unwrap(); let mut vm = Vm::new(kvm.fd()).expect("Cannot create new vm"); - let _kvmioapic = KvmIoapic::new(&vm.fd()).unwrap(); + let vcpu_count = 1; + #[cfg(all(target_os = "linux", target_arch = "x86_64"))] + let _kvmapi = KvmApi::new(vm.fd(), vcpu_count.into()).unwrap(); assert!(vm.memory_init(&gm, kvm.max_memslots()).is_ok()); let exit_evt = EventFd::new(utils::eventfd::EFD_NONBLOCK).unwrap(); @@ -1804,7 +1807,7 @@ mod tests { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { vcpu = Vcpu::new_x86_64( - 1, + vcpu_count, vm.fd(), vm.supported_cpuid().clone(), vm.supported_msrs().clone(), @@ -1815,7 +1818,7 @@ mod tests { } #[cfg(target_arch = "aarch64")] { - vcpu = Vcpu::new_aarch64(1, vm.fd(), exit_evt).unwrap(); + vcpu = Vcpu::new_aarch64(vcpu_count, vm.fd(), exit_evt).unwrap(); } (vm, vcpu, gm)