Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 82 additions & 3 deletions openvmm/openvmm_entry/src/cli_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -2824,15 +2824,63 @@ pub enum Vtl0LateMapPolicyCli {
}

/// PCIe MSI controller selection for aarch64.
#[derive(Debug, Copy, Clone, Default, ValueEnum)]
#[cfg(guest_arch = "aarch64")]
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
pub enum GicMsiCli {
/// Use ITS when available, fall back to GICv2m.
#[default]
Auto,
/// Force GICv3 ITS (LPI-based MSIs).
Its,
/// Force GICv2m (SPI-based MSIs).
V2m,
V2m {
/// Number of SPIs reserved for MSI delivery.
spi_count: Option<u32>,
},
}

#[cfg(guest_arch = "aarch64")]
impl FromStr for GicMsiCli {
type Err = anyhow::Error;

fn from_str(value: &str) -> Result<Self, Self::Err> {
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::<u32>()
.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 })
}
}

#[cfg(guest_arch = "aarch64")]
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)]
Expand Down Expand Up @@ -4964,6 +5012,37 @@ mod tests {
);
}

#[cfg(guest_arch = "aarch64")]
#[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();
Expand Down
8 changes: 1 addition & 7 deletions openvmm/openvmm_entry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down
Loading