From 0fcd75312712096744f2a9fc473acdd7c2a99839 Mon Sep 17 00:00:00 2001 From: Henry Li Date: Wed, 2 Sep 2026 21:59:17 -0700 Subject: [PATCH 1/3] openvmm: make GICv2m SPI count configurable Extend --gic-msi with v2m,spi_count=N and pass the value through to the existing GicMsiConfig field. This lets device-heavy guests reserve a larger MSI SPI pool without changing the global default or deterministic layout for existing configurations. Keep auto, its, and bare v2m backward compatible and reject zero, duplicate, malformed, or unknown options. --- openvmm/openvmm_entry/src/cli_args.rs | 81 ++++++++++++++++++++++++++- openvmm/openvmm_entry/src/lib.rs | 8 +-- 2 files changed, 79 insertions(+), 10 deletions(-) diff --git a/openvmm/openvmm_entry/src/cli_args.rs b/openvmm/openvmm_entry/src/cli_args.rs index ae9d91bf6e8..0895d8b53da 100644 --- a/openvmm/openvmm_entry/src/cli_args.rs +++ b/openvmm/openvmm_entry/src/cli_args.rs @@ -612,7 +612,7 @@ options: #[clap(long, default_value = "auto", value_parser = parse_x2apic)] pub x2apic: X2ApicConfig, - /// configure PCIe MSI controller for aarch64 (auto | its | v2m) + /// configure PCIe MSI controller for aarch64 (auto | its | v2m[,spi_count=N]) #[cfg(guest_arch = "aarch64")] #[clap(long, default_value = "auto")] pub gic_msi: GicMsiCli, @@ -2824,7 +2824,7 @@ pub enum Vtl0LateMapPolicyCli { } /// PCIe MSI controller selection for aarch64. -#[derive(Debug, Copy, Clone, Default, ValueEnum)] +#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)] pub enum GicMsiCli { /// Use ITS when available, fall back to GICv2m. #[default] @@ -2832,7 +2832,52 @@ pub enum GicMsiCli { /// Force GICv3 ITS (LPI-based MSIs). Its, /// Force GICv2m (SPI-based MSIs). - V2m, + V2m { + /// Number of SPIs reserved for MSI delivery. + spi_count: Option, + }, +} + +impl FromStr for GicMsiCli { + type Err = anyhow::Error; + + fn from_str(value: &str) -> Result { + match value { + "auto" => return Ok(Self::Auto), + "its" => return Ok(Self::Its), + "v2m" => return Ok(Self::V2m { spi_count: None }), + _ => {} + } + + let options = value + .strip_prefix("v2m,") + .context("expected auto, its, v2m, or v2m,spi_count=N")?; + let mut spi_count = None; + for option in options.split(',') { + let count = option + .strip_prefix("spi_count=") + .context("expected v2m,spi_count=N")? + .parse::() + .context("spi_count must be a positive integer")?; + anyhow::ensure!(count != 0, "spi_count must be a positive integer"); + anyhow::ensure!( + spi_count.replace(count).is_none(), + "duplicate spi_count option" + ); + } + + Ok(Self::V2m { spi_count }) + } +} + +impl GicMsiCli { + pub fn into_config(self) -> openvmm_defs::config::GicMsiConfig { + match self { + Self::Auto => openvmm_defs::config::GicMsiConfig::Auto, + Self::Its => openvmm_defs::config::GicMsiConfig::Its, + Self::V2m { spi_count } => openvmm_defs::config::GicMsiConfig::V2m { spi_count }, + } + } } #[derive(Debug, Copy, Clone, ValueEnum)] @@ -4964,6 +5009,36 @@ mod tests { ); } + #[test] + fn test_gic_msi_cli_from_str() { + assert_eq!(GicMsiCli::from_str("auto").unwrap(), GicMsiCli::Auto); + assert_eq!(GicMsiCli::from_str("its").unwrap(), GicMsiCli::Its); + assert_eq!( + GicMsiCli::from_str("v2m").unwrap(), + GicMsiCli::V2m { spi_count: None } + ); + assert_eq!( + GicMsiCli::from_str("v2m,spi_count=512").unwrap(), + GicMsiCli::V2m { + spi_count: Some(512) + } + ); + assert!(matches!( + GicMsiCli::from_str("v2m,spi_count=512") + .unwrap() + .into_config(), + openvmm_defs::config::GicMsiConfig::V2m { + spi_count: Some(512) + } + )); + + assert!(GicMsiCli::from_str("v2m,spi_count=0").is_err()); + assert!(GicMsiCli::from_str("v2m,spi_count=abc").is_err()); + assert!(GicMsiCli::from_str("v2m,spi_count=64,spi_count=512").is_err()); + assert!(GicMsiCli::from_str("v2m,unknown=512").is_err()); + assert!(GicMsiCli::from_str("other").is_err()); + } + #[test] fn test_memory_options_allow_legacy_thp_with_new_private_memory() { let opt = Options::try_parse_from(["openvmm", "--memory", "shared=off", "--thp"]).unwrap(); diff --git a/openvmm/openvmm_entry/src/lib.rs b/openvmm/openvmm_entry/src/lib.rs index 3567e8d29a7..1ffb5a4738e 100644 --- a/openvmm/openvmm_entry/src/lib.rs +++ b/openvmm/openvmm_entry/src/lib.rs @@ -1638,13 +1638,7 @@ async fn vm_config_from_command_line( // TODO: allow this to be configured from the command line gic_config: None, pmu_gsiv: openvmm_defs::config::PmuGsivConfig::Platform, - gic_msi: match opt.gic_msi { - cli_args::GicMsiCli::Auto => openvmm_defs::config::GicMsiConfig::Auto, - cli_args::GicMsiCli::Its => openvmm_defs::config::GicMsiConfig::Its, - cli_args::GicMsiCli::V2m => { - openvmm_defs::config::GicMsiConfig::V2m { spi_count: None } - } - }, + gic_msi: opt.gic_msi.into_config(), }, ); #[cfg(guest_arch = "x86_64")] From 9b0c32680b44bb927f27348cdce2d04616a3219a Mon Sep 17 00:00:00 2001 From: Henry Li Date: Wed, 2 Sep 2026 22:19:58 -0700 Subject: [PATCH 2/3] openvmm: gate GIC MSI CLI to aarch64 guests The GIC MSI option and its production call site are ARM64-only. Gate the CLI type, implementations, and parser test with the same guest architecture cfg so x64 clippy and documentation builds do not report dead code. --- openvmm/openvmm_entry/src/cli_args.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openvmm/openvmm_entry/src/cli_args.rs b/openvmm/openvmm_entry/src/cli_args.rs index 0895d8b53da..c81215dfb7b 100644 --- a/openvmm/openvmm_entry/src/cli_args.rs +++ b/openvmm/openvmm_entry/src/cli_args.rs @@ -2824,6 +2824,7 @@ pub enum Vtl0LateMapPolicyCli { } /// PCIe MSI controller selection for aarch64. +#[cfg(guest_arch = "aarch64")] #[derive(Debug, Copy, Clone, Default, PartialEq, Eq)] pub enum GicMsiCli { /// Use ITS when available, fall back to GICv2m. @@ -2838,6 +2839,7 @@ pub enum GicMsiCli { }, } +#[cfg(guest_arch = "aarch64")] impl FromStr for GicMsiCli { type Err = anyhow::Error; @@ -2870,6 +2872,7 @@ impl FromStr for GicMsiCli { } } +#[cfg(guest_arch = "aarch64")] impl GicMsiCli { pub fn into_config(self) -> openvmm_defs::config::GicMsiConfig { match self { @@ -5009,6 +5012,7 @@ mod tests { ); } + #[cfg(guest_arch = "aarch64")] #[test] fn test_gic_msi_cli_from_str() { assert_eq!(GicMsiCli::from_str("auto").unwrap(), GicMsiCli::Auto); From 2c4b315dedbc832816dfb680100b3fb78e7f7cbf Mon Sep 17 00:00:00 2001 From: Henry Li Date: Wed, 2 Sep 2026 23:15:27 -0700 Subject: [PATCH 3/3] ci: retry unrelated x64 VMM test failures