diff --git a/Cargo.lock b/Cargo.lock index 9c74e5103ef6b95bba1a66f32ceb1fab3cf78426..cb9e4a835cbb5f8cc9dfcc0ac9b0b9ce33cd1e33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,21 +4,21 @@ version = 3 [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "309ba69985d5170852ebbe8fbb33850d20794d0aed5b210dfea2db798df64e10" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags", "libc", @@ -35,9 +35,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c178f952cc7eac391f3124bd9851d1ac0bdbc4c9de2d892ccd5f0d8b160e96" +version = "0.5.1" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index c41fe90cc73ec25475f67e200292fbdb5856762b..5f4229473633fc63b5a9b385917b91e7df5c22f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,7 @@ description = "Library for writing Redox scheme daemons" [dependencies] redox_syscall = "0.5" -libredox = "0.1.2" +libredox = "0.1.3" + +[patch.crates-io] +redox_syscall = { path = "/home/dev/Projects/redox1/cookbook/recipes/core/kernel/source/syscall" } diff --git a/src/lib.rs b/src/lib.rs index 4e2291a8c1ba941d51a9d8d27d0f66fdf63eaf81..93fd9050b3e2f06683181e4a274b8297e2bef5cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use core::{slice, str}; use libredox::flag; +use syscall::schemev2::{Cqe, CqeOpcode, Opcode, Sqe}; use syscall::{ Error, Packet, Result, EINTR, EOPNOTSUPP, ESKMSG, KSMSG_CANCEL, KSMSG_MMAP, KSMSG_MSYNC, KSMSG_MUNMAP, SKMSG_FRETURNFD, @@ -81,12 +82,107 @@ use core::mem::size_of; #[repr(transparent)] #[derive(Clone, Copy, Debug, Default)] -pub struct Request { - packet: Packet, +pub struct Request<V: Version = V2> { + sqe: V::RawSqe, +} +mod private { + use super::*; + + pub trait Impl: Copy + Clone + core::fmt::Debug + Default { + type RawSqe: core::fmt::Debug + Clone + Copy + Default; + type RawCqe: core::fmt::Debug + Clone + Copy + Default; + + fn sqe_context_id(s: &Self::RawSqe) -> usize; + fn sqe_request_id(s: &Self::RawSqe) -> Id; + fn sqe_kind(s: Self::RawSqe) -> RequestKind<Self>; + + fn create_cqe(req: &CallRequest<Self>, status: Result<usize>) -> Self::RawCqe; + } +} +pub trait Version: private::Impl {} + +#[derive(Clone, Copy, Debug)] +pub enum Legacy {} +#[derive(Clone, Copy, Debug)] +pub enum V2 {} +impl Default for Legacy { + fn default() -> Self { + unreachable!() + } +} +impl Default for V2 { + fn default() -> Self { + unreachable!() + } +} +impl<V: private::Impl> Version for V {} + +impl private::Impl for Legacy { + type RawSqe = Packet; + type RawCqe = Packet; + + fn sqe_context_id(s: &Packet) -> usize { + s.pid + } + fn sqe_request_id(s: &Packet) -> Id { + Id(s.id as u32) + } + fn sqe_kind(packet: Self::RawSqe) -> RequestKind<Self> { + // TODO: Should KSMSG_MMAP_PREP be a regular scheme call? + + match packet.a { + KSMSG_CANCEL => RequestKind::Cancellation(CancellationRequest { + id: Id(packet.b as u32), + }), + KSMSG_MSYNC => RequestKind::MsyncMsg, + KSMSG_MUNMAP => RequestKind::MunmapMsg, + KSMSG_MMAP => RequestKind::MmapMsg, + + _ => RequestKind::Call(CallRequest { inner: Request { sqe: packet } }), + } + } + fn create_cqe(req: &CallRequest<Self>, status: Result<usize>) -> Packet { + Packet { + a: Error::mux(status), + id: req.inner.sqe.id, + ..Packet::default() + } + } +} +impl private::Impl for V2 { + type RawSqe = Sqe; + type RawCqe = Cqe; + + fn sqe_context_id(s: &Sqe) -> usize { + s.caller as usize + } + fn sqe_request_id(s: &Sqe) -> Id { + Id(s.tag) + } + fn sqe_kind(sqe: Self::RawSqe) -> RequestKind<Self> { + match Opcode::try_from_raw(sqe.opcode) { + Some(Opcode::Cancel) => RequestKind::Cancellation(CancellationRequest { + id: Id(sqe.tag), + }), + Some(Opcode::Msync) => RequestKind::MsyncMsg, + Some(Opcode::Munmap) => RequestKind::MunmapMsg, + Some(Opcode::RequestMmap) => RequestKind::MmapMsg, + + _ => RequestKind::Call(CallRequest { inner: Request { sqe } }), + } + } + fn create_cqe(req: &CallRequest<Self>, status: Result<usize>) -> Cqe { + Cqe { + flags: CqeOpcode::RespondRegular as u8, + extra_raw: [0_u8; 3], + result: Error::mux(status) as u64, + tag: req.inner.sqe.tag, + } + } } #[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)] -pub struct Id(u64); +pub struct Id(u32); #[derive(Debug)] pub struct CancellationRequest { @@ -95,12 +191,12 @@ pub struct CancellationRequest { #[repr(transparent)] #[derive(Clone, Copy, Debug)] -pub struct CallRequest { - inner: Request, +pub struct CallRequest<V: Version = V2> { + inner: Request<V>, } -pub enum RequestKind { - Call(CallRequest), +pub enum RequestKind<V: Version = V2> { + Call(CallRequest<V>), Cancellation(CancellationRequest), MsyncMsg, MunmapMsg, @@ -113,63 +209,54 @@ impl CallRequest { self.inner } - pub fn handle_scheme(mut self, scheme: &impl Scheme) -> Response { +} +impl CallRequest<Legacy> { + pub fn handle_scheme(mut self, scheme: &impl Scheme) -> Response<Legacy> { unsafe { - scheme.handle(&mut self.inner.packet); + scheme.handle(&mut self.inner.sqe); } - Response(self.inner.packet) + Response::<Legacy>(self.inner.sqe) } - pub fn handle_scheme_mut(mut self, scheme: &mut impl SchemeMut) -> Response { + pub fn handle_scheme_mut(mut self, scheme: &mut impl SchemeMut) -> Response<Legacy> { unsafe { - scheme.handle(&mut self.inner.packet); + scheme.handle(&mut self.inner.sqe); } - Response(self.inner.packet) + Response::<Legacy>(self.inner.sqe) } - pub fn handle_scheme_block(mut self, scheme: &mut impl SchemeBlock) -> Result<Response, Self> { - match unsafe { scheme.handle(&self.inner.packet) } { - Some(code) => Ok(Response(Packet { + pub fn handle_scheme_block(self, scheme: &mut impl SchemeBlock) -> Result<Response<Legacy>, Self> { + match unsafe { scheme.handle(&self.inner.sqe) } { + Some(code) => Ok(Response::<Legacy>(Packet { a: code, - ..self.inner.packet + ..self.inner.sqe })), None => Err(self), } } pub fn handle_scheme_block_mut( - mut self, + self, scheme: &mut impl SchemeBlockMut, - ) -> Result<Response, Self> { - match unsafe { scheme.handle(&self.inner.packet) } { - Some(code) => Ok(Response(Packet { + ) -> Result<Response<Legacy>, Self> { + match unsafe { scheme.handle(&self.inner.sqe) } { + Some(code) => Ok(Response::<Legacy>(Packet { a: code, - ..self.inner.packet + ..self.inner.sqe })), None => Err(self), } } } -impl Request { +impl<V: Version> Request<V> { #[inline] pub fn context_id(&self) -> usize { - self.packet.pid + V::sqe_context_id(&self.sqe) } #[inline] pub fn request_id(&self) -> Id { - Id(self.packet.id) + V::sqe_request_id(&self.sqe) } - pub fn kind(self) -> RequestKind { - // TODO: Should KSMSG_MMAP_PREP be a regular scheme call? - - match self.packet.a { - KSMSG_CANCEL => RequestKind::Cancellation(CancellationRequest { - id: Id((self.packet.b as u64) | ((self.packet.c as u64) << 32)), - }), - KSMSG_MSYNC => RequestKind::MsyncMsg, - KSMSG_MUNMAP => RequestKind::MunmapMsg, - KSMSG_MMAP => RequestKind::MmapMsg, - - _ => RequestKind::Call(CallRequest { inner: self }), - } + pub fn kind(self) -> RequestKind<V> { + V::sqe_kind(self.sqe) } } @@ -230,14 +317,11 @@ impl Socket { #[repr(transparent)] #[derive(Clone, Copy, Default)] -pub struct Response(Packet); +pub struct Response<V: Version = V2>(V::RawCqe); -impl Response { - pub fn new(req: &CallRequest, status: Result<usize>) -> Self { - Self(Packet { - a: Error::mux(status), - ..req.inner.packet - }) +impl<V: Version> Response<V> { + pub fn new(req: &CallRequest<V>, status: Result<usize>) -> Self { + Self(V::create_cqe(req, status)) } } @@ -248,9 +332,9 @@ pub enum SignalBehavior { // TODO: Support uninitialized memory #[inline] -pub fn read_requests( +pub fn read_requests<V: Version>( socket: usize, - buf: &mut [Request], + buf: &mut [Request<V>], behavior: SignalBehavior, ) -> Result<usize> { let len = buf.len().checked_mul(size_of::<Request>()).unwrap();