Skip to content

Commit 43247e4

Browse files
andr3wyShadowCurse
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 f6bd4b6 commit 43247e4

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")]
@@ -79,8 +80,8 @@ pub struct MMIODeviceInfo {
7980
pub addr: u64,
8081
/// Mmio addr range length.
8182
pub len: u64,
82-
/// Used Irq line(s) for the device.
83-
pub irqs: Vec<u32>,
83+
/// Used Irq line for the device.
84+
pub irq: Option<NonZeroU32>, // NOTE: guaranteed to be a value not 0, 0 is not allowed
8485
}
8586

8687
#[cfg(target_arch = "x86_64")]
@@ -150,15 +151,20 @@ impl MMIODeviceManager {
150151
resource_allocator: &mut ResourceAllocator,
151152
irq_count: u32,
152153
) -> Result<MMIODeviceInfo, MmioError> {
153-
let irqs = resource_allocator.allocate_gsi(irq_count)?;
154+
let irq = match resource_allocator.allocate_gsi(irq_count)?[..] {
155+
[] => None,
156+
[irq] => NonZeroU32::new(irq),
157+
_ => return Err(MmioError::InvalidIrqConfig),
158+
};
159+
154160
let device_info = MMIODeviceInfo {
155161
addr: resource_allocator.allocate_mmio_memory(
156162
MMIO_LEN,
157163
MMIO_LEN,
158164
AllocPolicy::FirstMatch,
159165
)?,
160166
len: MMIO_LEN,
161-
irqs,
167+
irq,
162168
};
163169
Ok(device_info)
164170
}
@@ -187,9 +193,9 @@ impl MMIODeviceManager {
187193
) -> Result<(), MmioError> {
188194
// Our virtio devices are currently hardcoded to use a single IRQ.
189195
// Validate that requirement.
190-
if device_info.irqs.len() != 1 {
196+
let Some(irq) = device_info.irq else {
191197
return Err(MmioError::InvalidIrqConfig);
192-
}
198+
};
193199
let identifier;
194200
{
195201
let locked_device = mmio_device.locked_device();
@@ -201,11 +207,8 @@ impl MMIODeviceManager {
201207
vm.register_ioevent(queue_evt, &io_addr, u32::try_from(i).unwrap())
202208
.map_err(MmioError::RegisterIoEvent)?;
203209
}
204-
vm.register_irqfd(
205-
&locked_device.interrupt_trigger().irq_evt,
206-
device_info.irqs[0],
207-
)
208-
.map_err(MmioError::RegisterIrqFd)?;
210+
vm.register_irqfd(&locked_device.interrupt_trigger().irq_evt, irq.get())
211+
.map_err(MmioError::RegisterIrqFd)?;
209212
}
210213

211214
self.register_mmio_device(
@@ -230,7 +233,7 @@ impl MMIODeviceManager {
230233
.add_virtio_mmio_device(
231234
device_info.len,
232235
GuestAddress(device_info.addr),
233-
device_info.irqs[0],
236+
device_info.irq.unwrap().get(),
234237
None,
235238
)
236239
.map_err(MmioError::Cmdline)
@@ -257,7 +260,7 @@ impl MMIODeviceManager {
257260
device_info.len,
258261
// We are sure that `irqs` has at least one element; allocate_mmio_resources makes
259262
// sure of it.
260-
device_info.irqs[0],
263+
device_info.irq.unwrap().get(),
261264
)?;
262265
}
263266
Ok(device_info)
@@ -289,7 +292,7 @@ impl MMIODeviceManager {
289292
.unwrap()
290293
.serial
291294
.interrupt_evt(),
292-
device_info.irqs[0],
295+
device_info.irq.unwrap().get(),
293296
)
294297
.map_err(MmioError::RegisterIrqFd)?;
295298

@@ -525,7 +528,7 @@ impl DeviceInfoForFDT for MMIODeviceInfo {
525528
self.addr
526529
}
527530
fn irq(&self) -> u32 {
528-
self.irqs[0]
531+
self.irq.unwrap().into()
529532
}
530533
fn length(&self) -> u64 {
531534
self.len
@@ -574,11 +577,10 @@ mod tests {
574577
#[cfg(target_arch = "x86_64")]
575578
/// Gets the number of interrupts used by the devices registered.
576579
pub fn used_irqs_count(&self) -> usize {
577-
let mut irq_number = 0;
578580
self.get_device_info()
579581
.iter()
580-
.for_each(|(_, device_info)| irq_number += device_info.irqs.len());
581-
irq_number
582+
.filter(|(_, device_info)| device_info.irq.is_some())
583+
.count()
582584
}
583585
}
584586

@@ -784,7 +786,10 @@ mod tests {
784786
);
785787
assert_eq!(
786788
crate::arch::IRQ_BASE,
787-
device_manager.id_to_dev_info[&(DeviceType::Virtio(type_id), id)].irqs[0]
789+
device_manager.id_to_dev_info[&(DeviceType::Virtio(type_id), id)]
790+
.irq
791+
.unwrap()
792+
.get()
788793
);
789794

790795
let id = "bar";
@@ -821,50 +826,39 @@ mod tests {
821826
}
822827

823828
#[test]
824-
fn test_slot_irq_allocation() {
829+
fn test_no_irq_allocation() {
825830
let mut device_manager = MMIODeviceManager::new();
826831
let mut resource_allocator = ResourceAllocator::new().unwrap();
832+
827833
let device_info = device_manager
828834
.allocate_mmio_resources(&mut resource_allocator, 0)
829835
.unwrap();
830-
assert_eq!(device_info.irqs.len(), 0);
836+
assert!(device_info.irq.is_none());
837+
}
838+
839+
#[test]
840+
fn test_irq_allocation() {
841+
let mut device_manager = MMIODeviceManager::new();
842+
let mut resource_allocator = ResourceAllocator::new().unwrap();
843+
831844
let device_info = device_manager
832845
.allocate_mmio_resources(&mut resource_allocator, 1)
833846
.unwrap();
834-
assert_eq!(device_info.irqs[0], crate::arch::IRQ_BASE);
835-
assert_eq!(
836-
format!(
837-
"{}",
838-
device_manager
839-
.allocate_mmio_resources(
840-
&mut resource_allocator,
841-
crate::arch::IRQ_MAX - crate::arch::IRQ_BASE + 1
842-
)
843-
.unwrap_err()
844-
),
845-
"Failed to allocate requested resource: The requested resource is not available."
846-
.to_string()
847-
);
847+
assert_eq!(device_info.irq.unwrap().get(), crate::arch::IRQ_BASE);
848+
}
848849

849-
let device_info = device_manager
850-
.allocate_mmio_resources(
851-
&mut resource_allocator,
852-
crate::arch::IRQ_MAX - crate::arch::IRQ_BASE - 1,
853-
)
854-
.unwrap();
855-
assert_eq!(device_info.irqs[16], crate::arch::IRQ_BASE + 17);
850+
#[test]
851+
fn test_allocation_failure() {
852+
let mut device_manager = MMIODeviceManager::new();
853+
let mut resource_allocator = ResourceAllocator::new().unwrap();
856854
assert_eq!(
857855
format!(
858856
"{}",
859857
device_manager
860858
.allocate_mmio_resources(&mut resource_allocator, 2)
861859
.unwrap_err()
862860
),
863-
"Failed to allocate requested resource: The requested resource is not available."
864-
.to_string()
861+
"Invalid MMIO IRQ configuration.".to_string()
865862
);
866-
device_manager
867-
.allocate_mmio_resources(&mut resource_allocator, 0)
868-
.unwrap();
869863
}
870864
}

0 commit comments

Comments
 (0)