Skip to content

Commit ed0ef45

Browse files
committed
refactor(xen): Reuse MmapRegion from unix module
Now that xen and non-xen definitions of all the mapping structure can co-exist, we can reuse stuff from the `mmap::unix` module in `mmap::xen`, and eliminate a few of the structs and functions that are copy-pasted between the two. Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
1 parent b2c2b40 commit ed0ef45

File tree

2 files changed

+46
-88
lines changed

2 files changed

+46
-88
lines changed

src/mmap/unix.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl<B: Bitmap> MmapRegionBuilder<B> {
217217
/// When running a 64-bit virtual machine on a 32-bit hypervisor, only part of the guest's
218218
/// physical memory may be mapped into the current process due to the limited virtual address
219219
/// space size of the process.
220-
#[derive(Debug)]
220+
#[derive(Clone, Debug)]
221221
pub struct MmapRegion<B = ()> {
222222
addr: *mut u8,
223223
size: usize,

src/mmap/xen.rs

Lines changed: 45 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
1010
use bitflags::bitflags;
1111
use libc::{c_int, c_void, MAP_SHARED, _SC_PAGESIZE};
12+
use std::sync::Arc;
1213
use std::{io, mem::size_of, os::raw::c_ulong, os::unix::io::AsRawFd, ptr::null_mut, result};
13-
1414
use vmm_sys_util::{
1515
fam::{Error as FamError, FamStruct, FamStructWrapper},
1616
generate_fam_struct_impl,
@@ -26,28 +26,23 @@ use tests::ioctl_with_ref;
2626

2727
use crate::bitmap::{Bitmap, NewBitmap, BS};
2828
use crate::guest_memory::{FileOffset, GuestAddress};
29+
use crate::mmap::unix::MmapRegion as MmapUnix;
2930
use crate::volatile_memory::{self, VolatileMemory, VolatileSlice};
3031
use crate::{
3132
guest_memory, Address, GuestMemoryRegion, GuestMemoryRegionBytes, GuestRegionCollection,
32-
GuestUsize, MemoryRegionAddress,
33+
GuestUsize, MemoryRegionAddress, MmapRegionBuilder,
3334
};
3435

3536
/// Error conditions that may arise when creating a new `MmapRegion` object.
3637
#[derive(Debug, thiserror::Error)]
3738
pub enum Error {
38-
/// The specified file offset and length cause overflow when added.
39-
#[error("The specified file offset and length cause overflow when added")]
40-
InvalidOffsetLength,
4139
/// The forbidden `MAP_FIXED` flag was specified.
4240
#[error("The forbidden `MAP_FIXED` flag was specified")]
4341
MapFixed,
44-
/// A mapping with offset + length > EOF was attempted.
45-
#[error("The specified file offset and length is greater then file length")]
46-
MappingPastEof,
4742
/// The `mmap` call returned an error.
4843
#[error("{0}")]
4944
Mmap(io::Error),
50-
/// Invalid file offset.
45+
/// Invalid file offset (non-zero of missing altogether).
5146
#[error("Invalid file offset")]
5247
InvalidFileOffset,
5348
/// Memory mapped in advance.
@@ -62,6 +57,9 @@ pub enum Error {
6257
/// Unexpected error.
6358
#[error("Unexpected error")]
6459
Unexpected,
60+
/// Error establishing normal unix mapping
61+
#[error["{0}"]]
62+
Unix(#[from] crate::mmap::unix::Error),
6563
}
6664

6765
type Result<T> = result::Result<T, Error>;
@@ -427,45 +425,6 @@ impl<B: Bitmap> VolatileMemory for MmapRegion<B> {
427425
}
428426
}
429427

430-
#[derive(Clone, Debug, PartialEq)]
431-
struct MmapUnix {
432-
addr: *mut u8,
433-
size: usize,
434-
}
435-
436-
impl MmapUnix {
437-
fn new(size: usize, prot: i32, flags: i32, fd: i32, f_offset: u64) -> Result<Self> {
438-
let addr =
439-
// SAFETY: This is safe because we're not allowing MAP_FIXED, and invalid parameters
440-
// cannot break Rust safety guarantees (things may change if we're mapping /dev/mem or
441-
// some wacky file).
442-
unsafe { libc::mmap(null_mut(), size, prot, flags, fd, f_offset as libc::off_t) };
443-
444-
if addr == libc::MAP_FAILED {
445-
return Err(Error::Mmap(io::Error::last_os_error()));
446-
}
447-
448-
Ok(Self {
449-
addr: addr as *mut u8,
450-
size,
451-
})
452-
}
453-
454-
fn addr(&self) -> *mut u8 {
455-
self.addr
456-
}
457-
}
458-
459-
impl Drop for MmapUnix {
460-
fn drop(&mut self) {
461-
// SAFETY: This is safe because we mmap the area at addr ourselves, and nobody
462-
// else is holding a reference to it.
463-
unsafe {
464-
libc::munmap(self.addr as *mut libc::c_void, self.size);
465-
}
466-
}
467-
}
468-
469428
// Bit mask for the vhost-user xen mmap message.
470429
bitflags! {
471430
/// Flags for the Xen mmap message.
@@ -531,21 +490,18 @@ fn pages(size: usize) -> (usize, usize) {
531490
(num, page_size * num)
532491
}
533492

534-
fn validate_file(file_offset: &Option<FileOffset>) -> Result<(i32, u64)> {
493+
fn validate_file(file_offset: Option<FileOffset>) -> Result<FileOffset> {
535494
let file_offset = match file_offset {
536495
Some(f) => f,
537496
None => return Err(Error::InvalidFileOffset),
538497
};
539498

540-
let fd = file_offset.file().as_raw_fd();
541-
let f_offset = file_offset.start();
542-
543499
// We don't allow file offsets with Xen foreign mappings.
544-
if f_offset != 0 {
545-
return Err(Error::InvalidOffsetLength);
500+
if file_offset.start() != 0 {
501+
return Err(Error::InvalidFileOffset);
546502
}
547503

548-
Ok((fd, f_offset))
504+
Ok(file_offset)
549505
}
550506

551507
// Xen Foreign memory mapping interface.
@@ -556,27 +512,22 @@ trait MmapXenTrait: std::fmt::Debug {
556512
}
557513

558514
// Standard Unix memory mapping for testing other crates.
559-
#[derive(Clone, Debug, PartialEq)]
515+
#[derive(Clone, Debug)]
560516
struct MmapXenUnix(MmapUnix, GuestAddress);
561517

562518
impl MmapXenUnix {
563519
fn new(range: &MmapRange) -> Result<Self> {
564-
let (fd, offset) = if let Some(ref f_off) = range.file_offset {
565-
(f_off.file().as_raw_fd(), f_off.start())
566-
} else {
567-
(-1, 0)
568-
};
520+
let mut builder = MmapRegionBuilder::new(range.size)
521+
.with_mmap_prot(range.prot.ok_or(Error::Unexpected)?)
522+
.with_mmap_flags(range.flags.ok_or(Error::Unexpected)?);
569523

570-
Ok(Self(
571-
MmapUnix::new(
572-
range.size,
573-
range.prot.ok_or(Error::Unexpected)?,
574-
range.flags.ok_or(Error::Unexpected)?,
575-
fd,
576-
offset,
577-
)?,
578-
range.addr,
579-
))
524+
if let Some(ref file_offset) = range.file_offset {
525+
builder = builder.with_file_offset(file_offset.clone());
526+
}
527+
528+
let mmap_unix = builder.build()?;
529+
530+
Ok(MmapXenUnix(mmap_unix, range.addr))
580531
}
581532
}
582533

@@ -587,7 +538,7 @@ impl MmapXenTrait for MmapXenUnix {
587538
}
588539

589540
fn addr(&self) -> *mut u8 {
590-
self.0.addr()
541+
self.0.as_ptr()
591542
}
592543

593544
fn guest_base(&self) -> GuestAddress {
@@ -626,7 +577,7 @@ fn ioctl_privcmd_mmapbatch_v2() -> c_ulong {
626577
}
627578

628579
// Xen foreign memory specific implementation.
629-
#[derive(Clone, Debug, PartialEq)]
580+
#[derive(Clone, Debug)]
630581
struct MmapXenForeign {
631582
domid: u32,
632583
guest_base: GuestAddress,
@@ -642,16 +593,15 @@ impl AsRawFd for MmapXenForeign {
642593

643594
impl MmapXenForeign {
644595
fn new(range: &MmapRange) -> Result<Self> {
645-
let (fd, f_offset) = validate_file(&range.file_offset)?;
646596
let (count, size) = pages(range.size);
597+
let file_offset = validate_file(range.file_offset.clone())?;
598+
let fd = file_offset.file().as_raw_fd();
647599

648-
let unix_mmap = MmapUnix::new(
649-
size,
650-
range.prot.ok_or(Error::Unexpected)?,
651-
range.flags.ok_or(Error::Unexpected)? | MAP_SHARED,
652-
fd,
653-
f_offset,
654-
)?;
600+
let unix_mmap = MmapRegionBuilder::new(size)
601+
.with_mmap_prot(range.prot.ok_or(Error::Unexpected)?)
602+
.with_mmap_flags(range.flags.ok_or(Error::Unexpected)? | MAP_SHARED)
603+
.with_file_offset(file_offset)
604+
.build()?;
655605

656606
let foreign = Self {
657607
domid: range.mmap_data,
@@ -701,7 +651,7 @@ impl MmapXenTrait for MmapXenForeign {
701651
}
702652

703653
fn addr(&self) -> *mut u8 {
704-
self.unix_mmap.addr()
654+
self.unix_mmap.as_ptr()
705655
}
706656

707657
fn guest_base(&self) -> GuestAddress {
@@ -855,12 +805,12 @@ impl AsRawFd for MmapXenGrant {
855805

856806
impl MmapXenGrant {
857807
fn new(range: &MmapRange, mmap_flags: MmapXenFlags) -> Result<Self> {
858-
validate_file(&range.file_offset)?;
808+
let file_offset = validate_file(range.file_offset.clone())?;
859809

860810
let mut grant = Self {
861811
guest_base: range.addr,
862812
unix_mmap: None,
863-
file_offset: range.file_offset.as_ref().unwrap().clone(),
813+
file_offset,
864814
flags: range.flags.ok_or(Error::Unexpected)?,
865815
size: 0,
866816
index: 0,
@@ -884,7 +834,15 @@ impl MmapXenGrant {
884834
fn mmap_range(&self, addr: GuestAddress, size: usize, prot: i32) -> Result<(MmapUnix, u64)> {
885835
let (count, size) = pages(size);
886836
let index = self.mmap_ioctl(addr, count)?;
887-
let unix_mmap = MmapUnix::new(size, prot, self.flags, self.as_raw_fd(), index)?;
837+
838+
let unix_mmap = MmapRegionBuilder::new(size)
839+
.with_mmap_prot(prot)
840+
.with_mmap_flags(self.flags)
841+
.with_file_offset(FileOffset::from_arc(
842+
Arc::clone(self.file_offset.arc()),
843+
index,
844+
))
845+
.build()?;
888846

889847
Ok((unix_mmap, index))
890848
}
@@ -934,7 +892,7 @@ impl MmapXenTrait for MmapXenGrant {
934892

935893
fn addr(&self) -> *mut u8 {
936894
if let Some(ref unix_mmap) = self.unix_mmap {
937-
unix_mmap.addr()
895+
unix_mmap.as_ptr()
938896
} else {
939897
null_mut()
940898
}
@@ -983,7 +941,7 @@ impl MmapXenSlice {
983941
let (unix_mmap, index) = grant.mmap_range(GuestAddress(addr), size, prot)?;
984942

985943
// SAFETY: We have already mapped the range including offset.
986-
let addr = unsafe { unix_mmap.addr().add(offset) };
944+
let addr = unsafe { unix_mmap.as_ptr().add(offset) };
987945

988946
Ok(Self {
989947
grant: Some(grant),

0 commit comments

Comments
 (0)