Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scalar5 support #271

Merged
merged 3 commits into from
Nov 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 82 additions & 1 deletion kernel/src/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down Expand Up @@ -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)?;
Expand Down Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions xous-rs/src/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}

Expand Down Expand Up @@ -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]
}
Expand Down Expand Up @@ -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]),
}
}
Expand Down
67 changes: 50 additions & 17 deletions xous-rs/src/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -467,10 +469,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.
Expand Down Expand Up @@ -516,8 +519,9 @@ pub enum SysCallNumber {
JoinThread = 36,
SetExceptionHandler = 37,
AdjustProcessLimit = 38,
#[cfg(feature="v2p")]
#[cfg(feature = "v2p")]
VirtToPhys = 39,
ReturnScalar5 = 40,
Invalid,
}

Expand Down Expand Up @@ -562,8 +566,9 @@ impl SysCallNumber {
36 => JoinThread,
37 => SetExceptionHandler,
38 => AdjustProcessLimit,
#[cfg(feature="v2p")]
#[cfg(feature = "v2p")]
39 => VirtToPhys,
40 => ReturnScalar5,
_ => Invalid,
}
}
Expand Down Expand Up @@ -928,15 +933,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) => [
Expand Down Expand Up @@ -1103,8 +1111,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),
})
}
Expand Down Expand Up @@ -1201,6 +1212,7 @@ impl SysCall {
SysCall::TryConnect(_)
| SysCall::TryReceiveMessage(_)
| SysCall::ReturnToParent(_, _)
| SysCall::ReturnScalar5(_, _, _, _, _, _)
| SysCall::ReturnScalar2(_, _, _)
| SysCall::ReturnScalar1(_, _)
| SysCall::ReturnMemory(_, _, _, _)
Expand Down Expand Up @@ -1343,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,
Expand Down Expand Up @@ -1530,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),
Expand Down Expand Up @@ -1572,6 +1604,7 @@ pub fn send_message(connection: CID, message: Message) -> core::result::Result<R
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),
Expand Down Expand Up @@ -1872,7 +1905,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<usize, Error> {
rsyscall(SysCall::VirtToPhys(va)).and_then(|result| {
if let Result::Scalar1(pa) = result {
Expand Down