about to add argument support
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
36d4c143f1
commit
30c66a1cdd
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
src/xous.rs
35
src/xous.rs
@ -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) {
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]) {
|
||||||
println!("Log scalar {}: {} {:x?}", sender, opcode, args);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
179
src/xous/services/name.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
39
src/xous/services/panic_to_screen.rs
Normal file
39
src/xous/services/panic_to_screen.rs
Normal 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])
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user