Skip to content

Commit 7e9f032

Browse files
committed
Add data structure to describe resource requirements
Add DeviceResourceRequest enum to describe a device's resource requirements, so we could build better flow among the VMM, the device manager and the device object. Signed-off-by: Liu Jiang <gerry@linux.alibaba.com> Signed-off-by: 守情 <liheng.xlh@alibaba-inc.com>
1 parent 6b8654a commit 7e9f032

File tree

1 file changed

+209
-0
lines changed

1 file changed

+209
-0
lines changed

src/resources.rs

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,105 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
//! Structs to manage device resources.
5+
//!
6+
//! The high level flow of resource management among the VMM, the device manager, and the device
7+
//! is as below:
8+
//! 1) the VMM creates a new device object.
9+
//! 2) the VMM asks the new device object for its resource requirements.
10+
//! 3) the VMM allocates resources for the device object according to resource requirements.
11+
//! 4) the VMM passes the allocated resources to the device object.
12+
//! 5) the VMM registers the new device onto corresponding device managers according the allocated
13+
//! resources.
14+
15+
use std::{u16, u32, u64};
16+
17+
/// Enumeration describing a device's resource requirements.
18+
pub enum ResourceConstraint {
19+
/// Request for an IO Port address range.
20+
PioAddress {
21+
/// Allocate resource within the range [`min`, `max`] if `min` is not u16::MAX.
22+
min: u16,
23+
/// Allocate resource within the range [`min`, `max`] if `max` is not zero.
24+
max: u16,
25+
/// Alignment for the allocated address.
26+
align: u16,
27+
/// Size for the allocated address range.
28+
size: u16,
29+
},
30+
/// Request for a Memory Mapped IO address range.
31+
MmioAddress {
32+
/// Allocate resource within the range [`min`, `max`] if 'min' is not u64::MAX.
33+
min: u64,
34+
/// Allocate resource within the range [`min`, `max`] if 'max' is not zero.
35+
max: u64,
36+
/// Alignment for the allocated address.
37+
align: u64,
38+
/// Size for the allocated address range.
39+
size: u64,
40+
},
41+
/// Request for a legacy IRQ.
42+
LegacyIrq {
43+
/// Reserve the preallocated IRQ if it's not u32::MAX.
44+
fixed: u32,
45+
},
46+
/// Request for PCI MSI IRQs.
47+
PciMsiIrq {
48+
/// Number of Irqs to allocate.
49+
size: u32,
50+
},
51+
/// Request for PCI MSIx IRQs.
52+
PciMsixIrq {
53+
/// Number of Irqs to allocate.
54+
size: u32,
55+
},
56+
/// Request for generic IRQs.
57+
GenericIrq {
58+
/// Number of Irqs to allocate.
59+
size: u32,
60+
},
61+
/// Request for KVM mem_slot indexes to map memory into the guest.
62+
KvmMemSlot {
63+
/// Allocate the specified kvm memory slot index if it's not u32::MAX.
64+
fixed: u32,
65+
/// Number of slots to allocate.
66+
size: u32,
67+
},
68+
}
69+
70+
impl ResourceConstraint {
71+
/// Create a new Mmio address request object with default configuration.
72+
pub fn new_pio(size: u16) -> Self {
73+
ResourceConstraint::PioAddress {
74+
min: u16::MAX,
75+
max: 0,
76+
align: 0x1,
77+
size,
78+
}
79+
}
80+
81+
/// Create a new Mmio address request object with default configuration.
82+
pub fn new_mmio(size: u64) -> Self {
83+
ResourceConstraint::MmioAddress {
84+
min: u64::MAX,
85+
max: 0,
86+
align: 0x1000,
87+
size,
88+
}
89+
}
90+
91+
/// Create a new legacy IRQ request object with default configuration.
92+
pub fn new_legacy_irq() -> Self {
93+
ResourceConstraint::LegacyIrq { fixed: u32::MAX }
94+
}
95+
96+
/// Create a new KVM memory slot request object with default configuration.
97+
pub fn new_kvm_mem_slot(size: u32) -> Self {
98+
ResourceConstraint::KvmMemSlot {
99+
fixed: u32::MAX,
100+
size,
101+
}
102+
}
103+
}
5104

6105
/// Type of Message Singaled Interrupt
7106
#[derive(Copy, Clone, PartialEq)]
@@ -140,3 +239,113 @@ impl DeviceResources {
140239
&self.0
141240
}
142241
}
242+
243+
#[cfg(test)]
244+
mod test {
245+
use super::*;
246+
247+
const PIO_ADDRESS_SIZE: u16 = 5;
248+
const PIO_ADDRESS_BASE: u16 = 0;
249+
const MMIO_ADDRESS_SIZE: u64 = 0x8765_4321;
250+
const MMIO_ADDRESS_BASE: u64 = 0x1234_5678;
251+
const LEGACY_IRQ: u32 = 0x168;
252+
const PCI_MSI_IRQ_SIZE: u32 = 0x8888;
253+
const PCI_MSI_IRQ_BASE: u32 = 0x6666;
254+
const PCI_MSIX_IRQ_SIZE: u32 = 0x16666;
255+
const PCI_MSIX_IRQ_BASE: u32 = 0x8888;
256+
const GENERIC_MSI_IRQS_SIZE: u32 = 0x16888;
257+
const GENERIC_MSI_IRQS_BASE: u32 = 0x16688;
258+
const NIC_MAC_ADDRESS: &str = "00:08:63:66:86:88";
259+
260+
fn get_device_resource() -> DeviceResources {
261+
let entry = ResourceEntry::PioAddressRange {
262+
base: PIO_ADDRESS_BASE,
263+
size: PIO_ADDRESS_SIZE,
264+
};
265+
let mut resource = DeviceResources::new();
266+
resource.append(entry);
267+
let entry = ResourceEntry::MmioAddressRange {
268+
base: MMIO_ADDRESS_BASE,
269+
size: MMIO_ADDRESS_SIZE,
270+
};
271+
resource.append(entry);
272+
let entry = ResourceEntry::LegacyIrq(LEGACY_IRQ);
273+
resource.append(entry);
274+
let entry = ResourceEntry::PciMsiIrq {
275+
base: PCI_MSI_IRQ_BASE,
276+
size: PCI_MSI_IRQ_SIZE,
277+
};
278+
resource.append(entry);
279+
let entry = ResourceEntry::PciMsixIrq {
280+
base: PCI_MSIX_IRQ_BASE,
281+
size: PCI_MSIX_IRQ_SIZE,
282+
};
283+
resource.append(entry);
284+
let entry = ResourceEntry::GenericIrq {
285+
base: GENERIC_MSI_IRQS_BASE,
286+
size: GENERIC_MSI_IRQS_SIZE,
287+
};
288+
resource.append(entry);
289+
let entry = ResourceEntry::NicMacAddresss(NIC_MAC_ADDRESS.to_string());
290+
resource.append(entry);
291+
292+
resource
293+
}
294+
295+
#[test]
296+
fn get_pio_address_ranges() {
297+
let resources = get_device_resource();
298+
assert!(
299+
resources.get_pio_address_ranges()[0].0 == PIO_ADDRESS_BASE
300+
&& resources.get_pio_address_ranges()[0].1 == PIO_ADDRESS_SIZE
301+
);
302+
}
303+
304+
#[test]
305+
fn test_get_mmio_address_ranges() {
306+
let resources = get_device_resource();
307+
assert!(
308+
resources.get_mmio_address_ranges()[0].0 == MMIO_ADDRESS_BASE
309+
&& resources.get_mmio_address_ranges()[0].1 == MMIO_ADDRESS_SIZE
310+
);
311+
}
312+
313+
#[test]
314+
fn test_get_legacy_irq() {
315+
let resources = get_device_resource();
316+
assert!(resources.get_legacy_irq().unwrap() == LEGACY_IRQ);
317+
}
318+
319+
#[test]
320+
fn test_get_pci_msi_irqs() {
321+
let resources = get_device_resource();
322+
assert!(
323+
resources.get_pci_msi_irqs().unwrap().0 == PCI_MSI_IRQ_BASE
324+
&& resources.get_pci_msi_irqs().unwrap().1 == PCI_MSI_IRQ_SIZE
325+
);
326+
}
327+
328+
#[test]
329+
fn test_pci_msix_irqs() {
330+
let resources = get_device_resource();
331+
assert!(
332+
resources.get_pci_msix_irqs().unwrap().0 == PCI_MSIX_IRQ_BASE
333+
&& resources.get_pci_msix_irqs().unwrap().1 == PCI_MSIX_IRQ_SIZE
334+
);
335+
}
336+
337+
#[test]
338+
fn test_get_generic_msi_irqs() {
339+
let resources = get_device_resource();
340+
assert!(
341+
resources.get_generic_msi_irqs().unwrap().0 == GENERIC_MSI_IRQS_BASE
342+
&& resources.get_generic_msi_irqs().unwrap().1 == GENERIC_MSI_IRQS_SIZE
343+
);
344+
}
345+
346+
#[test]
347+
fn test_get_mac_address() {
348+
let resources = get_device_resource();
349+
assert_eq!(resources.get_mac_address().unwrap(), NIC_MAC_ADDRESS);
350+
}
351+
}

0 commit comments

Comments
 (0)