Merge with upstream 2025-06-09

7a930a814e e2e: virtio: net: add e2e cases for virtio-net
5274caf47b e2e_tests: uprev guest under test
1458989b4c rutabaga_gfx: fix kumquat build

https://chromium.googlesource.com/crosvm/crosvm/+log/7083e31d219cdcd57866c70144e1b39ddc008f0f..7a930a814ee5e36bbfe5ba6957251891a4659e7a

BUG=420964652

Change-Id: I57b19447e0f16a7749eb18bafbc82aaf3870634e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/6631626
Bot-Commit: crosvm LUCI CI <crosvm-luci-ci-builder@crosvm-infra.iam.gserviceaccount.com>
Commit-Queue: Yuan Yao <yuanyaogoog@chromium.org>
diff --git a/OWNERS b/OWNERS
index 7a877f3..d0b875b 100644
--- a/OWNERS
+++ b/OWNERS
@@ -29,5 +29,6 @@
 crosvm-luci-ci-builder@crosvm-infra.iam.gserviceaccount.com #{LAST_RESORT_SUGGESTION}
 
 # Changes to Cargo.lock will require additional reviews by the crosvm council.
-per-file Cargo.lock = set noparent
-per-file Cargo.lock = file:OWNERS_COUNCIL
+# -- For chrome os branch, we don't need that extra approval.
+# per-file Cargo.lock = set noparent
+# per-file Cargo.lock = file:OWNERS_COUNCIL
diff --git a/base/src/sys/linux/sched.rs b/base/src/sys/linux/sched.rs
index 9f0e459..6aad98a 100644
--- a/base/src/sys/linux/sched.rs
+++ b/base/src/sys/linux/sched.rs
@@ -124,7 +124,7 @@
     }
 
     // SAFETY: Safe because we check the return value to prctl.
-    let ret = unsafe {
+    let ret = match unsafe {
         prctl(
             PR_SCHED_CORE,
             PR_SCHED_CORE_CREATE,
@@ -132,6 +132,14 @@
             pid_type::PIDTYPE_PID as i32, // PID scopes to this thread only
             0,                            // ignored by PR_SCHED_CORE_CREATE command
         )
+    } {
+        -1 => {
+            // Chrome OS has an pre-upstream version of this functionality which might work.
+            const PR_SET_CORE_SCHED: i32 = 0x200;
+            // SAFETY: Safe because we check the return value to prctl.
+            unsafe { prctl(PR_SET_CORE_SCHED, 1) }
+        }
+        ret => ret,
     };
     if ret == -1 {
         let error = Error::last();
diff --git a/common/audio_streams/Cargo.toml b/common/audio_streams/Cargo.toml
index a7f2210..cce7db7 100644
--- a/common/audio_streams/Cargo.toml
+++ b/common/audio_streams/Cargo.toml
@@ -9,7 +9,7 @@
 
 [dependencies]
 async-trait = "0.1.36"
-remain = { workspace = true }
-thiserror = { workspace = true }
+remain = "0.2"
+thiserror = "1.0.20"
 futures = "0.3"
-serde = { workspace = true, features = ["derive"] }
+serde = { version = "1.0", features = ["derive"] }
diff --git a/profiles/benchmarks.profdata.xz b/profiles/benchmarks.profdata.xz
new file mode 100644
index 0000000..3f417b4
--- /dev/null
+++ b/profiles/benchmarks.profdata.xz
Binary files differ
diff --git a/vendor/chromeos/metrics/Cargo.toml b/vendor/chromeos/metrics/Cargo.toml
new file mode 100644
index 0000000..48e271b
--- /dev/null
+++ b/vendor/chromeos/metrics/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "metrics_chromeos"
+version = "0.1.0"
+authors = ["The ChromiumOS Authors"]
+edition = "2021"
+
+[dependencies]
+anyhow = "*"
+base = { path = "../../../base" }
+metrics_events = { path = "../../../metrics_events" }
+metrics_rs = { version="0.1.0" }
+serde = { version = "1", features = ["derive"] }
+sync = { path = "../../../common/sync" }
+virtio_sys = { path = "../../../virtio_sys" }
diff --git a/vendor/chromeos/metrics/src/client.rs b/vendor/chromeos/metrics/src/client.rs
new file mode 100644
index 0000000..4539fb5
--- /dev/null
+++ b/vendor/chromeos/metrics/src/client.rs
@@ -0,0 +1,125 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use base::warn;
+use base::AsRawDescriptor;
+use base::RawDescriptor;
+use base::SendTube;
+use metrics_events::MetricEventType;
+use metrics_events::RecordDetails;
+use sync::Mutex;
+
+use crate::metrics_requests::MetricsRequest;
+use crate::MetricsClientDestructor;
+use crate::MetricsRequestHandler;
+
+/// Tube connected to the metrics controller.
+static CONTROLLER_TUBE: Mutex<Option<SendTube>> = Mutex::new(None);
+
+/// Sets the Tube where metrics are sent. Panics if called more than once.
+pub fn initialize(send_tube: SendTube) {
+    let mut tube = CONTROLLER_TUBE.lock();
+    if tube.is_some() {
+        // Technically we could replace tube; however:
+        // 1. this would EPIPE the other end.
+        // 2. this should never be done in production.
+        panic!("Attempt to initialize metrics client twice.");
+    }
+    *tube = Some(send_tube);
+}
+
+#[cfg(test)]
+pub fn force_initialize(send_tube: SendTube) {
+    // Safe because:
+    //      1. CLIENT_TUBE is guaranteed to be initialized.
+    //      2. Holding the lock prevents any other thread from accessing it.
+    let mut tube = CONTROLLER_TUBE.lock();
+    *tube = Some(send_tube);
+}
+
+pub fn push_descriptors(keep_rds: &mut Vec<RawDescriptor>) {
+    if let Some(tube) = CONTROLLER_TUBE.lock().as_ref() {
+        keep_rds.push(tube.as_raw_descriptor());
+    }
+}
+
+pub fn get_destructor() -> MetricsClientDestructor {
+    MetricsClientDestructor::new(|| {
+        // Let Tube close by going out of scope.
+        let _ = CONTROLLER_TUBE.lock().take();
+    })
+}
+
+/// Returns true if the metrics client is initialized.
+pub fn is_initialized() -> bool {
+    CONTROLLER_TUBE.lock().is_some()
+}
+
+pub fn set_auth_token(_: &str) {}
+pub fn set_graphics_api(_: &str) {}
+pub fn set_package_name(_: &str) {}
+pub fn merge_session_invariants(_: &[u8]) {}
+
+pub fn log_descriptor(event_code: MetricEventType, descriptor: i64) {
+    if MetricsRequestHandler::will_log_event(&event_code) {
+        send_request(MetricsRequest::Enum {
+            event_code,
+            sample: descriptor,
+        })
+    }
+}
+
+pub fn log_event(event_code: MetricEventType) {
+    if MetricsRequestHandler::will_log_event(&event_code) {
+        send_request(MetricsRequest::EventCount { event_code })
+    }
+}
+
+pub fn log_metric(event_code: MetricEventType, value: i64) {
+    if MetricsRequestHandler::will_log_event(&event_code) {
+        send_request(MetricsRequest::RegularHistogram {
+            event_code,
+            sample: value,
+        })
+    }
+}
+
+pub fn log_metric_with_details(event_code: MetricEventType, _: i64,  _: &RecordDetails) {
+    if MetricsRequestHandler::will_log_event(&event_code) {
+        unimplemented!()
+    }
+}
+
+pub fn log_histogram_metric(event_code: MetricEventType, value: i64) {
+    log_metric(event_code, value)
+}
+
+pub fn log_high_frequency_descriptor_event(event_code: MetricEventType, _: i64, _: i64) {
+    if MetricsRequestHandler::will_log_event(&event_code) {
+        unimplemented!()
+    }
+}
+
+pub fn log_event_with_details(event_code: MetricEventType, _: &RecordDetails) {
+    if MetricsRequestHandler::will_log_event(&event_code) {
+        unimplemented!()
+    }
+}
+
+/// Sends a metrics request to the server. Does nothing if the metrics client is not initialized.
+fn send_request(req: MetricsRequest) {
+    let controller_lock = CONTROLLER_TUBE.lock();
+    match controller_lock.as_ref() {
+        Some(controller_tube) => {
+            if let Err(e) = controller_tube.send(&req) {
+                warn!("Failed to send metrics to metrics controller: {}", e);
+            }
+        }
+        None => {
+            warn!(
+                "Failed to send metrics to metrics controller because no controller Tube was set."
+            );
+        }
+    }
+}
diff --git a/vendor/chromeos/metrics/src/lib.rs b/vendor/chromeos/metrics/src/lib.rs
new file mode 100644
index 0000000..525c091
--- /dev/null
+++ b/vendor/chromeos/metrics/src/lib.rs
@@ -0,0 +1,38 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Provides ChromeOS implementations of metrics interfaces that reports
+//! UMA metrics.
+
+mod client;
+mod metrics_requests;
+mod periodic_logger;
+mod request_handler;
+
+mod metrics_cleanup;
+
+use std::time::Duration;
+
+#[cfg(test)]
+pub use client::force_initialize;
+pub use client::get_destructor;
+pub use client::initialize;
+pub use client::is_initialized;
+pub use client::log_descriptor;
+pub use client::log_event;
+pub use client::log_event_with_details;
+pub use client::log_high_frequency_descriptor_event;
+pub use client::log_histogram_metric;
+pub use client::log_metric;
+pub use client::log_metric_with_details;
+pub use client::merge_session_invariants;
+pub use client::push_descriptors;
+pub use client::set_auth_token;
+pub use client::set_graphics_api;
+pub use client::set_package_name;
+pub use metrics_cleanup::MetricsClientDestructor;
+pub use periodic_logger::PeriodicLogger;
+pub use request_handler::MetricsRequestHandler;
+
+pub const METRICS_UPLOAD_INTERVAL: Duration = Duration::from_secs(60);
diff --git a/vendor/chromeos/metrics/src/metrics_cleanup.rs b/vendor/chromeos/metrics/src/metrics_cleanup.rs
new file mode 100644
index 0000000..9e9855b
--- /dev/null
+++ b/vendor/chromeos/metrics/src/metrics_cleanup.rs
@@ -0,0 +1,22 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Provides a tool for metrics client cleanup which may hold global state.
+
+/// Ensures any cleanup necessary is performed on drop. Can be used to ensure cleanup is done
+/// regardless of how the caller exits. Should be idempotent.
+pub struct MetricsClientDestructor(Box<dyn FnMut()>);
+impl MetricsClientDestructor {
+    pub fn new<T: 'static + FnMut()>(cleanup: T) -> Self {
+        MetricsClientDestructor(Box::new(cleanup))
+    }
+    /// A convenience method for immediately dropping self and invoking drop logic on the contained
+    /// object.
+    pub fn cleanup(self) {}
+}
+impl Drop for MetricsClientDestructor {
+    fn drop(&mut self) {
+        self.0();
+    }
+}
diff --git a/vendor/chromeos/metrics/src/metrics_requests.rs b/vendor/chromeos/metrics/src/metrics_requests.rs
new file mode 100644
index 0000000..238085c
--- /dev/null
+++ b/vendor/chromeos/metrics/src/metrics_requests.rs
@@ -0,0 +1,24 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Structs used to transport log requests between client processes and the logging controller
+
+use metrics_events::MetricEventType;
+use serde::Deserialize;
+use serde::Serialize;
+
+#[derive(Serialize, Deserialize, Debug)]
+pub enum MetricsRequest {
+    EventCount {
+        event_code: MetricEventType,
+    },
+    Enum {
+        event_code: MetricEventType,
+        sample: i64,
+    },
+    RegularHistogram {
+        event_code: MetricEventType,
+        sample: i64,
+    },
+}
diff --git a/vendor/chromeos/metrics/src/periodic_logger.rs b/vendor/chromeos/metrics/src/periodic_logger.rs
new file mode 100644
index 0000000..42dfc3f
--- /dev/null
+++ b/vendor/chromeos/metrics/src/periodic_logger.rs
@@ -0,0 +1,28 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use std::result::Result;
+use std::time::Duration;
+
+use metrics_events::MetricEventType;
+
+use crate::MetricsRequestHandler;
+
+/// A logging struct meant for use in tracking and periodically
+/// logging a single metric. The metric is aggregated over the
+/// designated time period. Intended for use with high-frequency metrics.
+pub struct PeriodicLogger;
+
+impl PeriodicLogger {
+    pub fn new(event_code: MetricEventType, _: Duration) -> Result<PeriodicLogger, String> {
+        if MetricsRequestHandler::will_log_event(&event_code) {
+            unimplemented!()
+        }
+        Ok(PeriodicLogger)
+    }
+
+    /// Indicate the event has occurred with the given
+    /// value to be aggregated over the given time period.
+    pub fn log(&self, _: i64) {}
+}
diff --git a/vendor/chromeos/metrics/src/request_handler.rs b/vendor/chromeos/metrics/src/request_handler.rs
new file mode 100644
index 0000000..6aee5cb
--- /dev/null
+++ b/vendor/chromeos/metrics/src/request_handler.rs
@@ -0,0 +1,105 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use base::error;
+use base::warn;
+use base::RecvTube;
+use metrics_events::MetricEventType;
+use metrics_rs::MetricsLibrary;
+use virtio_sys::virtio_ids;
+
+use crate::metrics_requests::MetricsRequest;
+
+#[derive(Default)]
+pub struct MetricsRequestHandler {
+    connected: bool,
+}
+
+const K_ONE_HOUR_MS: i32 = 60 * 60 * 1000;
+
+fn virtio_id_to_wakeup_metric(virtio_id: u32) -> &'static str {
+    match virtio_id {
+        virtio_ids::VIRTIO_ID_NET => "Arc.Wakeup.VirtioNet",
+        virtio_ids::VIRTIO_ID_BLOCK => "Arc.Wakeup.VirtioBlock",
+        virtio_ids::VIRTIO_ID_BALLOON => "Arc.Wakeup.VirtioBalloon",
+        virtio_ids::VIRTIO_ID_GPU => "Arc.Wakeup.VirtioGpu",
+        virtio_ids::VIRTIO_ID_VSOCK => "Arc.Wakeup.VirtioVsock",
+        virtio_ids::VIRTIO_ID_FS => "Arc.Wakeup.VirtioFs",
+        virtio_ids::VIRTIO_ID_WL => "Arc.Wakeup.VirtioWayland",
+        _ => "Arc.Wakeup.VirtioOther",
+    }
+}
+
+impl MetricsRequestHandler {
+    pub fn new() -> Self {
+        let connected = MetricsLibrary::get().is_some();
+        if !connected {
+            error!("Failed to initialize metrics library");
+        }
+
+        MetricsRequestHandler { connected }
+    }
+
+    pub fn handle_tube_readable(&self, tube: &RecvTube) {
+        if !self.connected {
+            return;
+        }
+
+        let req = match tube.recv::<MetricsRequest>() {
+            Ok(req) => req,
+            Err(e) => {
+                warn!("unexpected error receiving agent metrics request: {}", e);
+                return;
+            }
+        };
+
+        let metrics = MetricsLibrary::get().expect("metrics disappeared");
+        let mut metrics = metrics.lock().expect("poisioned lock");
+
+        let res = match req {
+            #[allow(unreachable_code, unused_variables, clippy::match_single_binding)]
+            MetricsRequest::Enum { event_code, sample } => {
+                let (name, max): (&str, i32) = match event_code {
+                    _ => return,
+                };
+                if sample > max as i64 {
+                    warn!("Enum value {} too large for {}", sample, name);
+                    return;
+                }
+                metrics.send_enum_to_uma(name, sample as i32, max)
+            }
+            #[allow(unreachable_code, unused_variables, clippy::match_single_binding)]
+            MetricsRequest::EventCount { event_code } => {
+                let name = match event_code {
+                    _ => return,
+                };
+                // See MetricsLibrary::SendBoolToUMA
+                metrics.send_enum_to_uma(name, 1, 2)
+            }
+            MetricsRequest::RegularHistogram { event_code, sample } => {
+                let (name, min, max, nbuckets) = match event_code {
+                    MetricEventType::RtcWakeup => ("Arc.Wakeup.RTC", 0, K_ONE_HOUR_MS, 50),
+                    MetricEventType::VirtioWakeup { virtio_id } => {
+                        (virtio_id_to_wakeup_metric(virtio_id), 0, K_ONE_HOUR_MS, 50)
+                    }
+                    _ => return,
+                };
+                let sample = sample.try_into().unwrap_or(i32::MAX);
+                metrics.send_to_uma(name, sample, min, max, nbuckets)
+            }
+        };
+        if let Err(err) = res {
+            error!("Failed to upload metrics: {:?}", err);
+        }
+    }
+
+    pub fn shutdown(&self) {}
+
+    pub fn will_log_event(event_code: &MetricEventType) -> bool {
+        matches!(
+            event_code,
+            MetricEventType::RtcWakeup | MetricEventType::VirtioWakeup { .. }
+        )
+    }
+}