openvm_circuit/system/memory/online/
memmap.rs1use std::{
2 fmt::Debug,
3 mem::{align_of, size_of, size_of_val},
4};
5
6use memmap2::MmapMut;
7
8use super::{LinearMemory, PAGE_SIZE};
9
10pub const CELL_STRIDE: usize = 1;
11
12#[derive(Debug)]
14pub struct MmapMemory {
15 mmap: MmapMut,
16}
17
18impl Clone for MmapMemory {
19 fn clone(&self) -> Self {
20 let mut new_mmap = MmapMut::map_anon(self.mmap.len()).unwrap();
21 new_mmap.copy_from_slice(&self.mmap);
22 Self { mmap: new_mmap }
23 }
24}
25
26impl MmapMemory {
27 #[inline(always)]
28 pub fn as_ptr(&self) -> *const u8 {
29 self.mmap.as_ptr()
30 }
31
32 #[inline(always)]
33 pub fn as_mut_ptr(&mut self) -> *mut u8 {
34 self.mmap.as_mut_ptr()
35 }
36
37 #[cfg(not(feature = "unprotected"))]
38 #[inline(always)]
39 fn check_bounds(&self, start: usize, size: usize) {
40 let memory_size = self.size();
41 if start > memory_size || size > memory_size - start {
42 panic_oob(start, size, memory_size);
43 }
44 }
45
46 #[cfg(feature = "unprotected")]
47 #[inline(always)]
48 fn check_bounds(&self, start: usize, size: usize) {
49 let memory_size = self.size();
50 debug_assert!(
51 start <= memory_size && size <= memory_size - start,
52 "Memory access out of bounds: start={} size={} memory_size={}",
53 start,
54 size,
55 memory_size
56 );
57 }
58}
59
60impl LinearMemory for MmapMemory {
61 fn new(mut size: usize) -> Self {
64 size = size.div_ceil(PAGE_SIZE) * PAGE_SIZE;
65 Self {
67 mmap: MmapMut::map_anon(size).unwrap(),
68 }
69 }
70
71 fn size(&self) -> usize {
72 self.mmap.len()
73 }
74
75 fn as_slice(&self) -> &[u8] {
76 &self.mmap
77 }
78
79 fn as_mut_slice(&mut self) -> &mut [u8] {
80 &mut self.mmap
81 }
82
83 #[cfg(target_os = "linux")]
84 fn fill_zero(&mut self) {
85 use libc::{madvise, MADV_DONTNEED};
86
87 let mmap = &mut self.mmap;
88 unsafe {
98 let ret = madvise(
99 mmap.as_ptr() as *mut libc::c_void,
100 mmap.len(),
101 MADV_DONTNEED,
102 );
103 if ret != 0 {
104 std::ptr::write_bytes(mmap.as_mut_ptr(), 0, mmap.len());
106 }
107 }
108 }
109
110 #[inline(always)]
111 unsafe fn read<BLOCK: Copy>(&self, from: usize) -> BLOCK {
112 self.check_bounds(from, size_of::<BLOCK>());
113 let src = self.as_ptr().add(from) as *const BLOCK;
114 core::ptr::read(src)
120 }
121
122 #[inline(always)]
123 unsafe fn read_unaligned<BLOCK: Copy>(&self, from: usize) -> BLOCK {
124 self.check_bounds(from, size_of::<BLOCK>());
125 let src = self.as_ptr().add(from) as *const BLOCK;
126 core::ptr::read_unaligned(src)
131 }
132
133 #[inline(always)]
134 unsafe fn write<BLOCK: Copy>(&mut self, start: usize, values: BLOCK) {
135 self.check_bounds(start, size_of::<BLOCK>());
136 let dst = self.as_mut_ptr().add(start) as *mut BLOCK;
137 core::ptr::write(dst, values);
141 }
142
143 #[inline(always)]
144 unsafe fn write_unaligned<BLOCK: Copy>(&mut self, start: usize, values: BLOCK) {
145 self.check_bounds(start, size_of::<BLOCK>());
146 let dst = self.as_mut_ptr().add(start) as *mut BLOCK;
147 core::ptr::write_unaligned(dst, values);
150 }
151
152 #[inline(always)]
153 unsafe fn swap<BLOCK: Copy>(&mut self, start: usize, values: &mut BLOCK) {
154 self.check_bounds(start, size_of::<BLOCK>());
155 core::ptr::swap(
159 self.as_mut_ptr().add(start) as *mut BLOCK,
160 values as *mut BLOCK,
161 );
162 }
163
164 #[inline(always)]
165 unsafe fn copy_nonoverlapping<T: Copy>(&mut self, to: usize, data: &[T]) {
166 self.check_bounds(to, size_of_val(data));
167 debug_assert_eq!(PAGE_SIZE % align_of::<T>(), 0);
168 let src = data.as_ptr();
169 let dst = self.as_mut_ptr().add(to) as *mut T;
170 core::ptr::copy_nonoverlapping::<T>(src, dst, data.len());
175 }
176
177 #[inline(always)]
178 unsafe fn get_aligned_slice<T: Copy>(&self, start: usize, len: usize) -> &[T] {
179 self.check_bounds(start, len * size_of::<T>());
180 let data = self.as_ptr().add(start) as *const T;
181 core::slice::from_raw_parts(data, len)
188 }
189}
190
191#[cold]
192#[inline(never)]
193fn panic_oob(start: usize, size: usize, memory_size: usize) -> ! {
194 panic!(
195 "Memory access out of bounds: start={} size={} memory_size={}",
196 start, size, memory_size
197 );
198}