Skip to main content

fake_mmio/
cached_vmo.rs

1// Copyright 2026 The Fuchsia 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//! Memory mapping utilities for cached VMOs in MMIO tests.
6
7use mmio::region::{MmioRegion, UnsafeMmio};
8use mmio::vmo::{VmoMapping, VmoMemory};
9
10use crate::atomic::{AtomicMmioPtr, AtomicOperand};
11
12/// A wrapper around [`VmoMemory`] guaranteed to be mapped with cached memory
13/// policy.
14pub struct CachedVmoMemory(VmoMemory);
15
16impl CachedVmoMemory {
17    /// Creates a new cached vmo memory from mapped memory.
18    ///
19    /// # Safety
20    ///
21    /// The caller must ensure that the mapped VMO is mapped with
22    /// `zx::CachePolicy::Cached`.
23    pub unsafe fn new_unchecked(inner: VmoMemory) -> Self {
24        Self(inner)
25    }
26
27    /// Returns the contained mapped VMO.
28    pub fn get(&self) -> &VmoMemory {
29        &self.0
30    }
31
32    /// Maps `vmo` at `offset` with `size` ensuring the correct cache policy.
33    pub fn map(offset: usize, size: usize, vmo: zx::Vmo) -> Result<MmioRegion<Self>, zx::Status> {
34        let region = VmoMapping::map_with_cache_policy(offset, size, vmo, zx::CachePolicy::Cached)?;
35        Ok(region.map(Self))
36    }
37
38    /// Creates a new VMO of `size` bytes and maps it into memory with cached
39    /// cache policy.
40    pub fn new_mapped(size: usize) -> Result<MmioRegion<Self>, zx::Status> {
41        let size_u64 = u64::try_from(size).map_err(|_| zx::Status::OUT_OF_RANGE)?;
42        let vmo = zx::Vmo::create(size_u64)?;
43        Self::map(0, size, vmo)
44    }
45}
46
47impl UnsafeMmio for CachedVmoMemory {
48    fn len(&self) -> usize {
49        self.0.len()
50    }
51
52    fn align_offset(&self, align: usize) -> usize {
53        self.0.align_offset(align)
54    }
55
56    unsafe fn load8_unchecked(&self, offset: usize) -> u8 {
57        // SAFETY: Passthrough from caller.
58        unsafe { self.0.load8_unchecked(offset) }
59    }
60
61    unsafe fn load16_unchecked(&self, offset: usize) -> u16 {
62        // SAFETY: Passthrough from caller.
63        unsafe { self.0.load16_unchecked(offset) }
64    }
65
66    unsafe fn load32_unchecked(&self, offset: usize) -> u32 {
67        // SAFETY: Passthrough from caller.
68        unsafe { self.0.load32_unchecked(offset) }
69    }
70
71    unsafe fn load64_unchecked(&self, offset: usize) -> u64 {
72        // SAFETY: Passthrough from caller.
73        unsafe { self.0.load64_unchecked(offset) }
74    }
75
76    unsafe fn store8_unchecked(&self, offset: usize, v: u8) {
77        // SAFETY: Passthrough from caller.
78        unsafe { self.0.store8_unchecked(offset, v) }
79    }
80
81    unsafe fn store16_unchecked(&self, offset: usize, v: u16) {
82        // SAFETY: Passthrough from caller.
83        unsafe { self.0.store16_unchecked(offset, v) }
84    }
85
86    unsafe fn store32_unchecked(&self, offset: usize, v: u32) {
87        // SAFETY: Passthrough from caller.
88        unsafe { self.0.store32_unchecked(offset, v) }
89    }
90
91    unsafe fn store64_unchecked(&self, offset: usize, v: u64) {
92        // SAFETY: Passthrough from caller.
93        unsafe { self.0.store64_unchecked(offset, v) }
94    }
95
96    fn write_barrier(&self) {
97        self.0.write_barrier()
98    }
99
100    fn read_barrier(&self) {
101        self.0.read_barrier()
102    }
103}
104
105impl AtomicMmioPtr for CachedVmoMemory {
106    fn ptr<T: AtomicOperand>(&self, offset: usize) -> std::ptr::NonNull<T> {
107        self.0.ptr(offset)
108    }
109}