crosvm-direct: enable interrupt passthrough.
Simple command line option to enable host interrupt passthrough.
BUG=b:173824544
TEST=None
Change-Id: I75a0224b8885b4129c64811ac315b995b2120d46
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2734594
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Tomasz Jeznach <tjeznach@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
diff --git a/src/crosvm.rs b/src/crosvm.rs
index c79d0ff..45b0485 100644
--- a/src/crosvm.rs
+++ b/src/crosvm.rs
@@ -257,6 +257,10 @@
pub vhost_user_net: Vec<VhostUserOption>,
#[cfg(feature = "direct")]
pub direct_pmio: Option<DirectIoOption>,
+ #[cfg(feature = "direct")]
+ pub direct_level_irq: Vec<u32>,
+ #[cfg(feature = "direct")]
+ pub direct_edge_irq: Vec<u32>,
}
impl Default for Config {
@@ -326,6 +330,10 @@
vhost_user_net: Vec::new(),
#[cfg(feature = "direct")]
direct_pmio: None,
+ #[cfg(feature = "direct")]
+ direct_level_irq: Vec::new(),
+ #[cfg(feature = "direct")]
+ direct_edge_irq: Vec::new(),
}
}
}
diff --git a/src/linux.rs b/src/linux.rs
index 4e268c5..493f551 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -117,7 +117,10 @@
CreateWaitContext(base::Error),
DeviceJail(minijail::Error),
DevicePivotRoot(minijail::Error),
+ #[cfg(feature = "direct")]
DirectIo(io::Error),
+ #[cfg(feature = "direct")]
+ DirectIrq(devices::DirectIrqError),
Disk(PathBuf, io::Error),
DiskImageLock(base::Error),
DropCapabilities(base::Error),
@@ -233,7 +236,10 @@
CreateWaitContext(e) => write!(f, "failed to create wait context: {}", e),
DeviceJail(e) => write!(f, "failed to jail device: {}", e),
DevicePivotRoot(e) => write!(f, "failed to pivot root device: {}", e),
+ #[cfg(feature = "direct")]
DirectIo(e) => write!(f, "failed to open direct io device: {}", e),
+ #[cfg(feature = "direct")]
+ DirectIrq(e) => write!(f, "failed to enable interrupt forwarding: {}", e),
Disk(p, e) => write!(f, "failed to load disk image {}: {}", p.display(), e),
DiskImageLock(e) => write!(f, "failed to lock disk image: {}", e),
DropCapabilities(e) => write!(f, "failed to drop process capabilities: {}", e),
@@ -2507,6 +2513,41 @@
}
};
+ #[cfg(feature = "direct")]
+ let mut irqs = Vec::new();
+
+ #[cfg(feature = "direct")]
+ for irq in &cfg.direct_level_irq {
+ if !linux.resources.reserve_irq(*irq) {
+ warn!("irq {} already reserved.", irq);
+ }
+ let trigger = Event::new().map_err(Error::CreateEvent)?;
+ let resample = Event::new().map_err(Error::CreateEvent)?;
+ linux
+ .irq_chip
+ .register_irq_event(*irq, &trigger, Some(&resample))
+ .unwrap();
+ let direct_irq =
+ devices::DirectIrq::new(trigger, Some(resample)).map_err(Error::DirectIrq)?;
+ direct_irq.irq_enable(*irq).map_err(Error::DirectIrq)?;
+ irqs.push(direct_irq);
+ }
+
+ #[cfg(feature = "direct")]
+ for irq in &cfg.direct_edge_irq {
+ if !linux.resources.reserve_irq(*irq) {
+ warn!("irq {} already reserved.", irq);
+ }
+ let trigger = Event::new().map_err(Error::CreateEvent)?;
+ linux
+ .irq_chip
+ .register_irq_event(*irq, &trigger, None)
+ .unwrap();
+ let direct_irq = devices::DirectIrq::new(trigger, None).map_err(Error::DirectIrq)?;
+ direct_irq.irq_enable(*irq).map_err(Error::DirectIrq)?;
+ irqs.push(direct_irq);
+ }
+
run_control(
linux,
control_server_socket,
diff --git a/src/main.rs b/src/main.rs
index f1f6bc6..de4cfc1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1679,6 +1679,36 @@
}
cfg.direct_pmio = Some(parse_direct_io_options(value)?);
}
+ #[cfg(feature = "direct")]
+ "direct-level-irq" => {
+ cfg.direct_level_irq
+ .push(
+ value
+ .unwrap()
+ .parse()
+ .map_err(|_| argument::Error::InvalidValue {
+ value: value.unwrap().to_owned(),
+ expected: String::from(
+ "this value for `direct-level-irq` must be an unsigned integer",
+ ),
+ })?,
+ );
+ }
+ #[cfg(feature = "direct")]
+ "direct-edge-irq" => {
+ cfg.direct_edge_irq
+ .push(
+ value
+ .unwrap()
+ .parse()
+ .map_err(|_| argument::Error::InvalidValue {
+ value: value.unwrap().to_owned(),
+ expected: String::from(
+ "this value for `direct-edge-irq` must be an unsigned integer",
+ ),
+ })?,
+ );
+ }
"help" => return Err(argument::Error::PrintHelp),
_ => unreachable!(),
}
@@ -1894,6 +1924,10 @@
"Path to a socket path for vhost-user fs, and tag for the shared dir"),
#[cfg(feature = "direct")]
Argument::value("direct-pmio", "PATH@RANGE[,RANGE[,...]]", "Path and ranges for direct port I/O access"),
+ #[cfg(feature = "direct")]
+ Argument::value("direct-level-irq", "irq", "Enable interrupt passthrough"),
+ #[cfg(feature = "direct")]
+ Argument::value("direct-edge-irq", "irq", "Enable interrupt passthrough"),
Argument::short_flag('h', "help", "Print help message.")];
let mut cfg = Config::default();