1 // Copyright 2020 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use crate::{wrap_descriptor, AsRawDescriptor, MappedRegion, MmapError, Protection, SharedMemory}; 6 use data_model::volatile_memory::*; 7 use data_model::DataInit; 8 use std::fs::File; 9 use sys_util::MemoryMapping as SysUtilMmap; 10 11 pub type Result<T> = std::result::Result<T, MmapError>; 12 13 /// See [MemoryMapping](sys_util::MemoryMapping) for struct- and method-level 14 /// documentation. 15 #[derive(Debug)] 16 pub struct MemoryMapping { 17 mapping: SysUtilMmap, 18 } 19 20 impl MemoryMapping { write_slice(&self, buf: &[u8], offset: usize) -> Result<usize>21 pub fn write_slice(&self, buf: &[u8], offset: usize) -> Result<usize> { 22 self.mapping.write_slice(buf, offset) 23 } 24 read_slice(&self, buf: &mut [u8], offset: usize) -> Result<usize>25 pub fn read_slice(&self, buf: &mut [u8], offset: usize) -> Result<usize> { 26 self.mapping.read_slice(buf, offset) 27 } 28 write_obj<T: DataInit>(&self, val: T, offset: usize) -> Result<()>29 pub fn write_obj<T: DataInit>(&self, val: T, offset: usize) -> Result<()> { 30 self.mapping.write_obj(val, offset) 31 } 32 read_obj<T: DataInit>(&self, offset: usize) -> Result<T>33 pub fn read_obj<T: DataInit>(&self, offset: usize) -> Result<T> { 34 self.mapping.read_obj(offset) 35 } 36 msync(&self) -> Result<()>37 pub fn msync(&self) -> Result<()> { 38 self.mapping.msync() 39 } 40 use_hugepages(&self) -> Result<()>41 pub fn use_hugepages(&self) -> Result<()> { 42 self.mapping.use_hugepages() 43 } 44 read_to_memory( &self, mem_offset: usize, src: &dyn AsRawDescriptor, count: usize, ) -> Result<()>45 pub fn read_to_memory( 46 &self, 47 mem_offset: usize, 48 src: &dyn AsRawDescriptor, 49 count: usize, 50 ) -> Result<()> { 51 self.mapping 52 .read_to_memory(mem_offset, &wrap_descriptor(src), count) 53 } 54 write_from_memory( &self, mem_offset: usize, dst: &dyn AsRawDescriptor, count: usize, ) -> Result<()>55 pub fn write_from_memory( 56 &self, 57 mem_offset: usize, 58 dst: &dyn AsRawDescriptor, 59 count: usize, 60 ) -> Result<()> { 61 self.mapping 62 .write_from_memory(mem_offset, &wrap_descriptor(dst), count) 63 } 64 } 65 66 pub trait Unix { remove_range(&self, mem_offset: usize, count: usize) -> Result<()>67 fn remove_range(&self, mem_offset: usize, count: usize) -> Result<()>; 68 } 69 70 impl Unix for MemoryMapping { remove_range(&self, mem_offset: usize, count: usize) -> Result<()>71 fn remove_range(&self, mem_offset: usize, count: usize) -> Result<()> { 72 self.mapping.remove_range(mem_offset, count) 73 } 74 } 75 76 pub trait MemoryMappingBuilderUnix<'a> { from_descriptor(self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder77 fn from_descriptor(self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder; 78 } 79 80 pub struct MemoryMappingBuilder<'a> { 81 descriptor: Option<&'a dyn AsRawDescriptor>, 82 size: usize, 83 offset: Option<u64>, 84 protection: Option<Protection>, 85 populate: bool, 86 } 87 88 impl<'a> MemoryMappingBuilderUnix<'a> for MemoryMappingBuilder<'a> { 89 /// Build the memory mapping given the specified descriptor to mapped memory 90 /// 91 /// Default: Create a new memory mapping. from_descriptor(mut self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder92 fn from_descriptor(mut self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder { 93 self.descriptor = Some(descriptor); 94 self 95 } 96 } 97 98 /// Builds a MemoryMapping object from the specified arguments. 99 impl<'a> MemoryMappingBuilder<'a> { 100 /// Creates a new builder specifying size of the memory region in bytes. new(size: usize) -> MemoryMappingBuilder<'a>101 pub fn new(size: usize) -> MemoryMappingBuilder<'a> { 102 MemoryMappingBuilder { 103 descriptor: None, 104 size, 105 offset: None, 106 protection: None, 107 populate: false, 108 } 109 } 110 111 /// Build the memory mapping given the specified File to mapped memory 112 /// 113 /// Default: Create a new memory mapping. 114 /// 115 /// Note: this is a forward looking interface to accomodate platforms that 116 /// require special handling for file backed mappings. 117 #[allow(unused_mut)] from_file(mut self, file: &'a File) -> MemoryMappingBuilder118 pub fn from_file(mut self, file: &'a File) -> MemoryMappingBuilder { 119 self.descriptor = Some(file as &dyn AsRawDescriptor); 120 self 121 } 122 123 /// Build the memory mapping given the specified SharedMemory to mapped memory 124 /// 125 /// Default: Create a new memory mapping. from_shared_memory(mut self, shm: &'a SharedMemory) -> MemoryMappingBuilder126 pub fn from_shared_memory(mut self, shm: &'a SharedMemory) -> MemoryMappingBuilder { 127 self.descriptor = Some(shm as &dyn AsRawDescriptor); 128 self 129 } 130 131 /// Offset in bytes from the beginning of the mapping to start the mmap. 132 /// 133 /// Default: No offset offset(mut self, offset: u64) -> MemoryMappingBuilder<'a>134 pub fn offset(mut self, offset: u64) -> MemoryMappingBuilder<'a> { 135 self.offset = Some(offset); 136 self 137 } 138 139 /// Protection (e.g. readable/writable) of the memory region. 140 /// 141 /// Default: Read/write protection(mut self, protection: Protection) -> MemoryMappingBuilder<'a>142 pub fn protection(mut self, protection: Protection) -> MemoryMappingBuilder<'a> { 143 self.protection = Some(protection); 144 self 145 } 146 147 /// Request that the mapped pages are pre-populated 148 /// 149 /// Default: Do not populate populate(mut self) -> MemoryMappingBuilder<'a>150 pub fn populate(mut self) -> MemoryMappingBuilder<'a> { 151 self.populate = true; 152 self 153 } 154 155 /// Build a MemoryMapping from the provided options. build(self) -> Result<MemoryMapping>156 pub fn build(self) -> Result<MemoryMapping> { 157 match self.descriptor { 158 None => { 159 if self.populate { 160 // Population not supported for new mmaps 161 return Err(MmapError::InvalidArgument); 162 } 163 MemoryMappingBuilder::wrap(SysUtilMmap::new_protection( 164 self.size, 165 self.protection.unwrap_or_else(Protection::read_write), 166 )) 167 } 168 Some(descriptor) => { 169 MemoryMappingBuilder::wrap(SysUtilMmap::from_fd_offset_protection_populate( 170 &wrap_descriptor(descriptor), 171 self.size, 172 self.offset.unwrap_or(0), 173 self.protection.unwrap_or_else(Protection::read_write), 174 self.populate, 175 )) 176 } 177 } 178 } 179 180 /// Build a MemoryMapping from the provided options at a fixed address. Note this 181 /// is a separate function from build in order to isolate unsafe behavior. 182 /// 183 /// # Safety 184 /// 185 /// Function should not be called before the caller unmaps any mmap'd regions already 186 /// present at `(addr..addr+size)`. If another MemoryMapping object holds the same 187 /// address space, the destructors of those objects will conflict and the space could 188 /// be unmapped while still in use. build_fixed(self, addr: *mut u8) -> Result<MemoryMapping>189 pub unsafe fn build_fixed(self, addr: *mut u8) -> Result<MemoryMapping> { 190 if self.populate { 191 // Population not supported for fixed mapping. 192 return Err(MmapError::InvalidArgument); 193 } 194 match self.descriptor { 195 None => MemoryMappingBuilder::wrap(SysUtilMmap::new_protection_fixed( 196 addr, 197 self.size, 198 self.protection.unwrap_or_else(Protection::read_write), 199 )), 200 Some(descriptor) => { 201 MemoryMappingBuilder::wrap(SysUtilMmap::from_fd_offset_protection_fixed( 202 addr, 203 &wrap_descriptor(descriptor), 204 self.size, 205 self.offset.unwrap_or(0), 206 self.protection.unwrap_or_else(Protection::read_write), 207 )) 208 } 209 } 210 } 211 wrap(result: Result<SysUtilMmap>) -> Result<MemoryMapping>212 fn wrap(result: Result<SysUtilMmap>) -> Result<MemoryMapping> { 213 result.map(|mapping| MemoryMapping { mapping }) 214 } 215 } 216 217 impl VolatileMemory for MemoryMapping { get_slice(&self, offset: usize, count: usize) -> VolatileMemoryResult<VolatileSlice>218 fn get_slice(&self, offset: usize, count: usize) -> VolatileMemoryResult<VolatileSlice> { 219 self.mapping.get_slice(offset, count) 220 } 221 } 222 223 // Safe because it exclusively forwards calls to a safe implementation. 224 unsafe impl MappedRegion for MemoryMapping { as_ptr(&self) -> *mut u8225 fn as_ptr(&self) -> *mut u8 { 226 self.mapping.as_ptr() 227 } 228 size(&self) -> usize229 fn size(&self) -> usize { 230 self.mapping.size() 231 } 232 } 233