@@ -19,7 +19,9 @@ use crate::snapshot::Persist;
1919/// * Memory allocations in the MMIO address space
2020#[ derive( Debug , Clone , Serialize , Deserialize ) ]
2121pub struct ResourceAllocator {
22- /// Allocator for device interrupt lines
22+ /// Allocator for legacy device interrupt lines
23+ pub irq_allocator : IdAllocator ,
24+ /// Allocator for PCI device GSIs
2325 pub gsi_allocator : IdAllocator ,
2426 /// Allocator for memory in the 32-bit MMIO address space
2527 pub mmio32_memory : AddressAllocator ,
@@ -41,7 +43,8 @@ impl ResourceAllocator {
4143 // It is fine for us to unwrap the following since we know we are passing valid ranges for
4244 // all allocators
4345 Self {
44- gsi_allocator : IdAllocator :: new ( arch:: IRQ_BASE , arch:: IRQ_MAX ) . unwrap ( ) ,
46+ irq_allocator : IdAllocator :: new ( arch:: IRQ_BASE , arch:: IRQ_MAX ) . unwrap ( ) ,
47+ gsi_allocator : IdAllocator :: new ( arch:: GSI_BASE , arch:: GSI_MAX ) . unwrap ( ) ,
4548 mmio32_memory : AddressAllocator :: new (
4649 arch:: MEM_32BIT_DEVICES_START ,
4750 arch:: MEM_32BIT_DEVICES_SIZE ,
@@ -57,6 +60,30 @@ impl ResourceAllocator {
5760 }
5861 }
5962
63+ /// Allocate a number of legacy IRQs
64+ ///
65+ /// # Arguments
66+ ///
67+ /// * `irq_count` - The number of legacy IRQs to allocate
68+ pub fn allocate_irq ( & mut self , irq_count : u32 ) -> Result < Vec < u32 > , vm_allocator:: Error > {
69+ let mut irqs = Vec :: with_capacity ( irq_count as usize ) ;
70+
71+ for _ in 0 ..irq_count {
72+ match self . irq_allocator . allocate_id ( ) {
73+ Ok ( irq) => irqs. push ( irq) ,
74+ Err ( err) => {
75+ // It is ok to unwrap here, we just allocated the GSI
76+ irqs. into_iter ( ) . for_each ( |irq| {
77+ self . irq_allocator . free_id ( irq) . unwrap ( ) ;
78+ } ) ;
79+ return Err ( err) ;
80+ }
81+ }
82+ }
83+
84+ Ok ( irqs)
85+ }
86+
6087 /// Allocate a number of GSIs
6188 ///
6289 /// # Arguments
@@ -167,25 +194,66 @@ mod tests {
167194 use vm_allocator:: AllocPolicy ;
168195
169196 use super :: ResourceAllocator ;
170- use crate :: arch:: { self , IRQ_BASE } ;
197+ use crate :: arch:: { self , GSI_BASE , IRQ_BASE } ;
171198 use crate :: snapshot:: { Persist , Snapshot } ;
172199
173200 const MAX_IRQS : u32 = arch:: IRQ_MAX - arch:: IRQ_BASE + 1 ;
174201
202+ #[ test]
203+ fn test_allocate_irq ( ) {
204+ let mut allocator = ResourceAllocator :: new ( ) ;
205+ // asking for 0 IRQs should return us an empty vector
206+ assert_eq ! ( allocator. allocate_irq( 0 ) , Ok ( vec![ ] ) ) ;
207+ // We cannot allocate more GSIs than available
208+ assert_eq ! (
209+ allocator. allocate_irq( MAX_IRQS + 1 ) ,
210+ Err ( vm_allocator:: Error :: ResourceNotAvailable )
211+ ) ;
212+ // But allocating all of them at once should work
213+ assert_eq ! (
214+ allocator. allocate_irq( MAX_IRQS ) ,
215+ Ok ( ( arch:: IRQ_BASE ..=arch:: IRQ_MAX ) . collect:: <Vec <_>>( ) )
216+ ) ;
217+ // And now we ran out of GSIs
218+ assert_eq ! (
219+ allocator. allocate_irq( 1 ) ,
220+ Err ( vm_allocator:: Error :: ResourceNotAvailable )
221+ ) ;
222+ // But we should be able to ask for 0 GSIs
223+ assert_eq ! ( allocator. allocate_irq( 0 ) , Ok ( vec![ ] ) ) ;
224+
225+ let mut allocator = ResourceAllocator :: new ( ) ;
226+ // We should be able to allocate 1 GSI
227+ assert_eq ! ( allocator. allocate_irq( 1 ) , Ok ( vec![ arch:: IRQ_BASE ] ) ) ;
228+ // We can't allocate MAX_IRQS any more
229+ assert_eq ! (
230+ allocator. allocate_irq( MAX_IRQS ) ,
231+ Err ( vm_allocator:: Error :: ResourceNotAvailable )
232+ ) ;
233+ // We can allocate another one and it should be the second available
234+ assert_eq ! ( allocator. allocate_irq( 1 ) , Ok ( vec![ arch:: IRQ_BASE + 1 ] ) ) ;
235+ // Let's allocate the rest in a loop
236+ for i in arch:: IRQ_BASE + 2 ..=arch:: IRQ_MAX {
237+ assert_eq ! ( allocator. allocate_irq( 1 ) , Ok ( vec![ i] ) ) ;
238+ }
239+ }
240+
241+ const MAX_GSIS : u32 = arch:: GSI_MAX - arch:: GSI_BASE + 1 ;
242+
175243 #[ test]
176244 fn test_allocate_gsi ( ) {
177245 let mut allocator = ResourceAllocator :: new ( ) ;
178246 // asking for 0 IRQs should return us an empty vector
179247 assert_eq ! ( allocator. allocate_gsi( 0 ) , Ok ( vec![ ] ) ) ;
180248 // We cannot allocate more GSIs than available
181249 assert_eq ! (
182- allocator. allocate_gsi( MAX_IRQS + 1 ) ,
250+ allocator. allocate_gsi( MAX_GSIS + 1 ) ,
183251 Err ( vm_allocator:: Error :: ResourceNotAvailable )
184252 ) ;
185253 // But allocating all of them at once should work
186254 assert_eq ! (
187- allocator. allocate_gsi( MAX_IRQS ) ,
188- Ok ( ( arch:: IRQ_BASE ..=arch:: IRQ_MAX ) . collect:: <Vec <_>>( ) )
255+ allocator. allocate_gsi( MAX_GSIS ) ,
256+ Ok ( ( arch:: GSI_BASE ..=arch:: GSI_MAX ) . collect:: <Vec <_>>( ) )
189257 ) ;
190258 // And now we ran out of GSIs
191259 assert_eq ! (
@@ -197,16 +265,16 @@ mod tests {
197265
198266 let mut allocator = ResourceAllocator :: new ( ) ;
199267 // We should be able to allocate 1 GSI
200- assert_eq ! ( allocator. allocate_gsi( 1 ) , Ok ( vec![ arch:: IRQ_BASE ] ) ) ;
268+ assert_eq ! ( allocator. allocate_gsi( 1 ) , Ok ( vec![ arch:: GSI_BASE ] ) ) ;
201269 // We can't allocate MAX_IRQS any more
202270 assert_eq ! (
203- allocator. allocate_gsi( MAX_IRQS ) ,
271+ allocator. allocate_gsi( MAX_GSIS ) ,
204272 Err ( vm_allocator:: Error :: ResourceNotAvailable )
205273 ) ;
206274 // We can allocate another one and it should be the second available
207- assert_eq ! ( allocator. allocate_gsi( 1 ) , Ok ( vec![ arch:: IRQ_BASE + 1 ] ) ) ;
275+ assert_eq ! ( allocator. allocate_gsi( 1 ) , Ok ( vec![ arch:: GSI_BASE + 1 ] ) ) ;
208276 // Let's allocate the rest in a loop
209- for i in arch:: IRQ_BASE + 2 ..=arch:: IRQ_MAX {
277+ for i in arch:: GSI_BASE + 2 ..=arch:: GSI_MAX {
210278 assert_eq ! ( allocator. allocate_gsi( 1 ) , Ok ( vec![ i] ) ) ;
211279 }
212280 }
@@ -221,12 +289,16 @@ mod tests {
221289 #[ test]
222290 fn test_save_restore ( ) {
223291 let mut allocator0 = ResourceAllocator :: new ( ) ;
292+ let irq_0 = allocator0. allocate_irq ( 1 ) . unwrap ( ) [ 0 ] ;
293+ assert_eq ! ( irq_0, IRQ_BASE ) ;
224294 let gsi_0 = allocator0. allocate_gsi ( 1 ) . unwrap ( ) [ 0 ] ;
225- assert_eq ! ( gsi_0, IRQ_BASE ) ;
295+ assert_eq ! ( gsi_0, GSI_BASE ) ;
226296
227297 let mut allocator1 = clone_allocator ( & allocator0) ;
298+ let irq_1 = allocator1. allocate_irq ( 1 ) . unwrap ( ) [ 0 ] ;
299+ assert_eq ! ( irq_1, IRQ_BASE + 1 ) ;
228300 let gsi_1 = allocator1. allocate_gsi ( 1 ) . unwrap ( ) [ 0 ] ;
229- assert_eq ! ( gsi_1, IRQ_BASE + 1 ) ;
301+ assert_eq ! ( gsi_1, GSI_BASE + 1 ) ;
230302 let mmio32_mem = allocator1
231303 . allocate_32bit_mmio_memory ( 0x42 , 1 , AllocPolicy :: FirstMatch )
232304 . unwrap ( ) ;
@@ -251,8 +323,10 @@ mod tests {
251323 . allocate_system_memory ( 0x42 , 1 , AllocPolicy :: ExactMatch ( system_mem) )
252324 . unwrap_err ( ) ;
253325
326+ let irq_2 = allocator2. allocate_irq ( 1 ) . unwrap ( ) [ 0 ] ;
327+ assert_eq ! ( irq_2, IRQ_BASE + 2 ) ;
254328 let gsi_2 = allocator2. allocate_gsi ( 1 ) . unwrap ( ) [ 0 ] ;
255- assert_eq ! ( gsi_2, IRQ_BASE + 2 ) ;
329+ assert_eq ! ( gsi_2, GSI_BASE + 2 ) ;
256330 let mmio32_mem = allocator1
257331 . allocate_32bit_mmio_memory ( 0x42 , 1 , AllocPolicy :: FirstMatch )
258332 . unwrap ( ) ;
0 commit comments