Skip to content

Commit cc81e85

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 <gerry@linux.alibaba.com> Signed-off-by: Bin Zha <zhabin@linux.alibaba.com>
1 parent 0c062d5 commit cc81e85

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ vm-memory = { git = "https://github.com/rust-vmm/vm-memory" }
1717
[features]
1818
kvm_irq = ["kvm-ioctls", "kvm-bindings"]
1919
legacy_irq = []
20+
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: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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+
unsafe {
34+
entry.u.msi.address_hi = msicfg.high_addr;
35+
entry.u.msi.address_lo = msicfg.low_addr;
36+
entry.u.msi.data = msicfg.data;
37+
}
38+
entry
39+
}
40+
41+
#[allow(irrefutable_let_patterns)]
42+
pub(super) fn create_msi_routing_entries(
43+
base: InterruptIndex,
44+
configs: &[InterruptSourceConfig],
45+
) -> Result<Vec<kvm_irq_routing_entry>> {
46+
let _ = base
47+
.checked_add(configs.len() as u32)
48+
.ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;
49+
let mut entries = Vec::with_capacity(configs.len());
50+
for (i, ref val) in configs.iter().enumerate() {
51+
if let InterruptSourceConfig::MsiIrq(msicfg) = val {
52+
let entry = new_msi_routing_entry(base + i as u32, msicfg);
53+
entries.push(entry);
54+
} else {
55+
return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
56+
}
57+
}
58+
Ok(entries)
59+
}

0 commit comments

Comments
 (0)