11
11
//! communicate with userspace applications. This sub module provides ioctl based interfaces to
12
12
//! control the in-kernel net, scsi, vsock vhost drivers.
13
13
14
+ use std:: mem;
14
15
use std:: os:: unix:: io:: { AsRawFd , RawFd } ;
15
16
17
+ use libc:: { c_void, ssize_t, write} ;
18
+
16
19
use vm_memory:: { Address , GuestAddress , GuestAddressSpace , GuestMemory , GuestUsize } ;
17
20
use vmm_sys_util:: eventfd:: EventFd ;
18
21
use vmm_sys_util:: ioctl:: { ioctl, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref} ;
19
22
20
23
use super :: {
21
- Error , Result , VhostBackend , VhostUserDirtyLogRegion , VhostUserMemoryRegionInfo ,
22
- VringConfigData , VHOST_MAX_MEMORY_REGIONS ,
24
+ Error , Result , VhostBackend , VhostIotlbBackend , VhostIotlbMsg , VhostIotlbMsgParser ,
25
+ VhostUserDirtyLogRegion , VhostUserMemoryRegionInfo , VringConfigData , VHOST_MAX_MEMORY_REGIONS ,
23
26
} ;
24
27
25
28
pub mod vhost_binding;
@@ -37,6 +40,15 @@ fn ioctl_result<T>(rc: i32, res: T) -> Result<T> {
37
40
}
38
41
}
39
42
43
+ #[ inline]
44
+ fn io_result < T > ( rc : isize , res : T ) -> Result < T > {
45
+ if rc < 0 {
46
+ Err ( Error :: IOError ( std:: io:: Error :: last_os_error ( ) ) )
47
+ } else {
48
+ Ok ( res)
49
+ }
50
+ }
51
+
40
52
/// Represent an in-kernel vhost device backend.
41
53
pub trait VhostKernBackend : AsRawFd {
42
54
/// Associated type to access guest memory.
@@ -314,4 +326,114 @@ pub trait VhostKernFeatures: Sized + AsRawFd {
314
326
315
327
ioctl_result ( ret, ( ) )
316
328
}
317
- }
329
+ }
330
+
331
+ /// Handle IOTLB messeges for in-kernel vhost device backend.
332
+ impl < I : VhostKernBackend + VhostKernFeatures > VhostIotlbBackend for I {
333
+ /// Send an IOTLB message to the in-kernel vhost backend.
334
+ ///
335
+ /// # Arguments
336
+ /// * `msg` - IOTLB message to send.
337
+ fn send_iotlb_msg ( & self , msg : & VhostIotlbMsg ) -> Result < ( ) > {
338
+ let ret: ssize_t ;
339
+
340
+ if self . get_backend_features_acked ( ) & ( 1 << VHOST_BACKEND_F_IOTLB_MSG_V2 ) != 0 {
341
+ let mut msg_v2 = vhost_msg_v2 {
342
+ type_ : VHOST_IOTLB_MSG_V2 ,
343
+ ..Default :: default ( )
344
+ } ;
345
+
346
+ msg_v2. __bindgen_anon_1 . iotlb . iova = msg. iova ;
347
+ msg_v2. __bindgen_anon_1 . iotlb . size = msg. size ;
348
+ msg_v2. __bindgen_anon_1 . iotlb . uaddr = msg. userspace_addr ;
349
+ msg_v2. __bindgen_anon_1 . iotlb . perm = msg. perm as u8 ;
350
+ msg_v2. __bindgen_anon_1 . iotlb . type_ = msg. msg_type as u8 ;
351
+
352
+ ret = unsafe {
353
+ write (
354
+ self . as_raw_fd ( ) ,
355
+ & msg_v2 as * const vhost_msg_v2 as * const c_void ,
356
+ mem:: size_of :: < vhost_msg_v2 > ( ) ,
357
+ )
358
+ } ;
359
+ } else {
360
+ let mut msg_v1 = vhost_msg {
361
+ type_ : VHOST_IOTLB_MSG ,
362
+ ..Default :: default ( )
363
+ } ;
364
+
365
+ msg_v1. __bindgen_anon_1 . iotlb . iova = msg. iova ;
366
+ msg_v1. __bindgen_anon_1 . iotlb . size = msg. size ;
367
+ msg_v1. __bindgen_anon_1 . iotlb . uaddr = msg. userspace_addr ;
368
+ msg_v1. __bindgen_anon_1 . iotlb . perm = msg. perm as u8 ;
369
+ msg_v1. __bindgen_anon_1 . iotlb . type_ = msg. msg_type as u8 ;
370
+
371
+ ret = unsafe {
372
+ write (
373
+ self . as_raw_fd ( ) ,
374
+ & msg_v1 as * const vhost_msg as * const c_void ,
375
+ mem:: size_of :: < vhost_msg > ( ) ,
376
+ )
377
+ } ;
378
+ }
379
+
380
+ io_result ( ret, ( ) )
381
+ }
382
+
383
+ /// Parse a buffer received from the in-kernel vhost backend and fill a VhostIotlbMsg.
384
+ ///
385
+ /// # Arguments
386
+ /// * `buffer` - Buffer containing the raw data received from the in-kernel vhost backend.
387
+ /// * `msg` - IOTLB message parsed.
388
+ fn parse_iotlb_msg < T : Sized + VhostIotlbMsgParser > (
389
+ & self ,
390
+ buffer : & T ,
391
+ msg : & mut VhostIotlbMsg ,
392
+ ) -> Result < ( ) > {
393
+ buffer. parse ( msg)
394
+ }
395
+ }
396
+
397
+ impl VhostIotlbMsgParser for vhost_msg {
398
+ fn parse ( & self , msg : & mut VhostIotlbMsg ) -> Result < ( ) > {
399
+ if self . type_ != VHOST_IOTLB_MSG {
400
+ return Err ( Error :: InvalidIotlbMsg ) ;
401
+ }
402
+
403
+ unsafe {
404
+ if self . __bindgen_anon_1 . iotlb . type_ == 0 {
405
+ return Err ( Error :: InvalidIotlbMsg ) ;
406
+ }
407
+
408
+ msg. iova = self . __bindgen_anon_1 . iotlb . iova ;
409
+ msg. size = self . __bindgen_anon_1 . iotlb . size ;
410
+ msg. userspace_addr = self . __bindgen_anon_1 . iotlb . uaddr ;
411
+ msg. perm = mem:: transmute ( self . __bindgen_anon_1 . iotlb . perm ) ;
412
+ msg. msg_type = mem:: transmute ( self . __bindgen_anon_1 . iotlb . type_ ) ;
413
+ }
414
+
415
+ Ok ( ( ) )
416
+ }
417
+ }
418
+
419
+ impl VhostIotlbMsgParser for vhost_msg_v2 {
420
+ fn parse ( & self , msg : & mut VhostIotlbMsg ) -> Result < ( ) > {
421
+ if self . type_ != VHOST_IOTLB_MSG_V2 {
422
+ return Err ( Error :: InvalidIotlbMsg ) ;
423
+ }
424
+
425
+ unsafe {
426
+ if self . __bindgen_anon_1 . iotlb . type_ == 0 {
427
+ return Err ( Error :: InvalidIotlbMsg ) ;
428
+ }
429
+
430
+ msg. iova = self . __bindgen_anon_1 . iotlb . iova ;
431
+ msg. size = self . __bindgen_anon_1 . iotlb . size ;
432
+ msg. userspace_addr = self . __bindgen_anon_1 . iotlb . uaddr ;
433
+ msg. perm = mem:: transmute ( self . __bindgen_anon_1 . iotlb . perm ) ;
434
+ msg. msg_type = mem:: transmute ( self . __bindgen_anon_1 . iotlb . type_ ) ;
435
+ }
436
+
437
+ Ok ( ( ) )
438
+ }
439
+ }
0 commit comments