10
10
#![ allow( clippy:: upper_case_acronyms) ]
11
11
12
12
use std:: fmt:: Debug ;
13
+ use std:: fs:: File ;
14
+ use std:: io;
13
15
use std:: marker:: PhantomData ;
14
16
use std:: ops:: Deref ;
15
17
16
- use vm_memory:: ByteValued ;
18
+ use vm_memory:: { mmap:: NewBitmap , ByteValued , Error as MmapError , FileOffset , MmapRegion } ;
19
+
20
+ #[ cfg( feature = "xen" ) ]
21
+ use vm_memory:: { GuestAddress , MmapRange , MmapXenFlags } ;
17
22
18
23
use super :: { Error , Result } ;
19
24
use crate :: VringConfigData ;
@@ -422,6 +427,8 @@ bitflags! {
422
427
const CONFIGURE_MEM_SLOTS = 0x0000_8000 ;
423
428
/// Support reporting status.
424
429
const STATUS = 0x0001_0000 ;
430
+ /// Support Xen mmap.
431
+ const XEN_MMAP = 0x0002_0000 ;
425
432
}
426
433
}
427
434
@@ -492,8 +499,26 @@ pub struct VhostUserMemoryRegion {
492
499
pub user_addr : u64 ,
493
500
/// Offset where region starts in the mapped memory.
494
501
pub mmap_offset : u64 ,
502
+
503
+ #[ cfg( feature = "xen" ) ]
504
+ /// Xen specific flags.
505
+ pub xen_mmap_flags : u32 ,
506
+
507
+ #[ cfg( feature = "xen" ) ]
508
+ /// Xen specific data.
509
+ pub xen_mmap_data : u32 ,
510
+ }
511
+
512
+ impl VhostUserMemoryRegion {
513
+ fn is_valid_common ( & self ) -> bool {
514
+ self . memory_size != 0
515
+ && self . guest_phys_addr . checked_add ( self . memory_size ) . is_some ( )
516
+ && self . user_addr . checked_add ( self . memory_size ) . is_some ( )
517
+ && self . mmap_offset . checked_add ( self . memory_size ) . is_some ( )
518
+ }
495
519
}
496
520
521
+ #[ cfg( not( feature = "xen" ) ) ]
497
522
impl VhostUserMemoryRegion {
498
523
/// Create a new instance.
499
524
pub fn new ( guest_phys_addr : u64 , memory_size : u64 , user_addr : u64 , mmap_offset : u64 ) -> Self {
@@ -504,18 +529,74 @@ impl VhostUserMemoryRegion {
504
529
mmap_offset,
505
530
}
506
531
}
532
+
533
+ /// Creates mmap region from Self.
534
+ pub fn mmap_region < B : NewBitmap > ( & self , file : File ) -> Result < MmapRegion < B > > {
535
+ MmapRegion :: < B > :: from_file (
536
+ FileOffset :: new ( file, self . mmap_offset ) ,
537
+ self . memory_size as usize ,
538
+ )
539
+ . map_err ( MmapError :: MmapRegion )
540
+ . map_err ( |e| Error :: ReqHandlerError ( io:: Error :: new ( io:: ErrorKind :: Other , e) ) )
541
+ }
542
+
543
+ fn is_valid ( & self ) -> bool {
544
+ self . is_valid_common ( )
545
+ }
507
546
}
508
547
509
- impl VhostUserMsgValidator for VhostUserMemoryRegion {
548
+ #[ cfg( feature = "xen" ) ]
549
+ impl VhostUserMemoryRegion {
550
+ /// Create a new instance.
551
+ pub fn with_xen (
552
+ guest_phys_addr : u64 ,
553
+ memory_size : u64 ,
554
+ user_addr : u64 ,
555
+ mmap_offset : u64 ,
556
+ xen_mmap_flags : u32 ,
557
+ xen_mmap_data : u32 ,
558
+ ) -> Self {
559
+ VhostUserMemoryRegion {
560
+ guest_phys_addr,
561
+ memory_size,
562
+ user_addr,
563
+ mmap_offset,
564
+ xen_mmap_flags,
565
+ xen_mmap_data,
566
+ }
567
+ }
568
+
569
+ /// Creates mmap region from Self.
570
+ pub fn mmap_region < B : NewBitmap > ( & self , file : File ) -> Result < MmapRegion < B > > {
571
+ let range = MmapRange :: new (
572
+ self . memory_size as usize ,
573
+ Some ( FileOffset :: new ( file, self . mmap_offset ) ) ,
574
+ GuestAddress ( self . guest_phys_addr ) ,
575
+ self . xen_mmap_flags ,
576
+ self . xen_mmap_data ,
577
+ ) ;
578
+
579
+ MmapRegion :: < B > :: from_range ( range)
580
+ . map_err ( MmapError :: MmapRegion )
581
+ . map_err ( |e| Error :: ReqHandlerError ( io:: Error :: new ( io:: ErrorKind :: Other , e) ) )
582
+ }
583
+
510
584
fn is_valid ( & self ) -> bool {
511
- if self . memory_size == 0
512
- || self . guest_phys_addr . checked_add ( self . memory_size ) . is_none ( )
513
- || self . user_addr . checked_add ( self . memory_size ) . is_none ( )
514
- || self . mmap_offset . checked_add ( self . memory_size ) . is_none ( )
515
- {
516
- return false ;
585
+ if !self . is_valid_common ( ) {
586
+ false
587
+ } else {
588
+ // Only of one of FOREIGN or GRANT should be set.
589
+ match MmapXenFlags :: from_bits ( self . xen_mmap_flags ) {
590
+ Some ( flags) => flags. is_valid ( ) ,
591
+ None => false ,
592
+ }
517
593
}
518
- true
594
+ }
595
+ }
596
+
597
+ impl VhostUserMsgValidator for VhostUserMemoryRegion {
598
+ fn is_valid ( & self ) -> bool {
599
+ self . is_valid ( )
519
600
}
520
601
}
521
602
@@ -541,6 +622,7 @@ impl Deref for VhostUserSingleMemoryRegion {
541
622
}
542
623
}
543
624
625
+ #[ cfg( not( feature = "xen" ) ) ]
544
626
impl VhostUserSingleMemoryRegion {
545
627
/// Create a new instance.
546
628
pub fn new ( guest_phys_addr : u64 , memory_size : u64 , user_addr : u64 , mmap_offset : u64 ) -> Self {
@@ -556,6 +638,31 @@ impl VhostUserSingleMemoryRegion {
556
638
}
557
639
}
558
640
641
+ #[ cfg( feature = "xen" ) ]
642
+ impl VhostUserSingleMemoryRegion {
643
+ /// Create a new instance.
644
+ pub fn new (
645
+ guest_phys_addr : u64 ,
646
+ memory_size : u64 ,
647
+ user_addr : u64 ,
648
+ mmap_offset : u64 ,
649
+ xen_mmap_flags : u32 ,
650
+ xen_mmap_data : u32 ,
651
+ ) -> Self {
652
+ VhostUserSingleMemoryRegion {
653
+ padding : 0 ,
654
+ region : VhostUserMemoryRegion :: with_xen (
655
+ guest_phys_addr,
656
+ memory_size,
657
+ user_addr,
658
+ mmap_offset,
659
+ xen_mmap_flags,
660
+ xen_mmap_data,
661
+ ) ,
662
+ }
663
+ }
664
+ }
665
+
559
666
// SAFETY: Safe because all fields of VhostUserSingleMemoryRegion are POD.
560
667
unsafe impl ByteValued for VhostUserSingleMemoryRegion { }
561
668
impl VhostUserMsgValidator for VhostUserSingleMemoryRegion { }
@@ -1001,6 +1108,20 @@ mod tests {
1001
1108
use super :: * ;
1002
1109
use std:: mem;
1003
1110
1111
+ #[ cfg( feature = "xen" ) ]
1112
+ impl VhostUserMemoryRegion {
1113
+ fn new ( guest_phys_addr : u64 , memory_size : u64 , user_addr : u64 , mmap_offset : u64 ) -> Self {
1114
+ Self :: with_xen (
1115
+ guest_phys_addr,
1116
+ memory_size,
1117
+ user_addr,
1118
+ mmap_offset,
1119
+ MmapXenFlags :: FOREIGN . bits ( ) ,
1120
+ 0 ,
1121
+ )
1122
+ }
1123
+ }
1124
+
1004
1125
#[ test]
1005
1126
fn check_master_request_code ( ) {
1006
1127
assert ! ( !MasterReq :: is_valid( MasterReq :: NOOP as _) ) ;
@@ -1106,12 +1227,7 @@ mod tests {
1106
1227
1107
1228
#[ test]
1108
1229
fn check_user_memory_region ( ) {
1109
- let mut msg = VhostUserMemoryRegion {
1110
- guest_phys_addr : 0 ,
1111
- memory_size : 0x1000 ,
1112
- user_addr : 0 ,
1113
- mmap_offset : 0 ,
1114
- } ;
1230
+ let mut msg = VhostUserMemoryRegion :: new ( 0 , 0x1000 , 0 , 0 ) ;
1115
1231
assert ! ( msg. is_valid( ) ) ;
1116
1232
msg. guest_phys_addr = 0xFFFFFFFFFFFFEFFF ;
1117
1233
assert ! ( msg. is_valid( ) ) ;
0 commit comments