Skip to content

Commit 27b2ce2

Browse files
committed
vmm: fall back to GICv2 if GICv3 is not supported
The SoC in some popular boards (namely, the RPi family) doesn't support an architected vGIC, which is required for requesting KVM the instantiation of a GICv3. To relieve the users from having to configure the gic version manually, try first to instantiate a GICv3, and fall back to a GICv2 if it fails. Signed-off-by: Sergio Lopez <[email protected]>
1 parent 6123b74 commit 27b2ce2

File tree

2 files changed

+26
-15
lines changed

2 files changed

+26
-15
lines changed

src/devices/src/legacy/kvmgicv3.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::legacy::gic::GICDevice;
88
use crate::legacy::irqchip::IrqChipT;
99
use crate::Error as DeviceError;
1010

11-
use kvm_ioctls::{DeviceFd, VmFd};
11+
use kvm_ioctls::{DeviceFd, Error, VmFd};
1212
use utils::eventfd::EventFd;
1313

1414
const KVM_VGIC_V3_BASE_SIZE: u64 = 0x0001_0000;
@@ -27,7 +27,7 @@ pub struct KvmGicV3 {
2727
}
2828

2929
impl KvmGicV3 {
30-
pub fn new(vm: &VmFd, vcpu_count: u64) -> Self {
30+
pub fn new(vm: &VmFd, vcpu_count: u64) -> Result<Self, Error> {
3131
let dist_size = KVM_VGIC_V3_BASE_SIZE;
3232
let dist_addr = arch::MMIO_MEM_START - dist_size;
3333
let redist_size = 2 * dist_size;
@@ -39,23 +39,23 @@ impl KvmGicV3 {
3939
fd: 0,
4040
flags: 0,
4141
};
42-
let device_fd = vm.create_device(&mut gic_device).unwrap();
42+
let device_fd = vm.create_device(&mut gic_device)?;
4343

4444
let attr = kvm_bindings::kvm_device_attr {
4545
group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
4646
attr: u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_DIST),
4747
addr: &dist_addr as *const u64 as u64,
4848
flags: 0,
4949
};
50-
device_fd.set_device_attr(&attr).unwrap();
50+
device_fd.set_device_attr(&attr)?;
5151

5252
let attr = kvm_bindings::kvm_device_attr {
5353
group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
5454
attr: u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_REDIST),
5555
addr: &redists_addr as *const u64 as u64,
5656
flags: 0,
5757
};
58-
device_fd.set_device_attr(&attr).unwrap();
58+
device_fd.set_device_attr(&attr)?;
5959

6060
let nr_irqs: u32 = arch::aarch64::layout::IRQ_MAX - arch::aarch64::layout::IRQ_BASE + 1;
6161
let nr_irqs_ptr = &nr_irqs as *const u32;
@@ -65,21 +65,21 @@ impl KvmGicV3 {
6565
addr: nr_irqs_ptr as u64,
6666
flags: 0,
6767
};
68-
device_fd.set_device_attr(&attr).unwrap();
68+
device_fd.set_device_attr(&attr)?;
6969

7070
let attr = kvm_bindings::kvm_device_attr {
7171
group: kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
7272
attr: u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT),
7373
addr: 0,
7474
flags: 0,
7575
};
76-
device_fd.set_device_attr(&attr).unwrap();
76+
device_fd.set_device_attr(&attr)?;
7777

78-
Self {
78+
Ok(Self {
7979
_device_fd: device_fd,
8080
properties: [dist_addr, dist_size, redists_addr, redists_size],
8181
vcpu_count,
82-
}
82+
})
8383
}
8484
}
8585

src/vmm/src/builder.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ use crate::vmm_config::external_kernel::{ExternalKernel, KernelFormat};
3030
use crate::vmm_config::net::NetBuilder;
3131
#[cfg(all(target_os = "linux", target_arch = "riscv64"))]
3232
use devices::legacy::KvmAia;
33-
#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
34-
use devices::legacy::KvmGicV3;
3533
#[cfg(target_arch = "x86_64")]
3634
use devices::legacy::KvmIoapic;
3735
use devices::legacy::Serial;
@@ -42,6 +40,8 @@ use devices::legacy::{GicV3, HvfGicV3};
4240
#[cfg(target_arch = "x86_64")]
4341
use devices::legacy::{IoApic, IrqChipT};
4442
use devices::legacy::{IrqChip, IrqChipDevice};
43+
#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
44+
use devices::legacy::{KvmGicV2, KvmGicV3};
4545
use devices::virtio::{port_io, MmioTransport, PortDescription, VirtioDevice, Vsock};
4646

4747
#[cfg(feature = "tee")]
@@ -837,10 +837,21 @@ pub fn build_microvm(
837837
)
838838
.map_err(StartMicrovmError::Internal)?;
839839

840-
intc = Arc::new(Mutex::new(IrqChipDevice::new(Box::new(KvmGicV3::new(
841-
vm.fd(),
842-
vm_resources.vm_config().vcpu_count.unwrap() as u64,
843-
)))));
840+
intc = {
841+
// The SoC in some popular boards (namely, the RPi family) doesn't support an
842+
// architected vGIC, which is required for requesting KVM the instantiation of a
843+
// GICv3. To relieve the users from having to configure the gic version manually,
844+
// try first to instantiate a GICv3, and fall back to a GICv2 if it fails.
845+
let vcpu_count = vm_resources.vm_config().vcpu_count.unwrap() as u64;
846+
let gic = match KvmGicV3::new(vm.fd(), vcpu_count) {
847+
Ok(gicv3) => IrqChipDevice::new(Box::new(gicv3)),
848+
Err(_) => {
849+
warn!("KVM GICv3 creation failed, falling back to KVM GICv2");
850+
IrqChipDevice::new(Box::new(KvmGicV2::new(vm.fd(), vcpu_count)))
851+
}
852+
};
853+
Arc::new(Mutex::new(gic))
854+
};
844855

845856
attach_legacy_devices(
846857
&vm,

0 commit comments

Comments
 (0)