twizzler_abi/syscall/
map_control.rs

1use core::sync::atomic::{AtomicU64, Ordering};
2
3use twizzler_rt_abi::{
4    error::{ArgumentError, RawTwzError, ResourceError, TwzError},
5    Result,
6};
7
8use super::{convert_codes_to_result, twzerr, Syscall};
9use crate::arch::syscall::raw_syscall;
10
11bitflags::bitflags! {
12    /// Flags for a sync command.
13    #[derive(Debug, Clone, Copy)]
14    pub struct SyncFlags: u32 {
15        /// Sync updates to durable storage
16        const DURABLE = 1 << 0;
17        /// Write release before triggering durable writeback
18        const ASYNC_DURABLE = 1 << 0;
19    }
20}
21
22/// Parameters for the kernel for syncing a mapping.
23#[derive(Debug, Clone, Copy)]
24pub struct SyncInfo {
25    /// Pointer to the wait word for transaction completion.
26    pub release: *const AtomicU64,
27    /// Value to compare against the wait word.
28    pub release_compare: u64,
29    /// Value to set if the wait word matches the compare value.
30    pub release_set: u64,
31    /// Pointer to wait word for durability return value.
32    pub durable: *const AtomicU64,
33    /// Flags for this sync command.
34    pub flags: SyncFlags,
35}
36
37unsafe impl Send for SyncInfo {}
38unsafe impl Sync for SyncInfo {}
39
40impl SyncInfo {
41    pub unsafe fn try_release(&self) -> Result<()> {
42        self.release
43            .as_ref()
44            .unwrap()
45            .compare_exchange(
46                self.release_compare,
47                self.release_set,
48                Ordering::SeqCst,
49                Ordering::SeqCst,
50            )
51            .map_err(|_| TwzError::Resource(ResourceError::Refused))
52            .map(|_| ())
53    }
54
55    pub unsafe fn set_durable(&self, err: impl Into<RawTwzError>) {
56        if self.durable.is_null() {
57            return;
58        }
59
60        self.durable
61            .as_ref()
62            .unwrap()
63            .store(err.into().raw(), Ordering::SeqCst);
64    }
65}
66
67/// Possible map control commands for [sys_map_ctrl].
68#[derive(Clone, Copy, Debug)]
69pub enum MapControlCmd {
70    /// Sync an entire mapping
71    Sync(*const SyncInfo),
72    /// Discard a mapping
73    Discard,
74    /// Invalidate a mapping
75    Invalidate,
76    /// Update a mapping
77    Update,
78}
79
80impl From<MapControlCmd> for (u64, u64) {
81    fn from(c: MapControlCmd) -> Self {
82        match c {
83            MapControlCmd::Sync(x) => (0, x.addr() as u64),
84            MapControlCmd::Discard => (1, 0),
85            MapControlCmd::Invalidate => (2, 0),
86            MapControlCmd::Update => (3, 0),
87        }
88    }
89}
90
91impl TryFrom<(u64, u64)> for MapControlCmd {
92    type Error = TwzError;
93    fn try_from(value: (u64, u64)) -> Result<Self> {
94        Ok(match value.0 {
95            0 => MapControlCmd::Sync((value.1 as usize) as *const SyncInfo),
96            1 => MapControlCmd::Discard,
97            2 => MapControlCmd::Invalidate,
98            3 => MapControlCmd::Update,
99            _ => return Err(ArgumentError::InvalidArgument.into()),
100        })
101    }
102}
103
104/// Perform a kernel operation on this mapping.
105pub fn sys_map_ctrl(start: *const u8, len: usize, cmd: MapControlCmd, opts2: u64) -> Result<()> {
106    let (cmd, opts) = cmd.into();
107    let args = [start.addr() as u64, len as u64, cmd, opts, opts2];
108    let (code, val) = unsafe { raw_syscall(Syscall::MapCtrl, &args) };
109    convert_codes_to_result(code, val, |c, _| c != 0, |_, _| (), twzerr)
110}