From c8bb039c418d6c3f604ff078555e9dae51666fee Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sat, 5 Nov 2022 18:39:06 +0800 Subject: [PATCH 1/3] xous: add api support for `Scalar5` Add syscall and return definitions for Scalar5, as well as ReturnScalar5. This will enable us to pass up to five scalars as a return from a blockingscalar call. Signed-off-by: Sean Cross --- xous-rs/src/definitions.rs | 5 +++++ xous-rs/src/syscall.rs | 43 +++++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/xous-rs/src/definitions.rs b/xous-rs/src/definitions.rs index 7cee91acb..39b5d00c8 100644 --- a/xous-rs/src/definitions.rs +++ b/xous-rs/src/definitions.rs @@ -460,6 +460,9 @@ pub enum Result { /// the caller. NewProcess(ProcessStartup), + /// 20: A scalar with five values + Scalar5(usize, usize, usize, usize, usize), + UnknownResult(usize, usize, usize, usize, usize, usize, usize), } @@ -523,6 +526,7 @@ impl Result { 0, ], Result::NewProcess(p) => Self::add_opcode(19, p.into()), + Result::Scalar5(a, b, c, d, e) => [15, *a, *b, *c, *d, *e, 0, 0], Result::UnknownResult(arg1, arg2, arg3, arg4, arg5, arg6, arg7) => { [usize::MAX, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7] } @@ -600,6 +604,7 @@ impl Result { 17 => Result::None, 18 => Result::MemoryReturned(MemorySize::new(src[1]), MemorySize::new(src[2])), 19 => Result::NewProcess(src.into()), + 20 => Result::Scalar5(src[1], src[2], src[3], src[4], src[5]), _ => Result::UnknownResult(src[0], src[1], src[2], src[3], src[4], src[5], src[6]), } } diff --git a/xous-rs/src/syscall.rs b/xous-rs/src/syscall.rs index 492211913..da053263f 100644 --- a/xous-rs/src/syscall.rs +++ b/xous-rs/src/syscall.rs @@ -467,10 +467,11 @@ pub enum SysCall { /// /// ## Errors /// * **BadAddress**: The mapping does not exist - #[cfg(feature="v2p")] - VirtToPhys( - usize, /* virtual address */ - ), + #[cfg(feature = "v2p")] + VirtToPhys(usize /* virtual address */), + + /// Return five scalars to the sender + ReturnScalar5(MessageSender, usize, usize, usize, usize, usize), /// This syscall does not exist. It captures all possible /// arguments so detailed analysis can be performed. @@ -516,8 +517,9 @@ pub enum SysCallNumber { JoinThread = 36, SetExceptionHandler = 37, AdjustProcessLimit = 38, - #[cfg(feature="v2p")] + #[cfg(feature = "v2p")] VirtToPhys = 39, + ReturnScalar5 = 40, Invalid, } @@ -562,8 +564,9 @@ impl SysCallNumber { 36 => JoinThread, 37 => SetExceptionHandler, 38 => AdjustProcessLimit, - #[cfg(feature="v2p")] + #[cfg(feature = "v2p")] 39 => VirtToPhys, + 40 => ReturnScalar5, _ => Invalid, } } @@ -928,15 +931,18 @@ impl SysCall { 0, 0, ], - #[cfg(feature="v2p")] - SysCall::VirtToPhys(vaddr) => [ - SysCallNumber::VirtToPhys as usize, - *vaddr, - 0, - 0, - 0, - 0, - 0, + #[cfg(feature = "v2p")] + SysCall::VirtToPhys(vaddr) => { + [SysCallNumber::VirtToPhys as usize, *vaddr, 0, 0, 0, 0, 0, 0] + } + SysCall::ReturnScalar5(sender, arg1, arg2, arg3, arg4, arg5) => [ + SysCallNumber::ReturnScalar5 as usize, + sender.to_usize(), + *arg1, + *arg2, + *arg3, + *arg4, + *arg5, 0, ], SysCall::Invalid(a1, a2, a3, a4, a5, a6, a7) => [ @@ -1103,8 +1109,11 @@ impl SysCall { SysCallNumber::JoinThread => SysCall::JoinThread(a1 as _), SysCallNumber::SetExceptionHandler => SysCall::SetExceptionHandler(a1 as _, a2 as _), SysCallNumber::AdjustProcessLimit => SysCall::AdjustProcessLimit(a1, a2, a3), - #[cfg(feature="v2p")] + #[cfg(feature = "v2p")] SysCallNumber::VirtToPhys => SysCall::VirtToPhys(a1 as _), + SysCallNumber::ReturnScalar5 => { + SysCall::ReturnScalar5(MessageSender::from_usize(a1), a2, a3, a4, a5, a6) + } SysCallNumber::Invalid => SysCall::Invalid(a1, a2, a3, a4, a5, a6, a7), }) } @@ -1872,7 +1881,7 @@ pub fn set_exception_handler( */ /// Translate a virtual address to a physical address -#[cfg(feature="v2p")] +#[cfg(feature = "v2p")] pub fn virt_to_phys(va: usize) -> core::result::Result { rsyscall(SysCall::VirtToPhys(va)).and_then(|result| { if let Result::Scalar1(pa) = result { From da5647539f4a2a13b39a5275c0a0ba77231bc68a Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sat, 5 Nov 2022 18:39:54 +0800 Subject: [PATCH 2/3] kernel: syscall: add support for return_scalar5 Add kernel support for returning 5 scalars. Signed-off-by: Sean Cross --- kernel/src/syscall.rs | 83 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 2288da465..226d68407 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -538,6 +538,84 @@ fn return_scalar2( }) } +fn return_scalar5( + server_pid: PID, + server_tid: TID, + in_irq: bool, + sender: MessageSender, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, +) -> SysCallResult { + SystemServices::with_mut(|ss| { + let sender = SenderID::from(sender); + + let server = ss + .server_from_sidx_mut(sender.sidx) + .ok_or(xous_kernel::Error::ServerNotFound)?; + // .expect("Couldn't get server from SIDX"); + if server.pid != server_pid { + return Err(xous_kernel::Error::ServerNotFound); + } + let result = server.take_waiting_message(sender.idx, None)?; + let (client_pid, client_tid) = match result { + WaitingMessage::ScalarMessage(pid, tid) => (pid, tid), + WaitingMessage::ForgetMemory(_) => { + println!("WARNING: Tried to wait on a scalar message that was actually forgetting memory"); + return Err(xous_kernel::Error::ProcessNotFound); + } + WaitingMessage::BorrowedMemory(_, _, _, _, _) => { + println!( + "WARNING: Tried to wait on a scalar message that was actually borrowed memory" + ); + return Err(xous_kernel::Error::ProcessNotFound); + } + WaitingMessage::MovedMemory => { + println!( + "WARNING: Tried to wait on a scalar message that was actually moved memory" + ); + return Err(xous_kernel::Error::ProcessNotFound); + } + WaitingMessage::None => { + println!("WARNING: Tried to wait on a message that didn't exist"); + return Err(xous_kernel::Error::ProcessNotFound); + } + }; + + let client_is_runnable = ss.runnable(client_pid, Some(client_tid))?; + + if !cfg!(baremetal) || in_irq || !client_is_runnable { + // In a hosted environment, `switch_to_thread()` doesn't continue + // execution from the new thread. Instead it continues in the old + // thread. Therefore, we need to instruct the client to resume, and + // return to the server. + // In a baremetal environment, the opposite is true -- we instruct + // the server to resume and return to the client. + ss.set_thread_result( + client_pid, + client_tid, + xous_kernel::Result::Scalar5(arg1, arg2, arg3, arg4, arg5), + )?; + if cfg!(baremetal) { + ss.ready_thread(client_pid, client_tid)?; + } + Ok(xous_kernel::Result::Ok) + } else { + // Switch away from the server, but leave it as Runnable + ss.unschedule_thread(server_pid, server_tid)?; + ss.ready_thread(server_pid, server_tid)?; + ss.set_thread_result(server_pid, server_tid, xous_kernel::Result::Ok)?; + + // Switch to the client + ss.ready_thread(client_pid, client_tid)?; + ss.switch_to_thread(client_pid, Some(client_tid))?; + Ok(xous_kernel::Result::Scalar5(arg1, arg2, arg3, arg4, arg5)) + } + }) +} + fn receive_message(pid: PID, tid: TID, sid: SID, blocking: ExecutionType) -> SysCallResult { SystemServices::with_mut(|ss| { assert!( @@ -855,6 +933,9 @@ pub fn handle_inner(pid: PID, tid: TID, in_irq: bool, call: SysCall) -> SysCallR SysCall::ReturnScalar2(sender, arg1, arg2) => { return_scalar2(pid, tid, in_irq, sender, arg1, arg2) } + SysCall::ReturnScalar5(sender, arg1, arg2, arg3, arg4, arg5) => { + return_scalar5(pid, tid, in_irq, sender, arg1, arg2, arg3, arg4, arg5) + } SysCall::TrySendMessage(cid, message) => send_message(pid, tid, cid, message), SysCall::TerminateProcess(_ret) => SystemServices::with_mut(|ss| { ss.unschedule_thread(pid, tid)?; @@ -936,7 +1017,7 @@ pub fn handle_inner(pid: PID, tid: TID, in_irq: bool, call: SysCall) -> SysCallR }), _ => Err(xous_kernel::Error::InvalidLimit), }, - #[cfg(feature="v2p")] + #[cfg(feature = "v2p")] SysCall::VirtToPhys(vaddr) => { let phys_addr = crate::arch::mem::virt_to_phys(vaddr as usize); match phys_addr { From c9f751f5f0b0ded770d1dd1ae53bab50e39b3a27 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sat, 5 Nov 2022 18:44:01 +0800 Subject: [PATCH 3/3] xous: add api support for scalar5 With the addition of scalar5, existing api calls must be updated to take advantage of it. This will allow `send_message()` to return a `scalar5`. Signed-off-by: Sean Cross --- xous-rs/src/syscall.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/xous-rs/src/syscall.rs b/xous-rs/src/syscall.rs index da053263f..5047abe73 100644 --- a/xous-rs/src/syscall.rs +++ b/xous-rs/src/syscall.rs @@ -327,6 +327,7 @@ pub enum SysCall { /// * **Ok**: The Scalar / Send message was successfully sent, or the Borrow has finished /// * **Scalar1**: The Server returned a `Scalar1` value /// * **Scalar2**: The Server returned a `Scalar2` value + /// * **Scalar5**: The Server returned a `Scalar5` value /// * **BlockedProcess**: In Hosted mode, the target process is now blocked /// /// # Errors @@ -342,6 +343,7 @@ pub enum SysCall { /// * **Ok**: The Scalar / Send message was successfully sent, or the Borrow has finished /// * **Scalar1**: The Server returned a `Scalar1` value /// * **Scalar2**: The Server returned a `Scalar2` value + /// * **Scalar5**: The Server returned a `Scalar5` value /// * **BlockedProcess**: In Hosted mode, the target process is now blocked /// /// # Errors @@ -1210,6 +1212,7 @@ impl SysCall { SysCall::TryConnect(_) | SysCall::TryReceiveMessage(_) | SysCall::ReturnToParent(_, _) + | SysCall::ReturnScalar5(_, _, _, _, _, _) | SysCall::ReturnScalar2(_, _, _) | SysCall::ReturnScalar1(_, _) | SysCall::ReturnMemory(_, _, _, _) @@ -1352,6 +1355,25 @@ pub fn return_scalar2( } } +/// Return 5 scalars to the provided message. +pub fn return_scalar5( + sender: MessageSender, + val1: usize, + val2: usize, + val3: usize, + val4: usize, + val5: usize, +) -> core::result::Result<(), Error> { + let result = rsyscall(SysCall::ReturnScalar5(sender, val1, val2, val3, val4, val5))?; + if let crate::Result::Ok = result { + Ok(()) + } else if let Result::Error(e) = result { + Err(e) + } else { + Err(Error::InternalError) + } +} + /// Claim a hardware interrupt for this process. pub fn claim_interrupt( irq_no: usize, @@ -1539,6 +1561,7 @@ pub fn try_send_message(connection: CID, message: Message) -> core::result::Resu Ok(Result::Ok) => Ok(Result::Ok), Ok(Result::Scalar1(a)) => Ok(Result::Scalar1(a)), Ok(Result::Scalar2(a, b)) => Ok(Result::Scalar2(a, b)), + Ok(Result::Scalar5(a, b, c, d, e)) => Ok(Result::Scalar5(a, b, c, d, e)), Ok(Result::MemoryReturned(offset, valid)) => Ok(Result::MemoryReturned(offset, valid)), Err(e) => Err(e), v => panic!("Unexpected return value: {:?}", v), @@ -1581,6 +1604,7 @@ pub fn send_message(connection: CID, message: Message) -> core::result::Result Ok(Result::Ok), Ok(Result::Scalar1(a)) => Ok(Result::Scalar1(a)), Ok(Result::Scalar2(a, b)) => Ok(Result::Scalar2(a, b)), + Ok(Result::Scalar5(a, b, c, d, e)) => Ok(Result::Scalar5(a, b, c, d, e)), Ok(Result::MemoryReturned(offset, valid)) => Ok(Result::MemoryReturned(offset, valid)), Err(e) => Err(e), v => panic!("Unexpected return value: {:?}", v),