aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA. Cody Schuffelen <schuffelen@google.com>2023-06-08 17:42:11 -0700
committerA. Cody Schuffelen <schuffelen@google.com>2023-06-13 17:17:10 -0700
commit357d715047110d1fbcbeabf29bdc95ecbfd83ce4 (patch)
tree4649f2a0f679bb72f75e5e36c4ca11cb98061a89
parentdddf3b4863ac285fdfa5d1c9e1269cee97c9644a (diff)
downloadcrosvm-357d715047110d1fbcbeabf29bdc95ecbfd83ce4.tar.gz
ANDROID: Add `--core-scheduling` flag gating interaction with PR_SCHED_CORE
On Android CI we observe performance regressions when crosvm takes advantage of the PR_SCHED_CORE feature. We are somewhat oversubscribed on CPUs, in some cases running a Cuttlefish Android VM with --cpus=4 and an OpenWRT VM with --cpus=1 next to some other host processes on cloud instances with 2 cores and 4 hyperthreads. In this case we would prefer not to lose cpu time to the scheduler blocking off hyperthreads when either VM claims complete cores to itself. In this case we are intending to fall back to the default state of "all processes trust each other", mentioned under "Trust model" on https://www.kernel.org/doc/html/next/admin-guide/hw-vuln/core-scheduling.html `--core-scheduling` defaults to true, so there is no behavioral change for existing users. Bug: b/280660768 Test: `crosvm start --core-scheduling=false` from Cuttlefish launcher script Change-Id: Id154790c16b7d9f81aff1f189468959fb5fa7259 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4602908 Reviewed-by: Frederick Mayle <fmayle@google.com> Reviewed-by: Dennis Kempin <denniskempin@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Commit-Queue: Cody Schuffelen <schuffelen@google.com> Merged-In: Id154790c16b7d9f81aff1f189468959fb5fa7259
-rw-r--r--src/crosvm/cmdline.rs12
-rw-r--r--src/crosvm/config.rs2
-rw-r--r--src/crosvm/sys/unix.rs3
-rw-r--r--src/crosvm/sys/unix/vcpu.rs5
4 files changed, 20 insertions, 2 deletions
diff --git a/src/crosvm/cmdline.rs b/src/crosvm/cmdline.rs
index 6c017ab6e..da8c2e00e 100644
--- a/src/crosvm/cmdline.rs
+++ b/src/crosvm/cmdline.rs
@@ -717,6 +717,10 @@ fn overwrite<T>(left: &mut T, right: T) {
let _ = std::mem::replace(left, right);
}
+fn bool_default_true() -> bool {
+ true
+}
+
/// Each field of this structure has a dual use:
///
/// 1) As a command-line parameter, controlled by the `#[argh]` helper attribute.
@@ -927,6 +931,13 @@ pub struct RunCommand {
/// older which is less frequently checked generation.
pub coiommu: Option<devices::CoIommuParameters>,
+ #[argh(option, default = "true")]
+ #[merge(strategy = overwrite)]
+ #[serde(default = "bool_default_true")]
+ /// protect VM threads from hyperthreading-based attacks by scheduling them on different cores.
+ /// Enabled by default, and required for per_vm_core_scheduling.
+ pub core_scheduling: bool,
+
#[argh(option, arg_name = "CPUSET", from_str_fn(parse_cpu_affinity))]
#[serde(skip)] // TODO(b/255223604)
#[merge(strategy = overwrite_option)]
@@ -2301,6 +2312,7 @@ impl TryFrom<RunCommand> for super::config::Config {
cfg.params.extend(cmd.params);
+ cfg.core_scheduling = cmd.core_scheduling;
cfg.per_vm_core_scheduling = cmd.per_vm_core_scheduling;
// `--cpu` parameters.
diff --git a/src/crosvm/config.rs b/src/crosvm/config.rs
index 28472f100..b2266b161 100644
--- a/src/crosvm/config.rs
+++ b/src/crosvm/config.rs
@@ -1003,6 +1003,7 @@ pub struct Config {
pub bus_lock_ratelimit: u64,
#[cfg(unix)]
pub coiommu_param: Option<devices::CoIommuParameters>,
+ pub core_scheduling: bool,
pub cpu_capacity: BTreeMap<usize, u32>, // CPU index -> capacity
pub cpu_clusters: Vec<CpuSet>,
#[cfg(feature = "crash-report")]
@@ -1214,6 +1215,7 @@ impl Default for Config {
bus_lock_ratelimit: 0,
#[cfg(unix)]
coiommu_param: None,
+ core_scheduling: true,
#[cfg(feature = "crash-report")]
crash_pipe_name: None,
#[cfg(feature = "crash-report")]
diff --git a/src/crosvm/sys/unix.rs b/src/crosvm/sys/unix.rs
index c00427b48..4b877a8ad 100644
--- a/src/crosvm/sys/unix.rs
+++ b/src/crosvm/sys/unix.rs
@@ -2680,7 +2680,7 @@ fn run_control<V: VmArch + 'static, Vcpu: VcpuArch + 'static>(
// 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 cfg.per_vm_core_scheduling {
+ if cfg.core_scheduling && cfg.per_vm_core_scheduling {
if let Err(e) = enable_core_scheduling() {
error!("Failed to enable core scheduling: {}", e);
}
@@ -2799,6 +2799,7 @@ fn run_control<V: VmArch + 'static, Vcpu: VcpuArch + 'static>(
use_hypervisor_signals,
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), feature = "gdb"))]
to_gdb_channel.clone(),
+ cfg.core_scheduling,
cfg.per_vm_core_scheduling,
cpu_config,
cfg.privileged_vm,
diff --git a/src/crosvm/sys/unix/vcpu.rs b/src/crosvm/sys/unix/vcpu.rs
index dff53911d..dc0099181 100644
--- a/src/crosvm/sys/unix/vcpu.rs
+++ b/src/crosvm/sys/unix/vcpu.rs
@@ -122,6 +122,7 @@ fn bus_io_handler(bus: &Bus) -> impl FnMut(IoParams) -> Option<[u8; 8]> + '_ {
/// This function will be called from each VCPU thread at startup.
pub fn set_vcpu_thread_scheduling(
vcpu_affinity: CpuSet,
+ core_scheduling: bool,
enable_per_vm_core_scheduling: bool,
vcpu_cgroup_tasks_file: Option<File>,
run_rt: bool,
@@ -132,7 +133,7 @@ pub fn set_vcpu_thread_scheduling(
}
}
- if !enable_per_vm_core_scheduling {
+ if core_scheduling && !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);
@@ -548,6 +549,7 @@ pub fn run_vcpu<V>(
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), feature = "gdb"))] to_gdb_tube: Option<
mpsc::Sender<VcpuDebugStatusMessage>,
>,
+ enable_core_scheduling: bool,
enable_per_vm_core_scheduling: bool,
cpu_config: Option<CpuConfigArch>,
privileged_vm: bool,
@@ -570,6 +572,7 @@ where
let vcpu_fn = || -> ExitState {
if let Err(e) = set_vcpu_thread_scheduling(
vcpu_affinity,
+ enable_core_scheduling,
enable_per_vm_core_scheduling,
vcpu_cgroup_tasks_file,
run_rt && !delay_rt,