Refactor VM config to support different CPU topologies
This is preliminary work to support crosvm's --host-cpu-topology (WIP),
which will make it possible to mirror host's CPU topology in the guest.
As a first step, we refactor AVF's system API to stop accepting number
of vCPUs as an argument, but instead only expose two topology configs:
1 vCPU (default) and matching the host's CPU topology.
For the time being, the latter results in crosvm started with `--cpu
<nproc>`.
Bug: 266664564
Test: atest -p packages/modules/Virtualization:avf-presubmit
Change-Id: I03a37be0b68b93dc0fa6e84fd51ca3bdefbe6dde
diff --git a/vm/src/main.rs b/vm/src/main.rs
index ea744f7..e1c3413 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -19,8 +19,8 @@
mod run;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
- IVirtualizationService::IVirtualizationService, PartitionType::PartitionType,
- VirtualMachineAppConfig::DebugLevel::DebugLevel,
+ CpuTopology::CpuTopology, IVirtualizationService::IVirtualizationService,
+ PartitionType::PartitionType, VirtualMachineAppConfig::DebugLevel::DebugLevel,
};
use anyhow::{Context, Error};
use binder::ProcessState;
@@ -91,9 +91,9 @@
#[clap(short, long)]
mem: Option<u32>,
- /// Number of vCPUs in the VM. If unspecified, defaults to 1.
- #[clap(long)]
- cpus: Option<u32>,
+ /// Run VM with vCPU topology matching that of the host. If unspecified, defaults to 1 vCPU.
+ #[clap(long, default_value = "one_cpu", value_parser = parse_cpu_topology)]
+ cpu_topology: CpuTopology,
/// Comma separated list of task profile names to apply to the VM
#[clap(long)]
@@ -146,9 +146,9 @@
#[clap(short, long)]
mem: Option<u32>,
- /// Number of vCPUs in the VM. If unspecified, defaults to 1.
- #[clap(long)]
- cpus: Option<u32>,
+ /// Run VM with vCPU topology matching that of the host. If unspecified, defaults to 1 vCPU.
+ #[clap(long, default_value = "one_cpu", value_parser = parse_cpu_topology)]
+ cpu_topology: CpuTopology,
/// Comma separated list of task profile names to apply to the VM
#[clap(long)]
@@ -163,9 +163,9 @@
#[clap(long)]
name: Option<String>,
- /// Number of vCPUs in the VM. If unspecified, defaults to 1.
- #[clap(long)]
- cpus: Option<u32>,
+ /// Run VM with vCPU topology matching that of the host. If unspecified, defaults to 1 vCPU.
+ #[clap(long, default_value = "one_cpu", value_parser = parse_cpu_topology)]
+ cpu_topology: CpuTopology,
/// Comma separated list of task profile names to apply to the VM
#[clap(long)]
@@ -222,6 +222,14 @@
}
}
+fn parse_cpu_topology(s: &str) -> Result<CpuTopology, String> {
+ match s {
+ "one_cpu" => Ok(CpuTopology::ONE_CPU),
+ "match_host" => Ok(CpuTopology::MATCH_HOST),
+ _ => Err(format!("Invalid cpu topology {}", s)),
+ }
+}
+
fn main() -> Result<(), Error> {
env_logger::init();
let opt = Opt::parse();
@@ -248,7 +256,7 @@
debug,
protected,
mem,
- cpus,
+ cpu_topology,
task_profiles,
extra_idsigs,
} => command_run_app(
@@ -266,7 +274,7 @@
debug,
protected,
mem,
- cpus,
+ cpu_topology,
task_profiles,
&extra_idsigs,
),
@@ -280,7 +288,7 @@
debug,
protected,
mem,
- cpus,
+ cpu_topology,
task_profiles,
} => command_run_microdroid(
name,
@@ -293,10 +301,10 @@
debug,
protected,
mem,
- cpus,
+ cpu_topology,
task_profiles,
),
- Opt::Run { name, config, cpus, task_profiles, console, log } => {
+ Opt::Run { name, config, cpu_topology, task_profiles, console, log } => {
command_run(
name,
service.as_ref(),
@@ -304,7 +312,7 @@
console.as_deref(),
log.as_deref(),
/* mem */ None,
- cpus,
+ cpu_topology,
task_profiles,
)
}
diff --git a/vm/src/run.rs b/vm/src/run.rs
index e229933..fa84591 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -16,6 +16,7 @@
use crate::create_partition::command_create_partition;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+ CpuTopology::CpuTopology,
IVirtualizationService::IVirtualizationService,
PartitionType::PartitionType,
VirtualMachineAppConfig::{DebugLevel::DebugLevel, Payload::Payload, VirtualMachineAppConfig},
@@ -54,7 +55,7 @@
debug_level: DebugLevel,
protected: bool,
mem: Option<u32>,
- cpus: Option<u32>,
+ cpu_topology: CpuTopology,
task_profiles: Vec<String>,
extra_idsigs: &[PathBuf],
) -> Result<(), Error> {
@@ -141,7 +142,7 @@
debugLevel: debug_level,
protectedVm: protected,
memoryMib: mem.unwrap_or(0) as i32, // 0 means use the VM default
- numCpus: cpus.unwrap_or(1) as i32,
+ cpuTopology: cpu_topology,
taskProfiles: task_profiles,
});
run(service, &config, &payload_config_str, console_path, log_path)
@@ -182,7 +183,7 @@
debug_level: DebugLevel,
protected: bool,
mem: Option<u32>,
- cpus: Option<u32>,
+ cpu_topology: CpuTopology,
task_profiles: Vec<String>,
) -> Result<(), Error> {
let apk = find_empty_payload_apk_path()?;
@@ -211,7 +212,7 @@
debug_level,
protected,
mem,
- cpus,
+ cpu_topology,
task_profiles,
&extra_sig,
)
@@ -226,7 +227,7 @@
console_path: Option<&Path>,
log_path: Option<&Path>,
mem: Option<u32>,
- cpus: Option<u32>,
+ cpu_topology: CpuTopology,
task_profiles: Vec<String>,
) -> Result<(), Error> {
let config_file = File::open(config_path).context("Failed to open config file")?;
@@ -235,14 +236,12 @@
if let Some(mem) = mem {
config.memoryMib = mem as i32;
}
- if let Some(cpus) = cpus {
- config.numCpus = cpus as i32;
- }
if let Some(name) = name {
config.name = name;
} else {
config.name = String::from("VmRun");
}
+ config.cpuTopology = cpu_topology;
config.taskProfiles = task_profiles;
run(
service,