From dd468710dc1221436606cec4cbacfb6de17b2a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dav=C3=AD=C3=B0=20Steinn=20Geirsson?= Date: Wed, 18 Mar 2026 16:36:45 +0000 Subject: [PATCH] vhost-user: encode shmem region IDs as array indices VhostUserShMemConfig::new() previously accepted a dense slice of sizes, with region IDs implicitly assigned 0..N. Change it to accept (id, size) pairs and store each size at memory_sizes[id], leaving absent regions as zero. This makes the encoding match crosvm's vmm_vhost, where region IDs are arbitrary u8 values (e.g. VIRTIO_GPU_SHM_ID_HOST_VISIBLE = 1) rather than always starting at zero. Co-Authored-By: Claude Sonnet 4.6 --- vhost/src/vhost_user/backend_req_handler.rs | 13 ++++++------- vhost/src/vhost_user/frontend.rs | 2 +- vhost/src/vhost_user/message.rs | 17 ++++++++++++----- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/vhost/src/vhost_user/backend_req_handler.rs b/vhost/src/vhost_user/backend_req_handler.rs index e857e60..7a59435 100644 --- a/vhost/src/vhost_user/backend_req_handler.rs +++ b/vhost/src/vhost_user/backend_req_handler.rs @@ -1079,10 +1079,10 @@ mod tests { #[test] fn test_get_shmem_config_multiple_regions() { - let memory_sizes = [ - 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000, - ]; - let config = VhostUserShMemConfig::new(8, &memory_sizes); + let config = VhostUserShMemConfig::new(&[ + (0, 0x1000), (1, 0x2000), (2, 0x3000), (3, 0x4000), + (4, 0x5000), (5, 0x6000), (6, 0x7000), (7, 0x8000), + ]); let (p1, p2) = UnixStream::pair().unwrap(); let mut dummy_backend = DummyBackendReqHandler::new(); @@ -1109,9 +1109,8 @@ mod tests { #[test] fn test_get_shmem_config_non_continuous_regions() { - // Create a configuration with non-continuous regions - let memory_sizes = [0x10000, 0, 0x20000, 0, 0, 0, 0, 0]; - let config = VhostUserShMemConfig::new(2, &memory_sizes); + // Create a configuration with non-contiguous region IDs (0 and 2, skipping 1) + let config = VhostUserShMemConfig::new(&[(0, 0x10000), (2, 0x20000)]); let (p1, p2) = UnixStream::pair().unwrap(); let mut dummy_backend = DummyBackendReqHandler::new(); diff --git a/vhost/src/vhost_user/frontend.rs b/vhost/src/vhost_user/frontend.rs index 13c4dd9..815928e 100644 --- a/vhost/src/vhost_user/frontend.rs +++ b/vhost/src/vhost_user/frontend.rs @@ -1220,7 +1220,7 @@ mod tests { fn test_frontend_get_shmem_config() { let (mut frontend, mut peer) = create_pair2(); - let expected_config = VhostUserShMemConfig::new(2, &[0x1000, 0x2000]); + let expected_config = VhostUserShMemConfig::new(&[(0, 0x1000), (1, 0x2000)]); let hdr = VhostUserMsgHeader::new( FrontendReq::GET_SHMEM_CONFIG, 0x4, diff --git a/vhost/src/vhost_user/message.rs b/vhost/src/vhost_user/message.rs index 88dbcaf..0d98409 100644 --- a/vhost/src/vhost_user/message.rs +++ b/vhost/src/vhost_user/message.rs @@ -700,7 +700,8 @@ pub struct VhostUserShMemConfig { pub nregions: u32, /// Padding for correct alignment padding: u32, - /// Size of each memory region + /// Size of each memory region, indexed by region ID. + /// A zero entry means the region with that ID is absent. pub memory_sizes: [u64; 256], } @@ -715,11 +716,17 @@ impl Default for VhostUserShMemConfig { } impl VhostUserShMemConfig { - /// Create a new instance - pub fn new(nregions: u32, memory: &[u64]) -> Self { - let memory_sizes: [u64; 256] = std::array::from_fn(|i| *memory.get(i).unwrap_or(&0)); + /// Create a new instance from a list of `(id, size)` pairs. + /// + /// Region IDs do not need to be contiguous. Each ID is used directly as an + /// index into the internal array, leaving absent regions as zero. + pub fn new(regions: &[(u8, u64)]) -> Self { + let mut memory_sizes = [0u64; 256]; + for &(id, size) in regions { + memory_sizes[usize::from(id)] = size; + } Self { - nregions, + nregions: regions.len() as u32, padding: 0, memory_sizes, }