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 { .. }
+ )
+ }
+}