mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2025-12-28 08:01:04 +00:00
scsi: Advertise support for CONFIG
The config that we send is based on the current QEMU defaults (as of 60ca584b8af0de525656f959991a440f8c191f12). This allows testing using Alex Bennee's vhost-user-generic series and will be required for hypervisors that do not come with the stubs that QEMU has (eg: Xen). Signed-off-by: Erik Schilling <erik.schilling@linaro.org> Link: https://lore.kernel.org/all/20230414160433.2096866-1-alex.bennee@linaro.org/
This commit is contained in:
parent
ad82d45928
commit
4c8a2bc3ac
@ -1,11 +1,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use core::slice;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::io::{self, ErrorKind};
|
||||
use std::mem;
|
||||
|
||||
use log::{debug, error, info, warn};
|
||||
use vhost::vhost_user::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
||||
use vhost_user_backend::{VhostUserBackendMut, VringRwLock, VringT};
|
||||
use virtio_bindings::virtio_scsi::{virtio_scsi_config, virtio_scsi_event};
|
||||
use virtio_bindings::{
|
||||
virtio_config::VIRTIO_F_VERSION_1,
|
||||
virtio_ring::{VIRTIO_RING_F_EVENT_IDX, VIRTIO_RING_F_INDIRECT_DESC},
|
||||
@ -19,6 +22,7 @@ use vmm_sys_util::{
|
||||
};
|
||||
|
||||
use crate::scsi::Target;
|
||||
use crate::virtio::CDB_SIZE;
|
||||
use crate::{
|
||||
scsi::{self, CmdError, TaskAttr},
|
||||
virtio::{self, Request, RequestParseError, Response, ResponseCode, VirtioScsiLun, SENSE_SIZE},
|
||||
@ -211,7 +215,7 @@ impl VhostUserBackendMut<VringRwLock> for VhostUserScsiBackend {
|
||||
}
|
||||
|
||||
fn protocol_features(&self) -> VhostUserProtocolFeatures {
|
||||
VhostUserProtocolFeatures::MQ
|
||||
VhostUserProtocolFeatures::MQ | VhostUserProtocolFeatures::CONFIG
|
||||
}
|
||||
|
||||
fn set_event_idx(&mut self, enabled: bool) {
|
||||
@ -267,9 +271,38 @@ impl VhostUserBackendMut<VringRwLock> for VhostUserScsiBackend {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn get_config(&self, _offset: u32, _size: u32) -> Vec<u8> {
|
||||
// QEMU handles config space itself
|
||||
panic!("Access to configuration space is not supported.");
|
||||
fn get_config(&self, offset: u32, size: u32) -> Vec<u8> {
|
||||
let config = virtio_scsi_config {
|
||||
num_queues: 1,
|
||||
seg_max: 128 - 2,
|
||||
max_sectors: 0xFFFF,
|
||||
cmd_per_lun: 128,
|
||||
event_info_size: mem::size_of::<virtio_scsi_event>()
|
||||
.try_into()
|
||||
.expect("event info size should fit 32bit"),
|
||||
sense_size: SENSE_SIZE.try_into().expect("SENSE_SIZE should fit 32bit"),
|
||||
cdb_size: CDB_SIZE.try_into().expect("CDB_SIZE should fit 32bit"),
|
||||
max_channel: 0,
|
||||
max_target: 255,
|
||||
max_lun: u32::from(!u16::from(VirtioScsiLun::ADDRESS_METHOD_PATTERN) << 8 | 0xff),
|
||||
};
|
||||
|
||||
// SAFETY:
|
||||
// Pointer is aligned (points to start of struct), valid and we only
|
||||
// access up to the size of the struct.
|
||||
let config_slice = unsafe {
|
||||
slice::from_raw_parts(
|
||||
&config as *const virtio_scsi_config as *const u8,
|
||||
mem::size_of::<virtio_scsi_config>(),
|
||||
)
|
||||
};
|
||||
|
||||
config_slice
|
||||
.iter()
|
||||
.skip(offset as usize)
|
||||
.take(size as usize)
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn set_config(&mut self, _offset: u32, _buf: &[u8]) -> std::result::Result<(), std::io::Error> {
|
||||
@ -294,7 +327,8 @@ mod tests {
|
||||
use virtio_bindings::{
|
||||
virtio_ring::VRING_DESC_F_WRITE,
|
||||
virtio_scsi::{
|
||||
virtio_scsi_cmd_req, VIRTIO_SCSI_S_BAD_TARGET, VIRTIO_SCSI_S_FAILURE, VIRTIO_SCSI_S_OK,
|
||||
virtio_scsi_cmd_req, virtio_scsi_config, VIRTIO_SCSI_S_BAD_TARGET,
|
||||
VIRTIO_SCSI_S_FAILURE, VIRTIO_SCSI_S_OK,
|
||||
},
|
||||
};
|
||||
use virtio_queue::{mock::MockSplitQueue, Descriptor};
|
||||
@ -565,4 +599,23 @@ mod tests {
|
||||
"expect no command to make it to the target"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reading_config() {
|
||||
let backend = VhostUserScsiBackend::new();
|
||||
|
||||
// 0 len slice
|
||||
assert_eq!(vec![0_u8; 0], backend.get_config(0, 0));
|
||||
// overly long slice
|
||||
assert_eq!(
|
||||
std::mem::size_of::<virtio_scsi_config>(),
|
||||
backend.get_config(0, 2000).len()
|
||||
);
|
||||
// subslice
|
||||
assert_eq!(1, backend.get_config(4, 1).len());
|
||||
// overly long subslice
|
||||
assert_eq!(28, backend.get_config(8, 10000).len());
|
||||
// offset after end
|
||||
assert_eq!(0, backend.get_config(100000, 10).len());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user