Skip to content

Commit e85455a

Browse files
authored
Merge pull request betrusted-io#271 from betrusted-io/scalar5-support
Scalar5 support
2 parents a16304b + c9f751f commit e85455a

File tree

3 files changed

+137
-18
lines changed

3 files changed

+137
-18
lines changed

kernel/src/syscall.rs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,84 @@ fn return_scalar2(
538538
})
539539
}
540540

541+
fn return_scalar5(
542+
server_pid: PID,
543+
server_tid: TID,
544+
in_irq: bool,
545+
sender: MessageSender,
546+
arg1: usize,
547+
arg2: usize,
548+
arg3: usize,
549+
arg4: usize,
550+
arg5: usize,
551+
) -> SysCallResult {
552+
SystemServices::with_mut(|ss| {
553+
let sender = SenderID::from(sender);
554+
555+
let server = ss
556+
.server_from_sidx_mut(sender.sidx)
557+
.ok_or(xous_kernel::Error::ServerNotFound)?;
558+
// .expect("Couldn't get server from SIDX");
559+
if server.pid != server_pid {
560+
return Err(xous_kernel::Error::ServerNotFound);
561+
}
562+
let result = server.take_waiting_message(sender.idx, None)?;
563+
let (client_pid, client_tid) = match result {
564+
WaitingMessage::ScalarMessage(pid, tid) => (pid, tid),
565+
WaitingMessage::ForgetMemory(_) => {
566+
println!("WARNING: Tried to wait on a scalar message that was actually forgetting memory");
567+
return Err(xous_kernel::Error::ProcessNotFound);
568+
}
569+
WaitingMessage::BorrowedMemory(_, _, _, _, _) => {
570+
println!(
571+
"WARNING: Tried to wait on a scalar message that was actually borrowed memory"
572+
);
573+
return Err(xous_kernel::Error::ProcessNotFound);
574+
}
575+
WaitingMessage::MovedMemory => {
576+
println!(
577+
"WARNING: Tried to wait on a scalar message that was actually moved memory"
578+
);
579+
return Err(xous_kernel::Error::ProcessNotFound);
580+
}
581+
WaitingMessage::None => {
582+
println!("WARNING: Tried to wait on a message that didn't exist");
583+
return Err(xous_kernel::Error::ProcessNotFound);
584+
}
585+
};
586+
587+
let client_is_runnable = ss.runnable(client_pid, Some(client_tid))?;
588+
589+
if !cfg!(baremetal) || in_irq || !client_is_runnable {
590+
// In a hosted environment, `switch_to_thread()` doesn't continue
591+
// execution from the new thread. Instead it continues in the old
592+
// thread. Therefore, we need to instruct the client to resume, and
593+
// return to the server.
594+
// In a baremetal environment, the opposite is true -- we instruct
595+
// the server to resume and return to the client.
596+
ss.set_thread_result(
597+
client_pid,
598+
client_tid,
599+
xous_kernel::Result::Scalar5(arg1, arg2, arg3, arg4, arg5),
600+
)?;
601+
if cfg!(baremetal) {
602+
ss.ready_thread(client_pid, client_tid)?;
603+
}
604+
Ok(xous_kernel::Result::Ok)
605+
} else {
606+
// Switch away from the server, but leave it as Runnable
607+
ss.unschedule_thread(server_pid, server_tid)?;
608+
ss.ready_thread(server_pid, server_tid)?;
609+
ss.set_thread_result(server_pid, server_tid, xous_kernel::Result::Ok)?;
610+
611+
// Switch to the client
612+
ss.ready_thread(client_pid, client_tid)?;
613+
ss.switch_to_thread(client_pid, Some(client_tid))?;
614+
Ok(xous_kernel::Result::Scalar5(arg1, arg2, arg3, arg4, arg5))
615+
}
616+
})
617+
}
618+
541619
fn receive_message(pid: PID, tid: TID, sid: SID, blocking: ExecutionType) -> SysCallResult {
542620
SystemServices::with_mut(|ss| {
543621
assert!(
@@ -855,6 +933,9 @@ pub fn handle_inner(pid: PID, tid: TID, in_irq: bool, call: SysCall) -> SysCallR
855933
SysCall::ReturnScalar2(sender, arg1, arg2) => {
856934
return_scalar2(pid, tid, in_irq, sender, arg1, arg2)
857935
}
936+
SysCall::ReturnScalar5(sender, arg1, arg2, arg3, arg4, arg5) => {
937+
return_scalar5(pid, tid, in_irq, sender, arg1, arg2, arg3, arg4, arg5)
938+
}
858939
SysCall::TrySendMessage(cid, message) => send_message(pid, tid, cid, message),
859940
SysCall::TerminateProcess(_ret) => SystemServices::with_mut(|ss| {
860941
ss.unschedule_thread(pid, tid)?;
@@ -936,7 +1017,7 @@ pub fn handle_inner(pid: PID, tid: TID, in_irq: bool, call: SysCall) -> SysCallR
9361017
}),
9371018
_ => Err(xous_kernel::Error::InvalidLimit),
9381019
},
939-
#[cfg(feature="v2p")]
1020+
#[cfg(feature = "v2p")]
9401021
SysCall::VirtToPhys(vaddr) => {
9411022
let phys_addr = crate::arch::mem::virt_to_phys(vaddr as usize);
9421023
match phys_addr {

xous-rs/src/definitions.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@ pub enum Result {
460460
/// the caller.
461461
NewProcess(ProcessStartup),
462462

463+
/// 20: A scalar with five values
464+
Scalar5(usize, usize, usize, usize, usize),
465+
463466
UnknownResult(usize, usize, usize, usize, usize, usize, usize),
464467
}
465468

@@ -523,6 +526,7 @@ impl Result {
523526
0,
524527
],
525528
Result::NewProcess(p) => Self::add_opcode(19, p.into()),
529+
Result::Scalar5(a, b, c, d, e) => [15, *a, *b, *c, *d, *e, 0, 0],
526530
Result::UnknownResult(arg1, arg2, arg3, arg4, arg5, arg6, arg7) => {
527531
[usize::MAX, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7]
528532
}
@@ -600,6 +604,7 @@ impl Result {
600604
17 => Result::None,
601605
18 => Result::MemoryReturned(MemorySize::new(src[1]), MemorySize::new(src[2])),
602606
19 => Result::NewProcess(src.into()),
607+
20 => Result::Scalar5(src[1], src[2], src[3], src[4], src[5]),
603608
_ => Result::UnknownResult(src[0], src[1], src[2], src[3], src[4], src[5], src[6]),
604609
}
605610
}

xous-rs/src/syscall.rs

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ pub enum SysCall {
327327
/// * **Ok**: The Scalar / Send message was successfully sent, or the Borrow has finished
328328
/// * **Scalar1**: The Server returned a `Scalar1` value
329329
/// * **Scalar2**: The Server returned a `Scalar2` value
330+
/// * **Scalar5**: The Server returned a `Scalar5` value
330331
/// * **BlockedProcess**: In Hosted mode, the target process is now blocked
331332
///
332333
/// # Errors
@@ -342,6 +343,7 @@ pub enum SysCall {
342343
/// * **Ok**: The Scalar / Send message was successfully sent, or the Borrow has finished
343344
/// * **Scalar1**: The Server returned a `Scalar1` value
344345
/// * **Scalar2**: The Server returned a `Scalar2` value
346+
/// * **Scalar5**: The Server returned a `Scalar5` value
345347
/// * **BlockedProcess**: In Hosted mode, the target process is now blocked
346348
///
347349
/// # Errors
@@ -467,10 +469,11 @@ pub enum SysCall {
467469
///
468470
/// ## Errors
469471
/// * **BadAddress**: The mapping does not exist
470-
#[cfg(feature="v2p")]
471-
VirtToPhys(
472-
usize, /* virtual address */
473-
),
472+
#[cfg(feature = "v2p")]
473+
VirtToPhys(usize /* virtual address */),
474+
475+
/// Return five scalars to the sender
476+
ReturnScalar5(MessageSender, usize, usize, usize, usize, usize),
474477

475478
/// This syscall does not exist. It captures all possible
476479
/// arguments so detailed analysis can be performed.
@@ -516,8 +519,9 @@ pub enum SysCallNumber {
516519
JoinThread = 36,
517520
SetExceptionHandler = 37,
518521
AdjustProcessLimit = 38,
519-
#[cfg(feature="v2p")]
522+
#[cfg(feature = "v2p")]
520523
VirtToPhys = 39,
524+
ReturnScalar5 = 40,
521525
Invalid,
522526
}
523527

@@ -562,8 +566,9 @@ impl SysCallNumber {
562566
36 => JoinThread,
563567
37 => SetExceptionHandler,
564568
38 => AdjustProcessLimit,
565-
#[cfg(feature="v2p")]
569+
#[cfg(feature = "v2p")]
566570
39 => VirtToPhys,
571+
40 => ReturnScalar5,
567572
_ => Invalid,
568573
}
569574
}
@@ -928,15 +933,18 @@ impl SysCall {
928933
0,
929934
0,
930935
],
931-
#[cfg(feature="v2p")]
932-
SysCall::VirtToPhys(vaddr) => [
933-
SysCallNumber::VirtToPhys as usize,
934-
*vaddr,
935-
0,
936-
0,
937-
0,
938-
0,
939-
0,
936+
#[cfg(feature = "v2p")]
937+
SysCall::VirtToPhys(vaddr) => {
938+
[SysCallNumber::VirtToPhys as usize, *vaddr, 0, 0, 0, 0, 0, 0]
939+
}
940+
SysCall::ReturnScalar5(sender, arg1, arg2, arg3, arg4, arg5) => [
941+
SysCallNumber::ReturnScalar5 as usize,
942+
sender.to_usize(),
943+
*arg1,
944+
*arg2,
945+
*arg3,
946+
*arg4,
947+
*arg5,
940948
0,
941949
],
942950
SysCall::Invalid(a1, a2, a3, a4, a5, a6, a7) => [
@@ -1103,8 +1111,11 @@ impl SysCall {
11031111
SysCallNumber::JoinThread => SysCall::JoinThread(a1 as _),
11041112
SysCallNumber::SetExceptionHandler => SysCall::SetExceptionHandler(a1 as _, a2 as _),
11051113
SysCallNumber::AdjustProcessLimit => SysCall::AdjustProcessLimit(a1, a2, a3),
1106-
#[cfg(feature="v2p")]
1114+
#[cfg(feature = "v2p")]
11071115
SysCallNumber::VirtToPhys => SysCall::VirtToPhys(a1 as _),
1116+
SysCallNumber::ReturnScalar5 => {
1117+
SysCall::ReturnScalar5(MessageSender::from_usize(a1), a2, a3, a4, a5, a6)
1118+
}
11081119
SysCallNumber::Invalid => SysCall::Invalid(a1, a2, a3, a4, a5, a6, a7),
11091120
})
11101121
}
@@ -1201,6 +1212,7 @@ impl SysCall {
12011212
SysCall::TryConnect(_)
12021213
| SysCall::TryReceiveMessage(_)
12031214
| SysCall::ReturnToParent(_, _)
1215+
| SysCall::ReturnScalar5(_, _, _, _, _, _)
12041216
| SysCall::ReturnScalar2(_, _, _)
12051217
| SysCall::ReturnScalar1(_, _)
12061218
| SysCall::ReturnMemory(_, _, _, _)
@@ -1343,6 +1355,25 @@ pub fn return_scalar2(
13431355
}
13441356
}
13451357

1358+
/// Return 5 scalars to the provided message.
1359+
pub fn return_scalar5(
1360+
sender: MessageSender,
1361+
val1: usize,
1362+
val2: usize,
1363+
val3: usize,
1364+
val4: usize,
1365+
val5: usize,
1366+
) -> core::result::Result<(), Error> {
1367+
let result = rsyscall(SysCall::ReturnScalar5(sender, val1, val2, val3, val4, val5))?;
1368+
if let crate::Result::Ok = result {
1369+
Ok(())
1370+
} else if let Result::Error(e) = result {
1371+
Err(e)
1372+
} else {
1373+
Err(Error::InternalError)
1374+
}
1375+
}
1376+
13461377
/// Claim a hardware interrupt for this process.
13471378
pub fn claim_interrupt(
13481379
irq_no: usize,
@@ -1530,6 +1561,7 @@ pub fn try_send_message(connection: CID, message: Message) -> core::result::Resu
15301561
Ok(Result::Ok) => Ok(Result::Ok),
15311562
Ok(Result::Scalar1(a)) => Ok(Result::Scalar1(a)),
15321563
Ok(Result::Scalar2(a, b)) => Ok(Result::Scalar2(a, b)),
1564+
Ok(Result::Scalar5(a, b, c, d, e)) => Ok(Result::Scalar5(a, b, c, d, e)),
15331565
Ok(Result::MemoryReturned(offset, valid)) => Ok(Result::MemoryReturned(offset, valid)),
15341566
Err(e) => Err(e),
15351567
v => panic!("Unexpected return value: {:?}", v),
@@ -1572,6 +1604,7 @@ pub fn send_message(connection: CID, message: Message) -> core::result::Result<R
15721604
Ok(Result::Ok) => Ok(Result::Ok),
15731605
Ok(Result::Scalar1(a)) => Ok(Result::Scalar1(a)),
15741606
Ok(Result::Scalar2(a, b)) => Ok(Result::Scalar2(a, b)),
1607+
Ok(Result::Scalar5(a, b, c, d, e)) => Ok(Result::Scalar5(a, b, c, d, e)),
15751608
Ok(Result::MemoryReturned(offset, valid)) => Ok(Result::MemoryReturned(offset, valid)),
15761609
Err(e) => Err(e),
15771610
v => panic!("Unexpected return value: {:?}", v),
@@ -1872,7 +1905,7 @@ pub fn set_exception_handler(
18721905
*/
18731906

18741907
/// Translate a virtual address to a physical address
1875-
#[cfg(feature="v2p")]
1908+
#[cfg(feature = "v2p")]
18761909
pub fn virt_to_phys(va: usize) -> core::result::Result<usize, Error> {
18771910
rsyscall(SysCall::VirtToPhys(va)).and_then(|result| {
18781911
if let Result::Scalar1(pa) = result {

0 commit comments

Comments
 (0)