Skip to main content

syscall/
schemev2.rs

1use core::{
2    mem,
3    ops::{Deref, DerefMut},
4    slice,
5};
6
7use bitflags::bitflags;
8
9pub struct CallerCtx {
10    pub pid: usize,
11    pub uid: u32,
12    pub gid: u32,
13}
14
15pub enum OpenResult {
16    ThisScheme { number: usize },
17    OtherScheme { fd: usize },
18}
19
20#[repr(C)]
21#[derive(Clone, Copy, Debug, Default)]
22pub struct Sqe {
23    pub opcode: u8,
24    pub sqe_flags: SqeFlags,
25    pub _rsvd: u16, // TODO: priority
26    pub tag: u32,
27    pub args: [u64; 6],
28    pub caller: u64,
29}
30impl Deref for Sqe {
31    type Target = [u8];
32    fn deref(&self) -> &[u8] {
33        unsafe { slice::from_raw_parts(self as *const Sqe as *const u8, mem::size_of::<Sqe>()) }
34    }
35}
36
37impl DerefMut for Sqe {
38    fn deref_mut(&mut self) -> &mut [u8] {
39        unsafe { slice::from_raw_parts_mut(self as *mut Sqe as *mut u8, mem::size_of::<Sqe>()) }
40    }
41}
42
43bitflags! {
44    #[derive(Clone, Copy, Debug, Default)]
45    pub struct SqeFlags: u8 {
46        // If zero, the message is bidirectional, and the scheme is expected to pass the Ksmsg's
47        // tag field to the Skmsg. Some opcodes require this flag to be set.
48        const ONEWAY = 1;
49    }
50}
51
52#[repr(C)]
53#[derive(Clone, Copy, Debug, Default)]
54pub struct Cqe {
55    pub flags: u8, // bits 2:0 are CqeOpcode
56    pub extra_raw: [u8; 3],
57    pub tag: u32,
58    pub result: u64,
59}
60impl Deref for Cqe {
61    type Target = [u8];
62    fn deref(&self) -> &[u8] {
63        unsafe { slice::from_raw_parts(self as *const Cqe as *const u8, mem::size_of::<Cqe>()) }
64    }
65}
66
67impl DerefMut for Cqe {
68    fn deref_mut(&mut self) -> &mut [u8] {
69        unsafe { slice::from_raw_parts_mut(self as *mut Cqe as *mut u8, mem::size_of::<Cqe>()) }
70    }
71}
72
73bitflags! {
74    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
75    pub struct NewFdFlags: u8 {
76        const POSITIONED = 1;
77    }
78}
79
80impl Cqe {
81    pub fn extra(&self) -> u32 {
82        u32::from_ne_bytes([self.extra_raw[0], self.extra_raw[1], self.extra_raw[2], 0])
83    }
84}
85
86#[repr(u8)]
87#[derive(Clone, Copy, Debug, Eq, PartialEq)]
88pub enum CqeOpcode {
89    RespondRegular,
90    RespondWithFd,
91    SendFevent, // no tag
92    ObtainFd,
93    RespondWithMultipleFds,
94    /// [`SchemeAsync::on_close`] and [`SchemeSync::on_close`] are only called when the last file
95    /// descriptor referring to the file description is closed. To implement traditional POSIX
96    /// advisory file locking, [`CqeOpcode::RespondAndNotifyOnDetach`] is used to notify the scheme
97    /// by sending a [`RequestKind::OnDetach`] request the next time the file description is
98    /// "detached" from a file descriptor. Not done by default to avoid unnecessary IPC.
99    RespondAndNotifyOnDetach,
100    // TODO: ProvideMmap
101}
102
103impl CqeOpcode {
104    pub fn try_from_raw(raw: u8) -> Option<Self> {
105        // TODO: Use a library where this match can be automated.
106        Some(match raw {
107            0 => Self::RespondRegular,
108            1 => Self::RespondWithFd,
109            2 => Self::SendFevent,
110            3 => Self::ObtainFd,
111            4 => Self::RespondWithMultipleFds,
112            5 => Self::RespondAndNotifyOnDetach,
113            _ => return None,
114        })
115    }
116}
117
118/// SqeOpcode
119#[repr(u8)]
120#[non_exhaustive]
121#[derive(Clone, Copy, Debug)]
122pub enum Opcode {
123    Close = 3,   // fd
124    Dup = 4,     // old fd, buf_ptr, buf_len
125    Read = 5,    // fd, buf_ptr, buf_len, TODO offset, TODO flags, _
126    Write = 6,   // fd, buf_ptr, buf_len, TODO offset, TODO flags)
127    Fsize = 7,   // fd
128    Fchmod = 8,  // fd, new mode
129    Fchown = 9,  // fd, new uid, new gid
130    Fcntl = 10,  // fd, cmd, arg
131    Fevent = 11, // fd, requested mask
132    Sendfd = 12,
133    Fpath = 13, // fd, buf_ptr, buf_len
134    Frename = 14,
135    Fstat = 15,     // fd, buf_ptr, buf_len
136    Fstatvfs = 16,  // fd, buf_ptr, buf_len
137    Fsync = 17,     // fd
138    Ftruncate = 18, // fd, new len
139    Futimens = 19,  // fd, times_buf, times_len
140
141    MmapPrep = 20,
142    RequestMmap = 21,
143    Mremap = 22,
144    Munmap = 23,
145    Msync = 24, // TODO
146
147    Cancel = 25, // @tag
148
149    Getdents = 26,
150    CloseMsg = 27,
151    Call = 28,
152
153    OpenAt = 29, // fd, buf_ptr, buf_len, flags
154    Flink = 30,
155    Recvfd = 31,
156
157    UnlinkAt = 32, // fd, path_ptr, path_len (utf8), flags
158    StdFsCall = 33,
159
160    Detach = 34,
161}
162
163impl Opcode {
164    pub fn try_from_raw(raw: u8) -> Option<Self> {
165        use Opcode::*;
166
167        // TODO: Use a library where this match can be automated.
168        Some(match raw {
169            3 => Close,
170            4 => Dup,
171            5 => Read,
172            6 => Write,
173            7 => Fsize,
174            8 => Fchmod,
175            9 => Fchown,
176            10 => Fcntl,
177            11 => Fevent,
178            12 => Sendfd,
179            13 => Fpath,
180            14 => Frename,
181            15 => Fstat,
182            16 => Fstatvfs,
183            17 => Fsync,
184            18 => Ftruncate,
185            19 => Futimens,
186
187            20 => MmapPrep,
188            21 => RequestMmap,
189            22 => Mremap,
190            23 => Munmap,
191            24 => Msync,
192
193            25 => Cancel,
194            26 => Getdents,
195            27 => CloseMsg,
196            28 => Call,
197
198            29 => OpenAt,
199            30 => Flink,
200            31 => Recvfd,
201
202            32 => UnlinkAt,
203            33 => StdFsCall,
204            34 => Detach,
205
206            _ => return None,
207        })
208    }
209}