Snap for 11973804 from b12ba3720cf1975ea57870a591cb7248fe276abd to 24Q3-release

Change-Id: I519f9a8c669805a42906f9bd2bd33c67eb78d468
diff --git a/src/crosvm/cmdline.rs b/src/crosvm/cmdline.rs
index f8afc55..8c182cf 100644
--- a/src/crosvm/cmdline.rs
+++ b/src/crosvm/cmdline.rs
@@ -1042,6 +1042,14 @@
     ///     pci-address=ADDR - Preferred PCI address, e.g. "00:01.0".
     block: Vec<DiskOptionWithId>,
 
+    #[cfg(any(target_os = "android", target_os = "linux"))]
+    #[argh(switch)]
+    #[serde(skip)]
+    #[merge(strategy = overwrite_option)]
+    /// set a minimum utilization for vCPU threads which will hint to the host scheduler
+    /// to ramp up higher frequencies or place vCPU threads on larger cores.
+    pub boost_uclamp: Option<bool>,
+
     #[cfg(target_arch = "x86_64")]
     #[argh(switch)]
     #[merge(strategy = overwrite_option)]
@@ -2696,6 +2704,7 @@
         #[cfg(any(target_os = "android", target_os = "linux"))]
         {
             cfg.lock_guest_memory = cmd.lock_guest_memory.unwrap_or_default();
+            cfg.boost_uclamp = cmd.boost_uclamp.unwrap_or_default();
         }
 
         #[cfg(feature = "audio")]
diff --git a/src/crosvm/config.rs b/src/crosvm/config.rs
index 6dc60c9..8caeda2 100644
--- a/src/crosvm/config.rs
+++ b/src/crosvm/config.rs
@@ -659,6 +659,8 @@
     pub block_control_tube: Vec<Tube>,
     #[cfg(windows)]
     pub block_vhost_user_tube: Vec<Tube>,
+    #[cfg(any(target_os = "android", target_os = "linux"))]
+    pub boost_uclamp: bool,
     pub boot_cpu: usize,
     #[cfg(target_arch = "x86_64")]
     pub break_linux_pci_config_io: bool,
@@ -947,6 +949,8 @@
             log_file: None,
             #[cfg(windows)]
             logs_directory: None,
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            boost_uclamp: false,
             memory: None,
             memory_file: None,
             mmio_address_ranges: Vec::new(),
diff --git a/src/crosvm/sys/linux.rs b/src/crosvm/sys/linux.rs
index 18caed8..38c7630 100644
--- a/src/crosvm/sys/linux.rs
+++ b/src/crosvm/sys/linux.rs
@@ -3527,6 +3527,7 @@
             #[cfg(target_arch = "x86_64")]
             bus_lock_ratelimit_ctrl,
             run_mode,
+            cfg.boost_uclamp,
         )?;
         vcpu_handles.push((handle, to_vcpu_channel));
     }
diff --git a/src/crosvm/sys/linux/vcpu.rs b/src/crosvm/sys/linux/vcpu.rs
index f5f25b7..5ae8835 100644
--- a/src/crosvm/sys/linux/vcpu.rs
+++ b/src/crosvm/sys/linux/vcpu.rs
@@ -24,6 +24,8 @@
 use arch::VcpuArch;
 use arch::VcpuInitArch;
 use arch::VmArch;
+use base::sched_attr;
+use base::sched_setattr;
 use base::signal::clear_signal_handler;
 use base::signal::BlockedSignal;
 use base::*;
@@ -49,6 +51,15 @@
 #[cfg(target_arch = "x86_64")]
 use crate::crosvm::ratelimit::Ratelimit;
 
+// TODO(davidai): Import libc constant when updated
+const SCHED_FLAG_RESET_ON_FORK: u64 = 0x1;
+const SCHED_FLAG_KEEP_POLICY: u64 = 0x08;
+const SCHED_FLAG_KEEP_PARAMS: u64 = 0x10;
+const SCHED_FLAG_UTIL_CLAMP_MIN: u64 = 0x20;
+const SCHED_SCALE_CAPACITY: u32 = 1024;
+
+const SCHED_FLAG_KEEP_ALL: u64 = SCHED_FLAG_KEEP_POLICY | SCHED_FLAG_KEEP_PARAMS;
+
 fn bus_io_handler(bus: &Bus) -> impl FnMut(IoParams) -> Option<[u8; 8]> + '_ {
     |IoParams {
          address,
@@ -86,6 +97,7 @@
     enable_per_vm_core_scheduling: bool,
     vcpu_cgroup_tasks_file: Option<File>,
     run_rt: bool,
+    boost_uclamp: bool,
 ) -> anyhow::Result<()> {
     if !vcpu_affinity.is_empty() {
         if let Err(e) = set_cpu_affinity(vcpu_affinity) {
@@ -93,6 +105,18 @@
         }
     }
 
+    if boost_uclamp {
+        let mut sched_attr = sched_attr::default();
+        sched_attr.sched_flags = SCHED_FLAG_KEEP_ALL
+            | SCHED_FLAG_UTIL_CLAMP_MIN
+            | SCHED_FLAG_RESET_ON_FORK;
+        sched_attr.sched_util_min = SCHED_SCALE_CAPACITY;
+
+        if let Err(e) = sched_setattr(0, &mut sched_attr, 0) {
+            warn!("Failed to boost vcpu util: {}", e);
+        }
+    }
+
     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() {
@@ -490,6 +514,7 @@
     vcpu_cgroup_tasks_file: Option<File>,
     #[cfg(target_arch = "x86_64")] bus_lock_ratelimit_ctrl: Arc<Mutex<Ratelimit>>,
     run_mode: VmRunMode,
+    boost_uclamp: bool,
 ) -> Result<JoinHandle<()>>
 where
     V: VcpuArch + 'static,
@@ -507,6 +532,7 @@
                     enable_per_vm_core_scheduling,
                     vcpu_cgroup_tasks_file,
                     run_rt && !delay_rt,
+                    boost_uclamp,
                 ) {
                     error!("vcpu thread setup failed: {:#}", e);
                     return ExitState::Stop;