@@ -16,13 +16,15 @@ use std::alloc::{alloc, dealloc, Layout};
16
16
use std:: mem;
17
17
18
18
use super :: vhost_binding:: * ;
19
- use super :: { ioctl_result, Error , Result , VhostKernBackend } ;
19
+ use super :: { ioctl_result, Error , Result , VhostKernBackend , VhostKernFeatures } ;
20
20
use crate :: vdpa:: * ;
21
+ use crate :: { VhostAccess , VhostIotlbBackend , VhostIotlbMsg , VhostIotlbType } ;
21
22
22
23
/// Handle for running VHOST_VDPA ioctls.
23
24
pub struct VhostKernVdpa < AS : GuestAddressSpace > {
24
25
fd : File ,
25
26
mem : AS ,
27
+ backend_features_acked : u64 ,
26
28
}
27
29
28
30
impl < AS : GuestAddressSpace > VhostKernVdpa < AS > {
@@ -36,6 +38,7 @@ impl<AS: GuestAddressSpace> VhostKernVdpa<AS> {
36
38
. open ( path)
37
39
. map_err ( Error :: VhostOpen ) ?,
38
40
mem,
41
+ backend_features_acked : 0 ,
39
42
} )
40
43
}
41
44
}
@@ -140,6 +143,32 @@ impl<AS: GuestAddressSpace> VhostVdpa for VhostKernVdpa<AS> {
140
143
141
144
ioctl_result ( ret, iova_range)
142
145
}
146
+
147
+ fn dma_map ( & self , iova : u64 , size : u64 , vaddr : * const u8 , readonly : bool ) -> Result < ( ) > {
148
+ let iotlb = VhostIotlbMsg {
149
+ iova,
150
+ size,
151
+ userspace_addr : vaddr as u64 ,
152
+ perm : match readonly {
153
+ true => VhostAccess :: ReadOnly ,
154
+ false => VhostAccess :: ReadWrite ,
155
+ } ,
156
+ msg_type : VhostIotlbType :: Update ,
157
+ } ;
158
+
159
+ self . send_iotlb_msg ( & iotlb)
160
+ }
161
+
162
+ fn dma_unmap ( & self , iova : u64 , size : u64 ) -> Result < ( ) > {
163
+ let iotlb = VhostIotlbMsg {
164
+ iova,
165
+ size,
166
+ msg_type : VhostIotlbType :: Invalidate ,
167
+ ..Default :: default ( )
168
+ } ;
169
+
170
+ self . send_iotlb_msg ( & iotlb)
171
+ }
143
172
}
144
173
145
174
impl < AS : GuestAddressSpace > VhostKernBackend for VhostKernVdpa < AS > {
@@ -156,6 +185,16 @@ impl<AS: GuestAddressSpace> AsRawFd for VhostKernVdpa<AS> {
156
185
}
157
186
}
158
187
188
+ impl < AS : GuestAddressSpace > VhostKernFeatures for VhostKernVdpa < AS > {
189
+ fn get_backend_features_acked ( & self ) -> u64 {
190
+ self . backend_features_acked
191
+ }
192
+
193
+ fn set_backend_features_acked ( & mut self , features : u64 ) {
194
+ self . backend_features_acked = features;
195
+ }
196
+ }
197
+
159
198
#[ cfg( test) ]
160
199
mod tests {
161
200
const VHOST_VDPA_PATH : & str = "/dev/vhost-vdpa-0" ;
@@ -281,4 +320,35 @@ mod tests {
281
320
vdpa. set_vring_enable ( 0 , true ) . unwrap ( ) ;
282
321
vdpa. set_vring_enable ( 0 , false ) . unwrap ( ) ;
283
322
}
323
+
324
+ #[ test]
325
+ #[ serial]
326
+ fn test_vdpa_kern_dma ( ) {
327
+ let m = GuestMemoryMmap :: < ( ) > :: from_ranges ( & [ ( GuestAddress ( 0 ) , 0x10_0000 ) ] ) . unwrap ( ) ;
328
+ let mut vdpa = VhostKernVdpa :: new ( VHOST_VDPA_PATH , & m) . unwrap ( ) ;
329
+
330
+ let features = vdpa. get_features ( ) . unwrap ( ) ;
331
+ // VIRTIO_F_VERSION_1 (bit 32) should be set
332
+ assert_ne ! ( features & ( 1 << 32 ) , 0 ) ;
333
+ vdpa. set_features ( features) . unwrap ( ) ;
334
+
335
+ let backend_features = vdpa. get_backend_features ( ) . unwrap ( ) ;
336
+ assert_ne ! ( backend_features & ( 1 << VHOST_BACKEND_F_IOTLB_MSG_V2 ) , 0 ) ;
337
+ vdpa. set_backend_features ( backend_features) . unwrap ( ) ;
338
+
339
+ vdpa. set_owner ( ) . unwrap ( ) ;
340
+
341
+ vdpa. dma_map ( 0xFFFF_0000 , 0xFFFF , std:: ptr:: null :: < u8 > ( ) , false )
342
+ . unwrap_err ( ) ;
343
+
344
+ unsafe {
345
+ let layout = Layout :: from_size_align ( 0xFFFF , 1 ) . unwrap ( ) ;
346
+ let ptr = alloc ( layout) ;
347
+
348
+ vdpa. dma_map ( 0xFFFF_0000 , 0xFFFF , ptr, false ) . unwrap ( ) ;
349
+ vdpa. dma_unmap ( 0xFFFF_0000 , 0xFFFF ) . unwrap ( ) ;
350
+
351
+ dealloc ( ptr, layout) ;
352
+ } ;
353
+ }
284
354
}
0 commit comments