1use {AsHandleRef, Cookied, HandleBased, Handle, HandleRef, Status};
8use {sys, into_result};
9use std::{mem, ptr};
10
11#[derive(Debug, Eq, PartialEq)]
16pub struct Vmo(Handle);
17impl_handle_based!(Vmo);
18impl Cookied for Vmo {}
19
20impl Vmo {
21 pub fn create(size: u64, options: VmoOpts) -> Result<Vmo, Status> {
29 let mut handle = 0;
30 let status = unsafe { sys::mx_vmo_create(size, options as u32, &mut handle) };
31 into_result(status, ||
32 Vmo::from(Handle(handle)))
33 }
34
35 pub fn read(&self, data: &mut [u8], offset: u64) -> Result<usize, Status> {
39 unsafe {
40 let mut actual = 0;
41 let status = sys::mx_vmo_read(self.raw_handle(), data.as_mut_ptr(),
42 offset, data.len(), &mut actual);
43 into_result(status, || actual)
44 }
45 }
46
47 pub fn write(&self, data: &[u8], offset: u64) -> Result<usize, Status> {
51 unsafe {
52 let mut actual = 0;
53 let status = sys::mx_vmo_write(self.raw_handle(), data.as_ptr(),
54 offset, data.len(), &mut actual);
55 into_result(status, || actual)
56 }
57 }
58
59 pub fn get_size(&self) -> Result<u64, Status> {
63 let mut size = 0;
64 let status = unsafe { sys::mx_vmo_get_size(self.raw_handle(), &mut size) };
65 into_result(status, || size)
66 }
67
68 pub fn set_size(&self, size: u64) -> Result<(), Status> {
72 let status = unsafe { sys::mx_vmo_set_size(self.raw_handle(), size) };
73 into_result(status, || ())
74 }
75
76 pub fn op_range(&self, op: VmoOp, offset: u64, size: u64) -> Result<(), Status> {
82 let status = unsafe {
83 sys::mx_vmo_op_range(self.raw_handle(), op as u32, offset, size, ptr::null_mut(), 0)
84 };
85 into_result(status, || ())
86 }
87
88 pub fn lookup(&self, offset: u64, size: u64, buffer: &mut [sys::mx_paddr_t])
95 -> Result<(), Status>
96 {
97 let status = unsafe {
98 sys::mx_vmo_op_range(self.raw_handle(), sys::MX_VMO_OP_LOOKUP, offset, size,
99 buffer.as_mut_ptr() as *mut u8, buffer.len() * mem::size_of::<sys::mx_paddr_t>())
100 };
101 into_result(status, || ())
102 }
103
104 pub fn clone(&self, options: VmoCloneOpts, offset: u64, size: u64) -> Result<Vmo, Status> {
110 let mut out = 0;
111 let status = unsafe {
112 sys::mx_vmo_clone(self.raw_handle(), options as u32, offset, size, &mut out)
113 };
114 into_result(status, || Vmo::from(Handle(out)))
115 }
116}
117
118#[repr(u32)]
120#[derive(Debug, Copy, Clone, Eq, PartialEq)]
121pub enum VmoOpts {
122 Default = 0,
124}
125
126impl Default for VmoOpts {
127 fn default() -> Self {
128 VmoOpts::Default
129 }
130}
131
132#[repr(u32)]
133#[derive(Debug, Copy, Clone, Eq, PartialEq)]
134pub enum VmoOp {
135 Commit = sys::MX_VMO_OP_COMMIT,
137 Decommit = sys::MX_VMO_OP_DECOMMIT,
139 Lock = sys::MX_VMO_OP_LOCK,
141 Unlock = sys::MX_VMO_OP_UNLOCK,
143 CacheSync = sys::MX_VMO_OP_CACHE_SYNC,
145 CacheInvalidate = sys::MX_VMO_OP_CACHE_INVALIDATE,
147 CacheClean = sys::MX_VMO_OP_CACHE_CLEAN,
149 CacheCleanInvalidate = sys::MX_VMO_OP_CACHE_CLEAN_INVALIDATE,
151}
152
153#[repr(u32)]
154#[derive(Debug, Copy, Clone, Eq, PartialEq)]
155pub enum VmoCloneOpts {
156 CopyOnWrite = sys::MX_VMO_CLONE_COPY_ON_WRITE,
158}
159
160impl Default for VmoCloneOpts {
161 fn default() -> Self {
162 VmoCloneOpts::CopyOnWrite
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[test]
171 fn vmo_get_size() {
172 let size = 16 * 1024 * 1024;
173 let vmo = Vmo::create(size, VmoOpts::Default).unwrap();
174 assert_eq!(size, vmo.get_size().unwrap());
175 }
176
177 #[test]
178 fn vmo_set_size() {
179 let start_size = 12;
180 let vmo = Vmo::create(start_size, VmoOpts::Default).unwrap();
181 assert_eq!(start_size, vmo.get_size().unwrap());
182
183 let new_size = 23;
185 assert!(vmo.set_size(new_size).is_ok());
186 assert_eq!(new_size, vmo.get_size().unwrap());
187 }
188
189 #[test]
190 fn vmo_read_write() {
191 let mut vec1 = vec![0; 16];
192 let vmo = Vmo::create(vec1.len() as u64, VmoOpts::Default).unwrap();
193 assert_eq!(vmo.write(b"abcdef", 0), Ok(6));
194 assert_eq!(16, vmo.read(&mut vec1, 0).unwrap());
195 assert_eq!(b"abcdef", &vec1[0..6]);
196 assert_eq!(vmo.write(b"123", 2), Ok(3));
197 assert_eq!(16, vmo.read(&mut vec1, 0).unwrap());
198 assert_eq!(b"ab123f", &vec1[0..6]);
199 assert_eq!(15, vmo.read(&mut vec1, 1).unwrap());
200 assert_eq!(b"b123f", &vec1[0..5]);
201 }
202
203 #[test]
204 fn vmo_op_range_unsupported() {
205 let vmo = Vmo::create(12, VmoOpts::Default).unwrap();
206 assert_eq!(vmo.op_range(VmoOp::Lock, 0, 1), Err(Status::ErrNotSupported));
207 assert_eq!(vmo.op_range(VmoOp::Unlock, 0, 1), Err(Status::ErrNotSupported));
208 }
209
210 #[test]
211 fn vmo_lookup() {
212 let vmo = Vmo::create(12, VmoOpts::Default).unwrap();
213 let mut buffer = vec![0; 2];
214
215 assert_eq!(vmo.lookup(0, 12, &mut buffer), Err(Status::ErrNoMemory));
217
218 assert_eq!(vmo.op_range(VmoOp::Commit, 0, 12), Ok(()));
220 assert_eq!(vmo.lookup(0, 12, &mut buffer), Ok(()));
221 assert_ne!(buffer[0], 0);
222 assert_eq!(buffer[1], 0);
223
224 assert_eq!(vmo.op_range(VmoOp::Decommit, 0, 12), Ok(()));
226 assert_eq!(vmo.lookup(0, 12, &mut buffer), Err(Status::ErrNoMemory));
227 }
228
229 #[test]
230 fn vmo_cache() {
231 let vmo = Vmo::create(12, VmoOpts::Default).unwrap();
232
233 assert_eq!(vmo.op_range(VmoOp::CacheSync, 0, 12), Ok(()));
235 assert_eq!(vmo.op_range(VmoOp::CacheInvalidate, 0, 12), Ok(()));
236 assert_eq!(vmo.op_range(VmoOp::CacheClean, 0, 12), Ok(()));
237 assert_eq!(vmo.op_range(VmoOp::CacheCleanInvalidate, 0, 12), Ok(()));
238 }
239
240 #[test]
241 fn vmo_clone() {
242 let original = Vmo::create(12, VmoOpts::Default).unwrap();
243 assert_eq!(original.write(b"one", 0), Ok(3));
244
245 let clone = original.clone(VmoCloneOpts::CopyOnWrite, 0, 10).unwrap();
247 let mut read_buffer = vec![0; 16];
248 assert_eq!(clone.read(&mut read_buffer, 0), Ok(10));
249 assert_eq!(&read_buffer[0..3], b"one");
250
251 assert_eq!(original.write(b"two", 0), Ok(3));
253 assert_eq!(original.read(&mut read_buffer, 0), Ok(12));
254 assert_eq!(&read_buffer[0..3], b"two");
255 assert_eq!(clone.read(&mut read_buffer, 0), Ok(10));
256 assert_eq!(&read_buffer[0..3], b"two");
257
258 assert_eq!(clone.write(b"three", 0), Ok(5));
260 assert_eq!(original.read(&mut read_buffer, 0), Ok(12));
261 assert_eq!(&read_buffer[0..3], b"two");
262 assert_eq!(clone.read(&mut read_buffer, 0), Ok(10));
263 assert_eq!(&read_buffer[0..5], b"three");
264
265 assert_eq!(original.write(b"four", 0), Ok(4));
268 assert_eq!(original.read(&mut read_buffer, 0), Ok(12));
269 assert_eq!(&read_buffer[0..4], b"four");
270 assert_eq!(clone.read(&mut read_buffer, 0), Ok(10));
271 assert_eq!(&read_buffer[0..5], b"three");
272 }
273}