Skip to content

Commit 7bf4308

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> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
1 parent 6b8654a commit 7bf4308

File tree

2 files changed

+228
-1
lines changed

2 files changed

+228
-1
lines changed

coverage_config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"coverage_score": 0,
2+
"coverage_score": 64.1,
33
"exclude_path": "",
44
"crate_features": ""
55
}

src/resources.rs

Lines changed: 227 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 constraints.
10+
//! 3) the VMM allocates resources for the device object according to resource constraints.
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 constraints.
18+
pub enum ResourceConstraint {
19+
/// Constraint 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+
/// Constraint 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+
/// Constraint for a legacy IRQ.
42+
LegacyIrq {
43+
/// Reserve the preallocated IRQ if it's not u32::MAX.
44+
fixed: u32,
45+
},
46+
/// Constraint for PCI MSI IRQs.
47+
PciMsiIrq {
48+
/// Number of Irqs to allocate.
49+
size: u32,
50+
},
51+
/// Constraint for PCI MSIx IRQs.
52+
PciMsixIrq {
53+
/// Number of Irqs to allocate.
54+
size: u32,
55+
},
56+
/// Constraint for generic IRQs.
57+
GenericIrq {
58+
/// Number of Irqs to allocate.
59+
size: u32,
60+
},
61+
/// Constraint 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 PIO address constraint 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 constraint 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 constraint 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 constraint 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,131 @@ impl DeviceResources {
140239
&self.0
141240
}
142241
}
242+
243+
#[cfg(test)]
244+
mod tests {
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 MAC_ADDRESS: &str = "00:08:63:66:86:88";
259+
const KVM_SLOT_ID: u32 = 0x0100;
260+
261+
fn get_device_resource() -> DeviceResources {
262+
let entry = Resource::PioAddressRange {
263+
base: PIO_ADDRESS_BASE,
264+
size: PIO_ADDRESS_SIZE,
265+
};
266+
let mut resource = DeviceResources::new();
267+
resource.append(entry);
268+
let entry = Resource::MmioAddressRange {
269+
base: MMIO_ADDRESS_BASE,
270+
size: MMIO_ADDRESS_SIZE,
271+
};
272+
resource.append(entry);
273+
let entry = Resource::LegacyIrq(LEGACY_IRQ);
274+
resource.append(entry);
275+
let entry = Resource::MsiIrq {
276+
ty: MsiIrqType::PciMsi,
277+
base: PCI_MSI_IRQ_BASE,
278+
size: PCI_MSI_IRQ_SIZE,
279+
};
280+
resource.append(entry);
281+
let entry = Resource::MsiIrq {
282+
ty: MsiIrqType::PciMsix,
283+
base: PCI_MSIX_IRQ_BASE,
284+
size: PCI_MSIX_IRQ_SIZE,
285+
};
286+
resource.append(entry);
287+
let entry = Resource::MsiIrq {
288+
ty: MsiIrqType::GenericMsi,
289+
base: GENERIC_MSI_IRQS_BASE,
290+
size: GENERIC_MSI_IRQS_SIZE,
291+
};
292+
resource.append(entry);
293+
let entry = Resource::MacAddresss(MAC_ADDRESS.to_string());
294+
resource.append(entry);
295+
296+
resource.append(Resource::KvmMemSlot(KVM_SLOT_ID));
297+
298+
resource
299+
}
300+
301+
#[test]
302+
fn get_pio_address_ranges() {
303+
let resources = get_device_resource();
304+
assert!(
305+
resources.get_pio_address_ranges()[0].0 == PIO_ADDRESS_BASE
306+
&& resources.get_pio_address_ranges()[0].1 == PIO_ADDRESS_SIZE
307+
);
308+
}
309+
310+
#[test]
311+
fn test_get_mmio_address_ranges() {
312+
let resources = get_device_resource();
313+
assert!(
314+
resources.get_mmio_address_ranges()[0].0 == MMIO_ADDRESS_BASE
315+
&& resources.get_mmio_address_ranges()[0].1 == MMIO_ADDRESS_SIZE
316+
);
317+
}
318+
319+
#[test]
320+
fn test_get_legacy_irq() {
321+
let resources = get_device_resource();
322+
assert!(resources.get_legacy_irq().unwrap() == LEGACY_IRQ);
323+
}
324+
325+
#[test]
326+
fn test_get_pci_msi_irqs() {
327+
let resources = get_device_resource();
328+
assert!(
329+
resources.get_pci_msi_irqs().unwrap().0 == PCI_MSI_IRQ_BASE
330+
&& resources.get_pci_msi_irqs().unwrap().1 == PCI_MSI_IRQ_SIZE
331+
);
332+
}
333+
334+
#[test]
335+
fn test_pci_msix_irqs() {
336+
let resources = get_device_resource();
337+
assert!(
338+
resources.get_pci_msix_irqs().unwrap().0 == PCI_MSIX_IRQ_BASE
339+
&& resources.get_pci_msix_irqs().unwrap().1 == PCI_MSIX_IRQ_SIZE
340+
);
341+
}
342+
343+
#[test]
344+
fn test_get_generic_msi_irqs() {
345+
let resources = get_device_resource();
346+
assert!(
347+
resources.get_generic_msi_irqs().unwrap().0 == GENERIC_MSI_IRQS_BASE
348+
&& resources.get_generic_msi_irqs().unwrap().1 == GENERIC_MSI_IRQS_SIZE
349+
);
350+
}
351+
352+
#[test]
353+
fn test_get_mac_address() {
354+
let resources = get_device_resource();
355+
assert_eq!(resources.get_mac_address().unwrap(), MAC_ADDRESS);
356+
}
357+
358+
#[test]
359+
fn test_get_kvm_slot() {
360+
let resources = get_device_resource();
361+
assert_eq!(resources.get_kvm_mem_slots(), vec![KVM_SLOT_ID]);
362+
}
363+
364+
#[test]
365+
fn test_get_all_resources() {
366+
let resources = get_device_resource();
367+
assert_eq!(resources.get_all_resources().len(), 8);
368+
}
369+
}

0 commit comments

Comments
 (0)