Skip to content

Commit 69b8c2c

Browse files
andr3wyroypat
authored andcommitted
Utilized option instead of vector to store irq lines
Each MMIO device in Firecracker only utilizes at most one irq line, so capture this property at the type level. Signed-off-by: Andrew Yao <[email protected]> Signed-off-by: Patrick Roy <[email protected]>
1 parent 4488f10 commit 69b8c2c

File tree

1 file changed

+41
-47
lines changed

1 file changed

+41
-47
lines changed

src/vmm/src/device_manager/mmio.rs

Lines changed: 41 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
use std::collections::HashMap;
99
use std::fmt::Debug;
10+
use std::num::NonZeroU32;
1011
use std::sync::{Arc, Mutex};
1112

1213
#[cfg(target_arch = "x86_64")]
@@ -76,8 +77,8 @@ pub struct MMIODeviceInfo {
7677
pub addr: u64,
7778
/// Mmio addr range length.
7879
pub len: u64,
79-
/// Used Irq line(s) for the device.
80-
pub irqs: Vec<u32>,
80+
/// Used Irq line for the device.
81+
pub irq: Option<NonZeroU32>, // NOTE: guaranteed to be a value not 0, 0 is not allowed
8182
}
8283

8384
#[cfg(target_arch = "x86_64")]
@@ -142,15 +143,20 @@ impl MMIODeviceManager {
142143
resource_allocator: &mut ResourceAllocator,
143144
irq_count: u32,
144145
) -> Result<MMIODeviceInfo, MmioError> {
145-
let irqs = resource_allocator.allocate_gsi(irq_count)?;
146+
let irq = match resource_allocator.allocate_gsi(irq_count)?[..] {
147+
[] => None,
148+
[irq] => NonZeroU32::new(irq),
149+
_ => return Err(MmioError::InvalidIrqConfig),
150+
};
151+
146152
let device_info = MMIODeviceInfo {
147153
addr: resource_allocator.allocate_mmio_memory(
148154
MMIO_LEN,
149155
MMIO_LEN,
150156
AllocPolicy::FirstMatch,
151157
)?,
152158
len: MMIO_LEN,
153-
irqs,
159+
irq,
154160
};
155161
Ok(device_info)
156162
}
@@ -179,9 +185,9 @@ impl MMIODeviceManager {
179185
) -> Result<(), MmioError> {
180186
// Our virtio devices are currently hardcoded to use a single IRQ.
181187
// Validate that requirement.
182-
if device_info.irqs.len() != 1 {
188+
let Some(irq) = device_info.irq else {
183189
return Err(MmioError::InvalidIrqConfig);
184-
}
190+
};
185191
let identifier;
186192
{
187193
let locked_device = mmio_device.locked_device();
@@ -193,11 +199,8 @@ impl MMIODeviceManager {
193199
vm.register_ioevent(queue_evt, &io_addr, u32::try_from(i).unwrap())
194200
.map_err(MmioError::RegisterIoEvent)?;
195201
}
196-
vm.register_irqfd(
197-
&locked_device.interrupt_trigger().irq_evt,
198-
device_info.irqs[0],
199-
)
200-
.map_err(MmioError::RegisterIrqFd)?;
202+
vm.register_irqfd(&locked_device.interrupt_trigger().irq_evt, irq.get())
203+
.map_err(MmioError::RegisterIrqFd)?;
201204
}
202205

203206
self.register_mmio_device(
@@ -222,7 +225,7 @@ impl MMIODeviceManager {
222225
.add_virtio_mmio_device(
223226
device_info.len,
224227
GuestAddress(device_info.addr),
225-
device_info.irqs[0],
228+
device_info.irq.unwrap().get(),
226229
None,
227230
)
228231
.map_err(MmioError::Cmdline)
@@ -249,7 +252,7 @@ impl MMIODeviceManager {
249252
device_info.len,
250253
// We are sure that `irqs` has at least one element; allocate_mmio_resources makes
251254
// sure of it.
252-
device_info.irqs[0],
255+
device_info.irq.unwrap().get(),
253256
);
254257
}
255258
Ok(device_info)
@@ -281,7 +284,7 @@ impl MMIODeviceManager {
281284
.unwrap()
282285
.serial
283286
.interrupt_evt(),
284-
device_info.irqs[0],
287+
device_info.irq.unwrap().get(),
285288
)
286289
.map_err(MmioError::RegisterIrqFd)?;
287290

@@ -507,7 +510,7 @@ impl DeviceInfoForFDT for MMIODeviceInfo {
507510
self.addr
508511
}
509512
fn irq(&self) -> u32 {
510-
self.irqs[0]
513+
self.irq.unwrap().into()
511514
}
512515
fn length(&self) -> u64 {
513516
self.len
@@ -555,11 +558,10 @@ mod tests {
555558
#[cfg(target_arch = "x86_64")]
556559
/// Gets the number of interrupts used by the devices registered.
557560
pub fn used_irqs_count(&self) -> usize {
558-
let mut irq_number = 0;
559561
self.get_device_info()
560562
.iter()
561-
.for_each(|(_, device_info)| irq_number += device_info.irqs.len());
562-
irq_number
563+
.filter(|(_, device_info)| device_info.irq.is_some())
564+
.count()
563565
}
564566
}
565567

@@ -762,7 +764,10 @@ mod tests {
762764
);
763765
assert_eq!(
764766
crate::arch::IRQ_BASE,
765-
device_manager.id_to_dev_info[&(DeviceType::Virtio(type_id), id)].irqs[0]
767+
device_manager.id_to_dev_info[&(DeviceType::Virtio(type_id), id)]
768+
.irq
769+
.unwrap()
770+
.get()
766771
);
767772

768773
let id = "bar";
@@ -799,50 +804,39 @@ mod tests {
799804
}
800805

801806
#[test]
802-
fn test_slot_irq_allocation() {
807+
fn test_no_irq_allocation() {
803808
let mut device_manager = MMIODeviceManager::new();
804809
let mut resource_allocator = ResourceAllocator::new().unwrap();
810+
805811
let device_info = device_manager
806812
.allocate_mmio_resources(&mut resource_allocator, 0)
807813
.unwrap();
808-
assert_eq!(device_info.irqs.len(), 0);
814+
assert!(device_info.irq.is_none());
815+
}
816+
817+
#[test]
818+
fn test_irq_allocation() {
819+
let mut device_manager = MMIODeviceManager::new();
820+
let mut resource_allocator = ResourceAllocator::new().unwrap();
821+
809822
let device_info = device_manager
810823
.allocate_mmio_resources(&mut resource_allocator, 1)
811824
.unwrap();
812-
assert_eq!(device_info.irqs[0], crate::arch::IRQ_BASE);
813-
assert_eq!(
814-
format!(
815-
"{}",
816-
device_manager
817-
.allocate_mmio_resources(
818-
&mut resource_allocator,
819-
crate::arch::IRQ_MAX - crate::arch::IRQ_BASE + 1
820-
)
821-
.unwrap_err()
822-
),
823-
"Failed to allocate requested resource: The requested resource is not available."
824-
.to_string()
825-
);
825+
assert_eq!(device_info.irq.unwrap().get(), crate::arch::IRQ_BASE);
826+
}
826827

827-
let device_info = device_manager
828-
.allocate_mmio_resources(
829-
&mut resource_allocator,
830-
crate::arch::IRQ_MAX - crate::arch::IRQ_BASE - 1,
831-
)
832-
.unwrap();
833-
assert_eq!(device_info.irqs[16], crate::arch::IRQ_BASE + 17);
828+
#[test]
829+
fn test_allocation_failure() {
830+
let mut device_manager = MMIODeviceManager::new();
831+
let mut resource_allocator = ResourceAllocator::new().unwrap();
834832
assert_eq!(
835833
format!(
836834
"{}",
837835
device_manager
838836
.allocate_mmio_resources(&mut resource_allocator, 2)
839837
.unwrap_err()
840838
),
841-
"Failed to allocate requested resource: The requested resource is not available."
842-
.to_string()
839+
"Invalid MMIO IRQ configuration.".to_string()
843840
);
844-
device_manager
845-
.allocate_mmio_resources(&mut resource_allocator, 0)
846-
.unwrap();
847841
}
848842
}

0 commit comments

Comments
 (0)