1use crate::arch_vm_aspace::ArchMmuFlags;
6use crate::vm_mapping::VmMapping;
7use crate::vm_object::VmObject;
8use core::ffi::{CStr, c_char};
9use core::marker::{PhantomData, PhantomPinned};
10use core::ptr::NonNull;
11use fbl::RefPtr;
12use kalloc::AllocError;
13use kernel::types::VAddr;
14use zx_status::Status;
15
16pub const VMAR_FLAG_COMPACT: u32 = 1 << 0;
18pub const VMAR_FLAG_SPECIFIC: u32 = 1 << 1;
20pub const VMAR_FLAG_SPECIFIC_OVERWRITE: u32 = 1 << 2;
22pub const VMAR_FLAG_CAN_MAP_SPECIFIC: u32 = 1 << 3;
24pub const VMAR_FLAG_CAN_MAP_READ: u32 = 1 << 4;
26pub const VMAR_FLAG_CAN_MAP_WRITE: u32 = 1 << 5;
28pub const VMAR_FLAG_CAN_MAP_EXECUTE: u32 = 1 << 6;
30pub const VMAR_FLAG_REQUIRE_NON_RESIZABLE: u32 = 1 << 7;
32pub const VMAR_FLAG_ALLOW_FAULTS: u32 = 1 << 8;
34pub const VMAR_FLAG_OFFSET_IS_UPPER_LIMIT: u32 = 1 << 9;
36pub const VMAR_FLAG_DEBUG_DYNAMIC_KERNEL_MAPPING: u32 = 1 << 10;
38pub const VMAR_FLAG_FAULT_BEYOND_STREAM_SIZE: u32 = 1 << 11;
40
41pub const VMAR_CAN_RWX_FLAGS: u32 =
43 VMAR_FLAG_CAN_MAP_READ | VMAR_FLAG_CAN_MAP_WRITE | VMAR_FLAG_CAN_MAP_EXECUTE;
44
45#[repr(u8)]
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
48pub enum MemoryPriority {
49 Default = 0,
51 High = 1,
53}
54
55#[repr(u8)]
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
58pub enum VmAddressRegionOpChildren {
59 Yes = 0,
60 No = 1,
61}
62
63const _: () = assert!(core::mem::size_of::<MemoryPriority>() == 1);
65const _: () = assert!(core::mem::size_of::<VmAddressRegionOpChildren>() == 1);
66
67pub struct MapResult {
69 pub mapping: RefPtr<VmMapping>,
71 pub base: usize,
73}
74
75unsafe extern "C" {
76 fn cpp_vm_address_region_get_ref_counted(vmar: *mut VmAddressRegion) -> *mut fbl::RefCounted;
77 fn cpp_vm_address_region_free(vmar: *mut VmAddressRegion);
78 fn cpp_vm_address_region_destroy(vmar: *mut VmAddressRegion) -> i32;
79 fn cpp_vm_address_region_base(vmar: *mut VmAddressRegion) -> VAddr;
80 fn cpp_vm_address_region_size(vmar: *mut VmAddressRegion) -> usize;
81 fn cpp_vm_address_region_flags(vmar: *mut VmAddressRegion) -> u32;
82 fn cpp_vm_address_region_name(vmar: *mut VmAddressRegion) -> *const c_char;
83 fn cpp_vm_address_region_has_parent(vmar: *mut VmAddressRegion) -> bool;
84 fn cpp_vm_address_region_set_memory_priority(
85 vmar: *mut VmAddressRegion,
86 priority: MemoryPriority,
87 ) -> i32;
88 fn cpp_vm_address_region_unmap(
89 vmar: *mut VmAddressRegion,
90 base: VAddr,
91 size: usize,
92 op_children: VmAddressRegionOpChildren,
93 ) -> i32;
94 fn cpp_vm_address_region_protect(
95 vmar: *mut VmAddressRegion,
96 base: VAddr,
97 size: usize,
98 new_arch_mmu_flags: ArchMmuFlags,
99 op_children: VmAddressRegionOpChildren,
100 ) -> i32;
101 fn cpp_vm_address_region_reserve_space(
102 vmar: *mut VmAddressRegion,
103 name: *const c_char,
104 base: usize,
105 size: usize,
106 arch_mmu_flags: ArchMmuFlags,
107 ) -> i32;
108 fn cpp_vm_address_region_create_sub_vmar(
109 vmar: *mut VmAddressRegion,
110 offset: usize,
111 size: usize,
112 align_pow2: u8,
113 vmar_flags: u32,
114 name: *const c_char,
115 out_status: *mut i32,
116 ) -> *mut VmAddressRegion;
117 fn cpp_vm_address_region_create_vm_mapping(
118 vmar: *mut VmAddressRegion,
119 mapping_offset: usize,
120 size: usize,
121 align_pow2: u8,
122 vmar_flags: u32,
123 vmo: *const VmObject,
124 vmo_offset: u64,
125 arch_mmu_flags: ArchMmuFlags,
126 name: *const c_char,
127 out_base: *mut usize,
128 out_status: *mut i32,
129 ) -> *mut VmMapping;
130}
131
132#[repr(C)]
134pub struct VmAddressRegion {
135 _data: [u8; 0],
136 _marker: PhantomData<PhantomPinned>,
137}
138
139impl VmAddressRegion {
140 fn as_mut_ptr(&self) -> *mut VmAddressRegion {
141 self as *const VmAddressRegion as *mut VmAddressRegion
142 }
143
144 pub fn create_sub_vmar(
146 &self,
147 offset: usize,
148 size: usize,
149 align_pow2: u8,
150 vmar_flags: u32,
151 name: &CStr,
152 ) -> Result<RefPtr<VmAddressRegion>, Status> {
153 let mut status = 0;
154 let raw = unsafe {
155 cpp_vm_address_region_create_sub_vmar(
156 self.as_mut_ptr(),
157 offset,
158 size,
159 align_pow2,
160 vmar_flags,
161 name.as_ptr(),
162 &mut status,
163 )
164 };
165 Status::ok(status)?;
166 unsafe { RefPtr::try_from_raw(raw).ok_or(Status::NO_MEMORY) }
167 }
168
169 pub fn create_vm_mapping(
174 &self,
175 mapping_offset: usize,
176 size: usize,
177 align_pow2: u8,
178 vmar_flags: u32,
179 vmo: RefPtr<VmObject>,
180 vmo_offset: u64,
181 arch_mmu_flags: ArchMmuFlags,
182 name: &CStr,
183 ) -> Result<MapResult, Status> {
184 let mut base = 0;
185 let mut status = 0;
186 let raw = unsafe {
187 cpp_vm_address_region_create_vm_mapping(
188 self.as_mut_ptr(),
189 mapping_offset,
190 size,
191 align_pow2,
192 vmar_flags,
193 RefPtr::into_raw(vmo),
194 vmo_offset,
195 arch_mmu_flags,
196 name.as_ptr(),
197 &mut base,
198 &mut status,
199 )
200 };
201 Status::ok(status)?;
202 let mapping = unsafe { RefPtr::try_from_raw(raw).ok_or(Status::NO_MEMORY)? };
203 Ok(MapResult { mapping, base })
204 }
205
206 pub fn destroy(&self) -> Result<(), Status> {
208 Status::ok(unsafe { cpp_vm_address_region_destroy(self.as_mut_ptr()) })
209 }
210
211 pub fn base(&self) -> VAddr {
213 unsafe { cpp_vm_address_region_base(self.as_mut_ptr()) }
214 }
215
216 pub fn size(&self) -> usize {
218 unsafe { cpp_vm_address_region_size(self.as_mut_ptr()) }
219 }
220
221 pub fn flags(&self) -> u32 {
223 unsafe { cpp_vm_address_region_flags(self.as_mut_ptr()) }
224 }
225
226 pub fn name(&self) -> &CStr {
228 unsafe { CStr::from_ptr(cpp_vm_address_region_name(self.as_mut_ptr())) }
229 }
230
231 pub fn has_parent(&self) -> bool {
233 unsafe { cpp_vm_address_region_has_parent(self.as_mut_ptr()) }
234 }
235
236 pub fn set_memory_priority(&self, priority: MemoryPriority) -> Result<(), Status> {
238 Status::ok(unsafe {
239 cpp_vm_address_region_set_memory_priority(self.as_mut_ptr(), priority)
240 })
241 }
242
243 pub unsafe fn unmap(
249 &self,
250 base: VAddr,
251 size: usize,
252 op_children: VmAddressRegionOpChildren,
253 ) -> Result<(), Status> {
254 Status::ok(unsafe {
255 cpp_vm_address_region_unmap(self.as_mut_ptr(), base, size, op_children)
256 })
257 }
258
259 pub fn protect(
261 &self,
262 base: VAddr,
263 size: usize,
264 new_arch_mmu_flags: ArchMmuFlags,
265 op_children: VmAddressRegionOpChildren,
266 ) -> Result<(), Status> {
267 Status::ok(unsafe {
268 cpp_vm_address_region_protect(
269 self.as_mut_ptr(),
270 base,
271 size,
272 new_arch_mmu_flags,
273 op_children,
274 )
275 })
276 }
277
278 pub fn reserve_space(
280 &self,
281 name: &CStr,
282 base: usize,
283 size: usize,
284 arch_mmu_flags: ArchMmuFlags,
285 ) -> Result<(), Status> {
286 Status::ok(unsafe {
287 cpp_vm_address_region_reserve_space(
288 self.as_mut_ptr(),
289 name.as_ptr(),
290 base,
291 size,
292 arch_mmu_flags,
293 )
294 })
295 }
296}
297
298impl fbl::HasRefCount for VmAddressRegion {
299 fn ref_count(&self) -> &fbl::RefCounted {
300 unsafe { &*cpp_vm_address_region_get_ref_counted(self.as_mut_ptr()) }
301 }
302}
303
304unsafe impl fbl::Recyclable for VmAddressRegion {
305 unsafe fn recycle(ptr: NonNull<Self>) {
306 unsafe {
307 cpp_vm_address_region_free(ptr.as_ptr());
308 }
309 }
310
311 fn allocate(_value: Self) -> Result<NonNull<Self>, AllocError> {
312 Err(AllocError)
313 }
314}