diff --git a/src/crosvm.rs b/src/crosvm.rs index 78dbdc6b0d..dc6e78de3a 100644 --- a/src/crosvm.rs +++ b/src/crosvm.rs @@ -302,6 +302,7 @@ pub struct Config { pub vcpu_affinity: Option, pub cpu_clusters: Vec>, pub cpu_capacity: BTreeMap, // CPU index -> capacity + pub per_vm_core_scheduling: bool, #[cfg(feature = "audio_cras")] pub cras_snd: Option, pub delay_rt: bool, @@ -390,6 +391,7 @@ impl Default for Config { vcpu_affinity: None, cpu_clusters: Vec::new(), cpu_capacity: BTreeMap::new(), + per_vm_core_scheduling: false, #[cfg(feature = "audio_cras")] cras_snd: None, delay_rt: false, diff --git a/src/linux.rs b/src/linux.rs index c5554827f4..adedad5e60 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -1826,6 +1826,7 @@ fn runnable_vcpu( no_smt: bool, has_bios: bool, use_hypervisor_signals: bool, + enable_per_vm_core_scheduling: bool, ) -> Result<(V, VcpuRunHandle)> where V: VcpuArch, @@ -1868,8 +1869,11 @@ where ) .map_err(Error::ConfigureVcpu)?; - if let Err(e) = enable_core_scheduling() { - error!("Failed to enable core scheduling: {}", e); + if !enable_per_vm_core_scheduling { + // Do per-vCPU core scheduling by setting a unique cookie to each vCPU. + if let Err(e) = enable_core_scheduling() { + error!("Failed to enable core scheduling: {}", e); + } } if run_rt { @@ -1991,6 +1995,7 @@ fn run_vcpu( #[cfg(all(target_arch = "x86_64", feature = "gdb"))] to_gdb_tube: Option< mpsc::Sender, >, + enable_per_vm_core_scheduling: bool, ) -> Result> where V: VcpuArch + 'static, @@ -2015,6 +2020,7 @@ where no_smt, has_bios, use_hypervisor_signals, + enable_per_vm_core_scheduling, ); start_barrier.wait(); @@ -2654,6 +2660,7 @@ where cfg.sandbox, Arc::clone(&map_request), gralloc, + cfg.per_vm_core_scheduling, ) } @@ -2746,6 +2753,7 @@ fn run_control( sandbox: bool, map_request: Arc>>, mut gralloc: RutabagaGralloc, + enable_per_vm_core_scheduling: bool, ) -> Result<()> { #[derive(PollToken)] enum Token { @@ -2816,6 +2824,15 @@ fn run_control( Some(vec) => vec.into_iter().map(Some).collect(), None => iter::repeat_with(|| None).take(linux.vcpu_count).collect(), }; + // Enable core scheduling before creating vCPUs so that the cookie will be + // shared by all vCPU threads. + // TODO(b/199312402): Avoid enabling core scheduling for the crosvm process + // itself for even better performance. Only vCPUs need the feature. + if enable_per_vm_core_scheduling { + if let Err(e) = enable_core_scheduling() { + error!("Failed to enable core scheduling: {}", e); + } + } for (cpu_id, vcpu) in vcpus.into_iter().enumerate() { let (to_vcpu_channel, from_main_channel) = mpsc::channel(); let vcpu_affinity = match linux.vcpu_affinity.clone() { @@ -2843,6 +2860,7 @@ fn run_control( use_hypervisor_signals, #[cfg(all(target_arch = "x86_64", feature = "gdb"))] to_gdb_channel.clone(), + enable_per_vm_core_scheduling, )?; vcpu_handles.push((handle, to_vcpu_channel)); } diff --git a/src/main.rs b/src/main.rs index 24ec73bdad..38b081ed6c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -978,6 +978,9 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: "cpu-capacity" => { parse_cpu_capacity(value.unwrap(), &mut cfg.cpu_capacity)?; } + "per-vm-core-scheduling" => { + cfg.per_vm_core_scheduling = true; + } #[cfg(feature = "audio_cras")] "cras-snd" => { cfg.cras_snd = Some( @@ -2041,6 +2044,9 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> { or colon-separated list of assignments of guest to host CPU assignments (e.g. 0=0:1=1:2=2) (default: no mask)"), Argument::value("cpu-cluster", "CPUSET", "Group the given CPUs into a cluster (default: no clusters)"), Argument::value("cpu-capacity", "CPU=CAP[,CPU=CAP[,...]]", "Set the relative capacity of the given CPU (default: no capacity)"), + Argument::flag("per-vm-core-scheduling", "Enable per-VM core scheduling intead of the default one (per-vCPU core scheduing) by + making all vCPU threads share same cookie for core scheduling. + This option is no-op on devices that have neither MDS nor L1TF vulnerability."), #[cfg(feature = "audio_cras")] Argument::value("cras-snd", "[capture=true,client=crosvm,socket=unified]",