Skip to content

Commit 3aecee8

Browse files
committed
Add generic heplers to manage MSI interrupts
Introduce generic mechanism to support message signalled interrupts based on KVM hypervisor. Signed-off-by: Liu Jiang <[email protected]> Signed-off-by: Bin Zha <[email protected]>
1 parent 1c4c121 commit 3aecee8

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ vmm-sys-util = "~0"
1515
[features]
1616
kvm_irq = ["kvm-ioctls", "kvm-bindings"]
1717
legacy_irq = []
18+
msi_irq = []

src/interrupt/kvm/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ mod legacy_irq;
2020
#[cfg(feature = "legacy_irq")]
2121
use self::legacy_irq::LegacyIrq;
2222

23+
#[cfg(feature = "msi_irq")]
24+
mod msi_irq;
25+
2326
/// Structure to manage interrupt sources for a virtual machine based on the Linux KVM framework.
2427
///
2528
/// The KVM framework provides methods to inject interrupts into the target virtual machines,

src/interrupt/kvm/msi_irq.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (C) 2019 Alibaba Cloud. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! Helper utilities for handling MSI interrupts.
5+
6+
use super::*;
7+
use kvm_bindings::{kvm_irq_routing_entry, KVM_IRQ_ROUTING_MSI};
8+
9+
pub(super) struct MsiConfig {
10+
pub(super) irqfd: EventFd,
11+
pub(super) config: Mutex<MsiIrqSourceConfig>,
12+
}
13+
14+
impl MsiConfig {
15+
pub(super) fn new() -> Self {
16+
MsiConfig {
17+
irqfd: EventFd::new(0).unwrap(),
18+
config: Mutex::new(Default::default()),
19+
}
20+
}
21+
}
22+
23+
pub(super) fn new_msi_routing_entry(
24+
gsi: InterruptIndex,
25+
msicfg: &MsiIrqSourceConfig,
26+
) -> kvm_irq_routing_entry {
27+
let mut entry = kvm_irq_routing_entry {
28+
gsi,
29+
type_: KVM_IRQ_ROUTING_MSI,
30+
flags: 0,
31+
..Default::default()
32+
};
33+
entry.u.msi.address_hi = msicfg.high_addr;
34+
entry.u.msi.address_lo = msicfg.low_addr;
35+
entry.u.msi.data = msicfg.data;
36+
entry
37+
}
38+
39+
#[allow(irrefutable_let_patterns)]
40+
pub(super) fn create_msi_routing_entries(
41+
base: InterruptIndex,
42+
configs: &[InterruptSourceConfig],
43+
) -> Result<Vec<kvm_irq_routing_entry>> {
44+
let _ = base
45+
.checked_add(configs.len() as u32)
46+
.ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;
47+
let mut entries = Vec::with_capacity(configs.len());
48+
for (i, ref val) in configs.iter().enumerate() {
49+
if let InterruptSourceConfig::MsiIrq(msicfg) = val {
50+
let entry = new_msi_routing_entry(base + i as u32, msicfg);
51+
entries.push(entry);
52+
} else {
53+
return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
54+
}
55+
}
56+
Ok(entries)
57+
}

0 commit comments

Comments
 (0)