about to add argument support

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2024-01-06 00:13:59 +08:00
parent 36d4c143f1
commit 30c66a1cdd
8 changed files with 519 additions and 88 deletions

View File

@ -1,4 +1,5 @@
use std::{ use std::{
collections::HashMap,
sync::mpsc::Receiver, sync::mpsc::Receiver,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
@ -51,11 +52,12 @@ pub struct Mmu {
privilege_mode: PrivilegeMode, privilege_mode: PrivilegeMode,
memory: Arc<Mutex<dyn Memory + Send + Sync>>, memory: Arc<Mutex<dyn Memory + Send + Sync>>,
// /// The size of main memory (if initialized)
// memory_length: Option<NonZeroU64>,
/// Address translation can be affected `mstatus` (MPRV, MPP in machine mode) /// Address translation can be affected `mstatus` (MPRV, MPP in machine mode)
/// then `Mmu` has copy of it. /// then `Mmu` has copy of it.
mstatus: u64, mstatus: u64,
/// A cache of instructions. We assume that instruction memory does not change.
instruction_cache: Arc<Mutex<HashMap<u64, u32>>>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -96,6 +98,7 @@ impl Mmu {
privilege_mode: PrivilegeMode::Machine, privilege_mode: PrivilegeMode::Machine,
memory, memory,
mstatus: 0, mstatus: 0,
instruction_cache: Arc::new(Mutex::new(HashMap::new())),
} }
} }
@ -170,13 +173,23 @@ impl Mmu {
/// # Arguments /// # Arguments
/// * `v_address` Virtual address /// * `v_address` Virtual address
pub fn fetch_word(&self, v_address: u64) -> Result<u32, Trap> { pub fn fetch_word(&self, v_address: u64) -> Result<u32, Trap> {
// if let Some(data) = self.instruction_cache.lock().unwrap().get(&v_address) {
// return Ok(*data);
// }
let width = 4; let width = 4;
if (v_address & 0xfff) <= (0x1000 - width) { if (v_address & 0xfff) <= (0x1000 - width) {
// Fast path. All bytes fetched are in the same page so // Fast path. All bytes fetched are in the same page so
// translating an address only once. // translating an address only once.
let effective_address = self.trim_to_xlen(v_address); let effective_address = self.trim_to_xlen(v_address);
self.translate_address(effective_address, &MemoryAccessType::Execute) self.translate_address(effective_address, &MemoryAccessType::Execute)
.map(|p_address| self.load_word_raw(p_address)) .map(|p_address| {
let data = self.load_word_raw(p_address);
self.instruction_cache
.lock()
.unwrap()
.insert(v_address, data);
data
})
.map_err(|()| Trap { .map_err(|()| Trap {
trap_type: TrapType::InstructionPageFault, trap_type: TrapType::InstructionPageFault,
value: effective_address, value: effective_address,
@ -189,6 +202,10 @@ impl Mmu {
Err(e) => return Err(e), Err(e) => return Err(e),
}; };
} }
self.instruction_cache
.lock()
.unwrap()
.insert(v_address, data);
Ok(data) Ok(data)
} }
} }

View File

@ -147,7 +147,6 @@ struct Memory {
free_pages: BTreeSet<usize>, free_pages: BTreeSet<usize>,
heap_start: u32, heap_start: u32,
heap_size: u32, heap_size: u32,
// allocation_start: u32,
allocation_previous: u32, allocation_previous: u32,
l1_pt: u32, l1_pt: u32,
satp: u32, satp: u32,
@ -664,33 +663,13 @@ impl riscv_cpu::cpu::Memory for Memory {
argument_2, argument_2,
argument_3, argument_3,
argument_4, argument_4,
) => { ) => syscalls::create_thread(
let (tx, rx) = std::sync::mpsc::channel(); self,
self.memory_cmd entry_point,
.send(MemoryCommand::CreateThread( stack_pointer,
entry_point as _, stack_length,
stack_pointer as _, [argument_1, argument_2, argument_3, argument_4],
stack_length as _, ),
argument_1 as _,
argument_2 as _,
argument_3 as _,
argument_4 as _,
tx,
))
.unwrap();
let thread_id = rx.recv().unwrap();
[
SyscallResultNumber::ThreadId as i64,
thread_id,
0,
0,
0,
0,
0,
0,
]
.into()
}
Syscall::UnmapMemory(address, size) => { Syscall::UnmapMemory(address, size) => {
// println!("UnmapMemory({:08x}, {})", address, size); // println!("UnmapMemory({:08x}, {})", address, size);
for offset in (address..address + size).step_by(4096) { for offset in (address..address + size).step_by(4096) {

View File

@ -1,6 +1,9 @@
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
pub mod log; pub mod log;
pub mod name;
pub mod panic_to_screen;
pub mod ticktimer; pub mod ticktimer;
use super::Memory;
pub type ResponseData = ([i64; 8], Option<(Vec<u8>, u64)>); pub type ResponseData = ([i64; 8], Option<(Vec<u8>, u64)>);
@ -19,48 +22,97 @@ pub enum LendResult {
} }
pub trait Service { pub trait Service {
fn scalar(&mut self, sender: u32, opcode: u32, _args: [u32; 4]) { fn scalar(&mut self, _memory: &mut Memory, sender: u32, opcode: u32, args: [u32; 4]) {
panic!("Unknown scalar to service {}: {}", sender, opcode);
}
fn blocking_scalar(&mut self, sender: u32, opcode: u32, _args: [u32; 4]) -> ScalarResult {
panic!("Unknown scalar to service {}: {}", sender, opcode);
}
fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> LendResult {
panic!( panic!(
"Unknown lend to service {}: {} ({:?})", "Unknown scalar to service {}: {} ({:?})",
sender, opcode, extra sender, opcode, args
); );
} }
/// Mutable lend messages may block fn blocking_scalar(
fn lend_mut(
&mut self, &mut self,
_memory: &mut Memory,
sender: u32, sender: u32,
opcode: u32, opcode: u32,
_buf: &mut [u8], args: [u32; 4],
) -> ScalarResult {
panic!(
"Unknown scalar to service {}: {} ({:?})",
sender, opcode, args
);
}
fn lend(
&mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
buf: &[u8],
extra: [u32; 2], extra: [u32; 2],
) -> LendResult { ) -> LendResult {
panic!( panic!(
"Unknown lend_mut to service {}: {} ({:?})", "Unknown lend {} bytes to service {}: {} ({:?})",
sender, opcode, extra buf.len(),
sender,
opcode,
extra
); );
} }
/// Send-type messages return immediately, and memory is detached from the host process. fn lend_mut(
fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) { &mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
buf: &mut [u8],
extra: [u32; 2],
) -> LendResult {
panic!( panic!(
"Unknown send to service {}: {} ({:?})", "Unknown lend_mut {} bytes to service {}: {} ({:?})",
sender, opcode, extra buf.len(),
sender,
opcode,
extra
);
}
fn send(
&mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
buf: &[u8],
extra: [u32; 2],
) {
panic!(
"Unknown send {} bytes to service {}: {} ({:?})",
buf.len(),
sender,
opcode,
extra
); );
} }
} }
pub fn get_service(name: &[u32; 4]) -> Option<Box<dyn Service + Sync + Send>> { pub fn get_service(name: &[u32; 4]) -> Option<Box<dyn Service + Sync + Send>> {
let mut output_bfr = [0u8; core::mem::size_of::<u32>() * 4 /*args.len()*/];
// Combine the four arguments to form a single
// contiguous buffer. Note: The buffer size will change
// depending on the platfor's `usize` length.
for (src, dest) in name.iter().zip(output_bfr.chunks_mut(4)) {
dest.copy_from_slice(src.to_le_bytes().as_ref());
}
println!(
"Connecting to service: {}",
std::str::from_utf8(&output_bfr).unwrap_or("<invalid name>")
);
match name { match name {
[0x6b636974, 0x656d6974, 0x65732d72, 0x72657672] => { [0x6b636974, 0x656d6974, 0x65732d72, 0x72657672] => {
Some(Box::new(ticktimer::Ticktimer::new())) Some(Box::new(ticktimer::Ticktimer::new()))
} }
[0x73756f78, 0x676f6c2d, 0x7265732d, 0x20726576] => Some(Box::new(log::Log::new())), [0x73756f78, 0x676f6c2d, 0x7265732d, 0x20726576] => Some(Box::new(log::Log::new())),
_ => None, [0x73756f78, 0x6d616e2d, 0x65732d65, 0x72657672] => Some(Box::new(name::Name::new())),
_ => panic!("Unhandled service request: {:x?}", name),
} }
} }

View File

@ -1,4 +1,5 @@
use super::{LendResult, ScalarResult, Service}; use super::{LendResult, ScalarResult, Service};
use crate::xous::Memory;
use std::io::Write; use std::io::Write;
enum LogLendOpcode { enum LogLendOpcode {
@ -9,11 +10,54 @@ enum LogLendOpcode {
StandardError = 2, StandardError = 2,
} }
#[allow(dead_code)]
enum LogSendOpcode {
/// A panic occurred, and a panic log is forthcoming
PanicStarted = 1000,
/// Log messages of varying size
PanicMessage0 = 1100,
PanicMessage1 = 1101,
PanicMessage2 = 1102,
PanicMessage3 = 1103,
PanicMessage4 = 1104,
PanicMessage5 = 1105,
PanicMessage6 = 1106,
PanicMessage7 = 1107,
PanicMessage8 = 1108,
PanicMessage9 = 1109,
PanicMessage10 = 1110,
PanicMessage11 = 1111,
PanicMessage12 = 1112,
PanicMessage13 = 1113,
PanicMessage14 = 1114,
PanicMessage15 = 1115,
PanicMessage16 = 1116,
PanicMessage17 = 1117,
PanicMessage18 = 1118,
PanicMessage19 = 1119,
PanicMessage20 = 1120,
PanicMessage21 = 1121,
PanicMessage22 = 1122,
PanicMessage23 = 1123,
PanicMessage24 = 1124,
PanicMessage25 = 1125,
PanicMessage26 = 1126,
PanicMessage27 = 1127,
PanicMessage28 = 1128,
PanicMessage29 = 1129,
PanicMessage30 = 1130,
PanicMessage31 = 1131,
PanicMessage32 = 1132,
/// End of a panic
PanicFinished = 1200,
}
pub struct Log {} pub struct Log {}
impl Log { impl Log {
pub fn new() -> Self { pub fn new() -> Self {
// println!("Constructing a log server");
Log {} Log {}
} }
} }
@ -25,16 +69,64 @@ impl Default for Log {
} }
impl Service for Log { impl Service for Log {
fn scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) { fn scalar(&mut self, _memory: &mut Memory, sender: u32, opcode: u32, args: [u32; 4]) {
let message_bytes = if opcode >= LogSendOpcode::PanicMessage0 as u32
&& opcode <= LogSendOpcode::PanicMessage32 as u32
{
Some(opcode - LogSendOpcode::PanicMessage0 as u32)
} else {
None
};
if LogSendOpcode::PanicStarted as u32 == opcode {
println!("Panic started");
} else if LogSendOpcode::PanicFinished as u32 == opcode {
println!();
println!("Panic finished");
} else if let Some(message_bytes) = message_bytes {
let mut output_bfr = [0u8; core::mem::size_of::<u32>() * 4 /*args.len()*/];
// let mut output_iter = output_bfr.iter_mut();
// Combine the four arguments to form a single
// contiguous buffer. Note: The buffer size will change
// depending on the platfor's `usize` length.
for (src, dest) in args.iter().zip(output_bfr.chunks_mut(4)) {
dest.copy_from_slice(src.to_le_bytes().as_ref());
// for src in word.to_le_bytes().iter() {
// *(output_iter.next().unwrap()) = *src;
// }
}
print!(
"{}",
std::str::from_utf8(&output_bfr[0..message_bytes as usize]).unwrap_or("<invalid>")
);
} else {
println!("Log scalar {}: {} {:x?}", sender, opcode, args); println!("Log scalar {}: {} {:x?}", sender, opcode, args);
} }
}
fn blocking_scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) -> ScalarResult { fn blocking_scalar(
println!("Log blocking_scalar {}: {} {:x?}", sender, opcode, args); &mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
args: [u32; 4],
) -> ScalarResult {
println!(
"Unhandled log blocking_scalar {}: {} {:x?}",
sender, opcode, args
);
ScalarResult::Scalar1(0) ScalarResult::Scalar1(0)
} }
fn lend(&mut self, sender: u32, opcode: u32, buf: &[u8], extra: [u32; 2]) -> LendResult { fn lend(
&mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
buf: &[u8],
extra: [u32; 2],
) -> LendResult {
if opcode == LogLendOpcode::StandardOutput as u32 { if opcode == LogLendOpcode::StandardOutput as u32 {
let print_buffer = &buf[0..extra[1] as usize]; let print_buffer = &buf[0..extra[1] as usize];
// println!("Log stdout:"); // println!("Log stdout:");
@ -46,23 +138,31 @@ impl Service for Log {
std::io::stderr().write_all(print_buffer).unwrap(); std::io::stderr().write_all(print_buffer).unwrap();
std::io::stderr().flush().unwrap(); std::io::stderr().flush().unwrap();
} else { } else {
panic!("Log lend {}: {} {:x?}", sender, opcode, buf); panic!("Unhandled log lend {}: {} {:x?}", sender, opcode, buf);
} }
LendResult::MemoryReturned([0, 0]) LendResult::MemoryReturned([0, 0])
} }
fn lend_mut( fn lend_mut(
&mut self, &mut self,
_memory: &mut Memory,
sender: u32, sender: u32,
opcode: u32, opcode: u32,
_buf: &mut [u8], _buf: &mut [u8],
extra: [u32; 2], extra: [u32; 2],
) -> LendResult { ) -> LendResult {
println!("Log lend_mut {}: {} {:x?}", sender, opcode, extra); println!("Unhandled log lend_mut {}: {} {:x?}", sender, opcode, extra);
LendResult::MemoryReturned([0, 0]) LendResult::MemoryReturned([0, 0])
} }
fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) { fn send(
println!("Log send {}: {} {:x?}", sender, opcode, extra); &mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
_buf: &[u8],
extra: [u32; 2],
) {
println!("Unhandled log send {}: {} {:x?}", sender, opcode, extra);
} }
} }

179
src/xous/services/name.rs Normal file
View File

@ -0,0 +1,179 @@
use crate::xous::Memory;
use super::{LendResult, ScalarResult, Service};
#[allow(dead_code)]
enum NameLendOpcode {
/// Create a new server with the given name and return its SID.
Register = 0,
/// Create a connection to the target server.
Lookup = 1,
/// Create an authenticated connection to the target server.
AuthenticatedLookup = 2,
/// unregister a server, given its cryptographically unique SID.
Unregister = 3,
/// disconnect, given a server name and a cryptographically unique, one-time use token
Disconnect = 4,
/// indicates if all inherently trusted slots have been occupied. Should not run untrusted code until this is the case.
TrustedInitDone = 5,
/// Connect to a Server, blocking if the Server does not exist. When the Server is started,
/// return with either the CID or an AuthenticationRequest
///
/// # Message Types
///
/// * MutableLend
///
/// # Arguments
///
/// The memory being pointed to should be a &str, and the length of the string should
/// be specified in the `valid` field.
///
/// # Return Values
///
/// Memory is overwritten to contain a return value. This return value can be defined
/// as the following enum:
///
/// ```rust
/// #[repr(C)]
/// #[non_exhaustive]
/// enum ConnectResult {
/// Success(xous::CID /* connection ID */, [u32; 4] /* Disconnection token */),
/// Error(u32 /* error code */),
/// Unhandled, /* Catchall for future Results */
/// }
/// ```
BlockingConnect = 6,
/// Connect to a Server, returning the connection ID or an authentication request if
/// it exists, and returning ServerNotFound if it does not exist.
///
/// # Message Types
///
/// * MutableLend
///
/// # Arguments
///
/// The memory being pointed to should be a &str, and the length of the string should
/// be specified in the `valid` field.
///
/// # Return Values
///
/// Memory is overwritten to contain a return value. This return value can be defined
/// as the following enum:
///
/// ```rust
/// #[repr(C)]
/// #[non_exhaustive]
/// enum ConnectResult {
/// Success(xous::CID /* connection ID */, [u32; 4] /* Disconnection token */),
/// Error(u32 /* error code */),
/// Unhandled, /* Catchall for future Results */
/// }
/// ```
TryConnect = 7,
}
pub struct Name {}
impl Name {
pub fn new() -> Self {
Name {}
}
}
impl Default for Name {
fn default() -> Self {
Self::new()
}
}
impl Service for Name {
fn scalar(&mut self, _memory: &mut Memory, sender: u32, opcode: u32, args: [u32; 4]) {
panic!("Unhandled name scalar {}: {} {:x?}", sender, opcode, args);
}
fn blocking_scalar(
&mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
args: [u32; 4],
) -> ScalarResult {
panic!(
"Unhandled name blocking_scalar {}: {} {:x?}",
sender, opcode, args
);
// ScalarResult::Scalar1(0)
}
fn lend(
&mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
buf: &[u8],
extra: [u32; 2],
) -> LendResult {
panic!(
"Unhandled name lend {}: {} {:x?} {:x?}",
sender, opcode, buf, extra
);
// LendResult::MemoryReturned([0, 0])
}
fn lend_mut(
&mut self,
memory: &mut Memory,
sender: u32,
opcode: u32,
buf: &mut [u8],
extra: [u32; 2],
) -> LendResult {
if opcode == NameLendOpcode::Register as u32 {
panic!("Register opcode unimplemented");
} else if opcode == NameLendOpcode::TryConnect as u32
|| opcode == NameLendOpcode::BlockingConnect as u32
{
let buf_len = buf.len().min(extra[1] as usize);
let name = std::str::from_utf8(&buf[0..buf_len]).unwrap_or("<invalid>");
println!("Registering name {}", name);
let service = Box::new(if name == "panic-to-screen!" {
println!("Panic-to-screen registered");
super::panic_to_screen::PanicToScreen::new()
} else {
panic!("Unrecognized service name {}", name);
});
let connection_id = memory.connections.len() as u32 + 1;
memory.connections.insert(connection_id, service);
buf[0..4].copy_from_slice(&0u32.to_le_bytes());
buf[4..8].copy_from_slice(&connection_id.to_le_bytes());
LendResult::MemoryReturned([0, 0])
} else {
panic!(
"Unhandled name lend_mut {}: {} {:x?}",
sender, opcode, extra
);
}
//
}
fn send(
&mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
_buf: &[u8],
extra: [u32; 2],
) {
panic!("Unhandled name send {}: {} {:x?}", sender, opcode, extra);
}
}

View File

@ -0,0 +1,39 @@
use super::{LendResult, Service};
use crate::xous::Memory;
enum PanicToScreenLendMutOpcode {
AppendPanicText = 0,
}
pub struct PanicToScreen {}
impl PanicToScreen {
pub fn new() -> Self {
PanicToScreen {}
}
}
impl Default for PanicToScreen {
fn default() -> Self {
Self::new()
}
}
impl Service for PanicToScreen {
fn lend_mut(
&mut self,
_memory: &mut Memory,
_sender: u32,
opcode: u32,
buf: &mut [u8],
extra: [u32; 2],
) -> LendResult {
if opcode != PanicToScreenLendMutOpcode::AppendPanicText as _ {
panic!("Unhandled panic-to-screen opcode {}", opcode);
}
let panic_str = std::str::from_utf8(&buf[0..extra[1] as usize]).unwrap_or("<invalid>");
println!("Panic to screen: {}", panic_str);
LendResult::MemoryReturned([0, 0])
}
}

View File

@ -5,6 +5,7 @@ use std::{
}; };
use super::LendResult; use super::LendResult;
use crate::xous::Memory;
pub struct Ticktimer { pub struct Ticktimer {
start: std::time::SystemTime, start: std::time::SystemTime,
@ -35,16 +36,24 @@ impl Default for Ticktimer {
} }
impl super::Service for Ticktimer { impl super::Service for Ticktimer {
fn scalar(&mut self, _sender: u32, opcode: u32, args: [u32; 4]) { fn scalar(&mut self, _memory: &mut Memory, _sender: u32, opcode: u32, args: [u32; 4]) {
if opcode == ScalarOpcode::FreeCondition as u32 { if opcode == ScalarOpcode::FreeCondition as u32 {
let condition_index = args[0] as usize; let condition_index = args[0] as usize;
if let Some(condvar) = self.condvars.remove(&condition_index) { if let Some(condvar) = self.condvars.remove(&condition_index) {
assert!(condvar.1.load(std::sync::atomic::Ordering::Relaxed) == 0); assert!(condvar.1.load(std::sync::atomic::Ordering::Relaxed) == 0);
} }
} else {
println!("Unhandled scalar: {}", opcode);
} }
} }
fn blocking_scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) -> super::ScalarResult { fn blocking_scalar(
&mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
args: [u32; 4],
) -> super::ScalarResult {
if opcode == ScalarOpcode::ElapsedMs as u32 { if opcode == ScalarOpcode::ElapsedMs as u32 {
let elapsed_ms = std::time::SystemTime::now() let elapsed_ms = std::time::SystemTime::now()
.duration_since(self.start) .duration_since(self.start)
@ -118,19 +127,27 @@ impl super::Service for Ticktimer {
super::ScalarResult::Scalar1(notify_count as u32) super::ScalarResult::Scalar1(notify_count as u32)
} else { } else {
panic!( panic!(
"Ticktimer blocking_scalar {}: {} {:x?}", "Ticktimer unhandled blocking_scalar {}: {} {:x?}",
sender, opcode, args sender, opcode, args
); );
} }
} }
fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> LendResult { fn lend(
&mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
_buf: &[u8],
extra: [u32; 2],
) -> LendResult {
println!("Ticktimer lend {}: {} {:x?}", sender, opcode, extra); println!("Ticktimer lend {}: {} {:x?}", sender, opcode, extra);
LendResult::MemoryReturned([0, 0]) LendResult::MemoryReturned([0, 0])
} }
fn lend_mut( fn lend_mut(
&mut self, &mut self,
_memory: &mut Memory,
sender: u32, sender: u32,
opcode: u32, opcode: u32,
_buf: &mut [u8], _buf: &mut [u8],
@ -140,7 +157,14 @@ impl super::Service for Ticktimer {
LendResult::MemoryReturned([0, 0]) LendResult::MemoryReturned([0, 0])
} }
fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) { fn send(
&mut self,
_memory: &mut Memory,
sender: u32,
opcode: u32,
_buf: &[u8],
extra: [u32; 2],
) {
println!("Ticktimer send {}: {} {:x?}", sender, opcode, extra); println!("Ticktimer send {}: {} {:x?}", sender, opcode, extra);
} }
} }

View File

@ -1,3 +1,6 @@
use std::sync::mpsc::channel;
use super::super::xous::services::get_service;
use super::definitions::{SyscallErrorNumber, SyscallResultNumber}; use super::definitions::{SyscallErrorNumber, SyscallResultNumber};
use super::services; use super::services;
use super::Memory; use super::Memory;
@ -58,7 +61,7 @@ pub fn connect(memory: &mut Memory, id: [u32; 4]) -> SyscallResult {
// "Connect([0x{:08x}, 0x{:08x}, 0x{:08x}, 0x{:08x}])", // "Connect([0x{:08x}, 0x{:08x}, 0x{:08x}, 0x{:08x}])",
// id[0], id[1], id[2], id[3] // id[0], id[1], id[2], id[3]
// ); // );
if let Some(service) = super::super::xous::services::get_service(&id) { if let Some(service) = get_service(&id) {
let connection_id = memory.connections.len() as u32 + 1; let connection_id = memory.connections.len() as u32 + 1;
memory.connections.insert(connection_id, service); memory.connections.insert(connection_id, service);
[ [
@ -91,7 +94,6 @@ pub fn try_connect(memory: &mut Memory, id: [u32; 4]) -> SyscallResult {
connect(memory, id) connect(memory, id)
} }
pub fn send_message( pub fn send_message(
memory: &mut Memory, memory: &mut Memory,
connection_id: u32, connection_id: u32,
@ -116,11 +118,13 @@ pub fn send_message(
} else { } else {
None None
}; };
let Some(service) = memory.connections.get_mut(&connection_id) else { // Pull the service out of the connections table so that we can send
// a mutable copy of the memory object to the service.
let Some(mut service) = memory.connections.remove(&connection_id) else {
println!("Unhandled connection ID {}", connection_id); println!("Unhandled connection ID {}", connection_id);
return [ return [
SyscallResultNumber::Error as i64, SyscallResultNumber::Error as i64,
9, /* ServerNotFound */ SyscallErrorNumber::ServerNotFound as i64,
0, 0,
0, 0,
0, 0,
@ -130,12 +134,12 @@ pub fn send_message(
] ]
.into(); .into();
}; };
match kind { let response = match kind {
1..=3 => { 1..=3 => {
let mut memory_region = memory_region.unwrap(); let mut memory_region = memory_region.unwrap();
let extra = [args[2], args[3]]; let extra = [args[2], args[3]];
match kind { match kind {
1 => match service.lend_mut(0, opcode, &mut memory_region, extra) { 1 => match service.lend_mut(memory, 0, opcode, &mut memory_region, extra) {
services::LendResult::WaitForResponse(msg) => msg.into(), services::LendResult::WaitForResponse(msg) => msg.into(),
services::LendResult::MemoryReturned(result) => { services::LendResult::MemoryReturned(result) => {
for (offset, value) in memory_region.into_iter().enumerate() { for (offset, value) in memory_region.into_iter().enumerate() {
@ -154,7 +158,7 @@ pub fn send_message(
.into() .into()
} }
}, },
2 => match service.lend(0, opcode, &memory_region, extra) { 2 => match service.lend(memory, 0, opcode, &memory_region, extra) {
services::LendResult::WaitForResponse(msg) => msg.into(), services::LendResult::WaitForResponse(msg) => msg.into(),
services::LendResult::MemoryReturned(result) => [ services::LendResult::MemoryReturned(result) => [
SyscallResultNumber::MemoryReturned as i64, SyscallResultNumber::MemoryReturned as i64,
@ -169,17 +173,17 @@ pub fn send_message(
.into(), .into(),
}, },
3 => { 3 => {
service.send(0, opcode, &memory_region, extra); service.send(memory, 0, opcode, &memory_region, extra);
[SyscallResultNumber::Ok as i64, 0, 0, 0, 0, 0, 0, 0].into() [SyscallResultNumber::Ok as i64, 0, 0, 0, 0, 0, 0, 0].into()
} }
_ => unreachable!(), _ => unreachable!(),
} }
} }
4 => { 4 => {
service.scalar(0, opcode, args); service.scalar(memory, 0, opcode, args);
[SyscallResultNumber::Ok as i64, 0, 0, 0, 0, 0, 0, 0].into() [SyscallResultNumber::Ok as i64, 0, 0, 0, 0, 0, 0, 0].into()
} }
5 => match service.blocking_scalar(0, opcode, args) { 5 => match service.blocking_scalar(memory, 0, opcode, args) {
services::ScalarResult::Scalar1(result) => [ services::ScalarResult::Scalar1(result) => [
SyscallResultNumber::Scalar1 as i64, SyscallResultNumber::Scalar1 as i64,
result as i64, result as i64,
@ -216,20 +220,22 @@ pub fn send_message(
services::ScalarResult::WaitForResponse(msg) => msg.into(), services::ScalarResult::WaitForResponse(msg) => msg.into(),
}, },
_ => { _ => {
println!("Unknown message kind {}", kind); panic!("Unknown message kind {}", kind);
[ // [
SyscallResultNumber::Error as i64, // SyscallResultNumber::Error as i64,
9, /* ServerNotFound */ // 9, /* ServerNotFound */
0, // 0,
0, // 0,
0, // 0,
0, // 0,
0, // 0,
0, // 0,
] // ]
.into() // .into()
}
} }
};
memory.connections.insert(connection_id, service);
response
} }
pub fn try_send_message( pub fn try_send_message(
@ -294,3 +300,38 @@ pub fn increase_heap(memory: &mut Memory, delta: i64, _flags: i64) -> SyscallRes
.into() .into()
} }
} }
pub fn create_thread(
memory: &mut Memory,
entry_point: i64,
stack_pointer: i64,
stack_length: i64,
arguments: [i64; 4],
) -> SyscallResult {
let (tx, rx) = channel();
memory
.memory_cmd
.send(super::MemoryCommand::CreateThread(
entry_point as _,
stack_pointer as _,
stack_length as _,
arguments[0] as _,
arguments[1] as _,
arguments[2] as _,
arguments[3] as _,
tx,
))
.unwrap();
let thread_id = rx.recv().unwrap();
[
SyscallResultNumber::ThreadId as i64,
thread_id,
0,
0,
0,
0,
0,
0,
]
.into()
}