1 // Copyright (C) 2021 Red Hat, Inc. All rights reserved.
2 // SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
3 
4 //! Trait to control vhost-vdpa backend drivers.
5 
6 use vmm_sys_util::eventfd::EventFd;
7 
8 use crate::backend::VhostBackend;
9 use crate::Result;
10 
11 /// vhost vdpa IOVA range
12 pub struct VhostVdpaIovaRange {
13     /// First address that can be mapped by vhost-vDPA.
14     pub first: u64,
15     /// Last address that can be mapped by vhost-vDPA.
16     pub last: u64,
17 }
18 
19 /// Trait to control vhost-vdpa backend drivers.
20 ///
21 /// vDPA (virtio Data Path Acceleration) devices has datapath compliant with the
22 /// virtio specification and the control path is vendor specific.
23 /// vDPA devices can be both physically located on the hardware or emulated
24 /// by software.
25 ///
26 /// Compared to vhost acceleration, vDPA offers more control over the device
27 /// lifecycle.
28 /// For this reason, the vhost-vdpa interface extends the vhost API, offering
29 /// additional APIs for controlling the device (e.g. changing the state or
30 /// accessing the configuration space
31 pub trait VhostVdpa: VhostBackend {
32     /// Get the device id.
33     /// The device ids follow the same definition of the device id defined in virtio-spec.
get_device_id(&self) -> Result<u32>34     fn get_device_id(&self) -> Result<u32>;
35 
36     /// Get the status.
37     /// The status bits follow the same definition of the device status defined in virtio-spec.
get_status(&self) -> Result<u8>38     fn get_status(&self) -> Result<u8>;
39 
40     /// Set the status.
41     /// The status bits follow the same definition of the device status defined in virtio-spec.
42     ///
43     /// # Arguments
44     /// * `status` - Status bits to set
set_status(&self, status: u8) -> Result<()>45     fn set_status(&self, status: u8) -> Result<()>;
46 
47     /// Get the device configuration.
48     ///
49     /// # Arguments
50     /// * `offset` - Offset in the device configuration space
51     /// * `buffer` - Buffer for configuration data
get_config(&self, offset: u32, buffer: &mut [u8]) -> Result<()>52     fn get_config(&self, offset: u32, buffer: &mut [u8]) -> Result<()>;
53 
54     /// Set the device configuration.
55     ///
56     /// # Arguments
57     /// * `offset` - Offset in the device configuration space
58     /// * `buffer` - Buffer for configuration data
set_config(&self, offset: u32, buffer: &[u8]) -> Result<()>59     fn set_config(&self, offset: u32, buffer: &[u8]) -> Result<()>;
60 
61     /// Set the status for a given vring.
62     ///
63     /// # Arguments
64     /// * `queue_index` - Index of the queue to enable/disable.
65     /// * `enabled` - true to enable the vring, false to disable it.
set_vring_enable(&self, queue_index: usize, enabled: bool) -> Result<()>66     fn set_vring_enable(&self, queue_index: usize, enabled: bool) -> Result<()>;
67 
68     /// Get the maximum number of descriptors in the vring supported by the device.
get_vring_num(&self) -> Result<u16>69     fn get_vring_num(&self) -> Result<u16>;
70 
71     /// Set the eventfd to trigger when device configuration change.
72     ///
73     /// # Arguments
74     /// * `fd` - EventFd to trigger.
set_config_call(&self, fd: &EventFd) -> Result<()>75     fn set_config_call(&self, fd: &EventFd) -> Result<()>;
76 
77     /// Get the valid I/O virtual addresses range supported by the device.
get_iova_range(&self) -> Result<VhostVdpaIovaRange>78     fn get_iova_range(&self) -> Result<VhostVdpaIovaRange>;
79 
80     /// Get the config size
get_config_size(&self) -> Result<u32>81     fn get_config_size(&self) -> Result<u32>;
82 
83     /// Get the count of all virtqueues
get_vqs_count(&self) -> Result<u32>84     fn get_vqs_count(&self) -> Result<u32>;
85 
86     /// Get the number of virtqueue groups
get_group_num(&self) -> Result<u32>87     fn get_group_num(&self) -> Result<u32>;
88 
89     /// Get the number of address spaces
get_as_num(&self) -> Result<u32>90     fn get_as_num(&self) -> Result<u32>;
91 
92     /// Get the group for a virtqueue.
93     /// The virtqueue index is stored in the index field of
94     /// vhost_vring_state. The group for this specific virtqueue is
95     /// returned via num field of vhost_vring_state.
get_vring_group(&self, queue_index: u32) -> Result<u32>96     fn get_vring_group(&self, queue_index: u32) -> Result<u32>;
97 
98     /// Set the ASID for a virtqueue group. The group index is stored in
99     /// the index field of vhost_vring_state, the ASID associated with this
100     /// group is stored at num field of vhost_vring_state.
set_group_asid(&self, group_index: u32, asid: u32) -> Result<()>101     fn set_group_asid(&self, group_index: u32, asid: u32) -> Result<()>;
102 
103     /// Suspend a device so it does not process virtqueue requests anymore
104     ///
105     /// After the return of ioctl the device must preserve all the necessary state
106     /// (the virtqueue vring base plus the possible device specific states) that is
107     /// required for restoring in the future. The device must not change its
108     /// configuration after that point.
suspend(&self) -> Result<()>109     fn suspend(&self) -> Result<()>;
110 
111     /// Map DMA region.
112     ///
113     /// # Arguments
114     /// * `iova` - I/O virtual address.
115     /// * `size` - Size of the I/O mapping.
116     /// * `vaddr` - Virtual address in the current process.
117     /// * `readonly` - true if the region is read-only, false if reads and writes are allowed.
dma_map(&self, iova: u64, size: u64, vaddr: *const u8, readonly: bool) -> Result<()>118     fn dma_map(&self, iova: u64, size: u64, vaddr: *const u8, readonly: bool) -> Result<()>;
119 
120     /// Unmap DMA region.
121     ///
122     /// # Arguments
123     /// * `iova` - I/O virtual address.
124     /// * `size` - Size of the I/O mapping.
dma_unmap(&self, iova: u64, size: u64) -> Result<()>125     fn dma_unmap(&self, iova: u64, size: u64) -> Result<()>;
126 }
127