Skip to content

Commit

Permalink
Merge pull request betrusted-io#271 from betrusted-io/scalar5-support
Browse files Browse the repository at this point in the history
Scalar5 support
  • Loading branch information
bunnie authored Nov 5, 2022
2 parents a16304b + c9f751f commit e85455a
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 18 deletions.
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

0 comments on commit e85455a

Please sign in to comment.