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