Skip to content

Commit 65e0e84

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 9104425 commit 65e0e84

File tree

1 file changed

+41
-47
lines changed

1 file changed

+41
-47
lines changed

src/vmm/src/device_manager/mmio.rs

+41-47
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

@@ -517,7 +520,7 @@ impl DeviceInfoForFDT for MMIODeviceInfo {
517520
self.addr
518521
}
519522
fn irq(&self) -> u32 {
520-
self.irqs[0]
523+
self.irq.unwrap().into()
521524
}
522525
fn length(&self) -> u64 {
523526
self.len
@@ -565,11 +568,10 @@ mod tests {
565568
#[cfg(target_arch = "x86_64")]
566569
/// Gets the number of interrupts used by the devices registered.
567570
pub fn used_irqs_count(&self) -> usize {
568-
let mut irq_number = 0;
569571
self.get_device_info()
570572
.iter()
571-
.for_each(|(_, device_info)| irq_number += device_info.irqs.len());
572-
irq_number
573+
.filter(|(_, device_info)| device_info.irq.is_some())
574+
.count()
573575
}
574576
}
575577

@@ -772,7 +774,10 @@ mod tests {
772774
);
773775
assert_eq!(
774776
crate::arch::IRQ_BASE,
775-
device_manager.id_to_dev_info[&(DeviceType::Virtio(type_id), id)].irqs[0]
777+
device_manager.id_to_dev_info[&(DeviceType::Virtio(type_id), id)]
778+
.irq
779+
.unwrap()
780+
.get()
776781
);
777782

778783
let id = "bar";
@@ -809,50 +814,39 @@ mod tests {
809814
}
810815

811816
#[test]
812-
fn test_slot_irq_allocation() {
817+
fn test_no_irq_allocation() {
813818
let mut device_manager = MMIODeviceManager::new();
814819
let mut resource_allocator = ResourceAllocator::new().unwrap();
820+
815821
let device_info = device_manager
816822
.allocate_mmio_resources(&mut resource_allocator, 0)
817823
.unwrap();
818-
assert_eq!(device_info.irqs.len(), 0);
824+
assert!(device_info.irq.is_none());
825+
}
826+
827+
#[test]
828+
fn test_irq_allocation() {
829+
let mut device_manager = MMIODeviceManager::new();
830+
let mut resource_allocator = ResourceAllocator::new().unwrap();
831+
819832
let device_info = device_manager
820833
.allocate_mmio_resources(&mut resource_allocator, 1)
821834
.unwrap();
822-
assert_eq!(device_info.irqs[0], crate::arch::IRQ_BASE);
823-
assert_eq!(
824-
format!(
825-
"{}",
826-
device_manager
827-
.allocate_mmio_resources(
828-
&mut resource_allocator,
829-
crate::arch::IRQ_MAX - crate::arch::IRQ_BASE + 1
830-
)
831-
.unwrap_err()
832-
),
833-
"Failed to allocate requested resource: The requested resource is not available."
834-
.to_string()
835-
);
835+
assert_eq!(device_info.irq.unwrap().get(), crate::arch::IRQ_BASE);
836+
}
836837

837-
let device_info = device_manager
838-
.allocate_mmio_resources(
839-
&mut resource_allocator,
840-
crate::arch::IRQ_MAX - crate::arch::IRQ_BASE - 1,
841-
)
842-
.unwrap();
843-
assert_eq!(device_info.irqs[16], crate::arch::IRQ_BASE + 17);
838+
#[test]
839+
fn test_allocation_failure() {
840+
let mut device_manager = MMIODeviceManager::new();
841+
let mut resource_allocator = ResourceAllocator::new().unwrap();
844842
assert_eq!(
845843
format!(
846844
"{}",
847845
device_manager
848846
.allocate_mmio_resources(&mut resource_allocator, 2)
849847
.unwrap_err()
850848
),
851-
"Failed to allocate requested resource: The requested resource is not available."
852-
.to_string()
849+
"Invalid MMIO IRQ configuration.".to_string()
853850
);
854-
device_manager
855-
.allocate_mmio_resources(&mut resource_allocator, 0)
856-
.unwrap();
857851
}
858852
}

0 commit comments

Comments
 (0)