mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
kernel: return context on failure
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
3799397be9
commit
1f478925ce
7 changed files with 119 additions and 60 deletions
|
|
@ -134,8 +134,8 @@ pub extern "C" fn trap_handler(
|
|||
// MemoryManagerHandle::get().print_ownership();
|
||||
MemoryMapping::current().print_map();
|
||||
panic!(
|
||||
"error at {:08x}: memory not mapped or reserved for addr {:08x}",
|
||||
pc, addr
|
||||
"error {:?} at {:08x}: memory not mapped or reserved for addr {:08x}",
|
||||
x, pc, addr
|
||||
);
|
||||
});
|
||||
let flags = *entry & 0x1ff;
|
||||
|
|
|
|||
|
|
@ -529,11 +529,12 @@ pub fn lend_page_inner(
|
|||
result.map(|_| phys)
|
||||
}
|
||||
|
||||
/// Return a page from `src_space` back to `dest_space`.
|
||||
pub fn return_page_inner(
|
||||
mm: &mut MemoryManager,
|
||||
_mm: &mut MemoryManager,
|
||||
src_space: &MemoryMapping,
|
||||
src_addr: *mut usize,
|
||||
dest_pid: PID,
|
||||
_dest_pid: PID,
|
||||
dest_space: &MemoryMapping,
|
||||
dest_addr: *mut usize,
|
||||
) -> Result<usize, xous::Error> {
|
||||
|
|
@ -570,7 +571,7 @@ pub fn return_page_inner(
|
|||
unsafe { flush_mmu() };
|
||||
|
||||
src_space.activate();
|
||||
Ok(0)
|
||||
Ok(phys)
|
||||
}
|
||||
|
||||
pub fn virt_to_phys(virt: usize) -> Result<usize, xous::Error> {
|
||||
|
|
|
|||
|
|
@ -399,6 +399,20 @@ impl Server {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return an available context to the blocking list. This is part of the
|
||||
/// error condition when a message cannot be handled but the context has
|
||||
/// already been claimed.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If the context cannot be returned because it is already blocking.
|
||||
pub fn return_available_context(&mut self, ctx_number: CtxID) {
|
||||
if self.ready_contexts & 1 << ctx_number != 0 {
|
||||
panic!("tried to return context {}, but it was already blocking", ctx_number);
|
||||
}
|
||||
self.ready_contexts |= 1 << ctx_number;
|
||||
}
|
||||
|
||||
/// Add the given context to the list of ready and waiting contexts.
|
||||
pub fn park_context(&mut self, context: CtxID) {
|
||||
self.ready_contexts |= 1 << context;
|
||||
|
|
|
|||
|
|
@ -663,6 +663,15 @@ impl SystemServices {
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// * **ShareViolation**: Tried to mutably share a region that was already
|
||||
/// shared
|
||||
/// * **BadAddress**: The provided address was not valid
|
||||
/// * **BadAlignment**: The provided address or length was not page-aligned
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If the memory should have been able to go into the destination process
|
||||
/// but failed, then the system panics.
|
||||
pub fn send_memory(
|
||||
&mut self,
|
||||
src_virt: *mut usize,
|
||||
|
|
@ -684,7 +693,6 @@ impl SystemServices {
|
|||
}
|
||||
|
||||
let current_pid = self.current_pid();
|
||||
/// XXX THIS SHOULD UNMAP THESE PAGES ON ERROR
|
||||
let src_mapping = self.get_process(current_pid)?.mapping;
|
||||
let dest_mapping = self.get_process(dest_pid)?.mapping;
|
||||
let mut mm = MemoryManagerHandle::get();
|
||||
|
|
@ -695,7 +703,6 @@ impl SystemServices {
|
|||
.find_virtual_address(dest_virt, len, MemoryType::Messages)
|
||||
.or_else(|e| {
|
||||
src_mapping.activate();
|
||||
/// XXX THIS SHOULD UNMAP THESE PAGES ON ERROR
|
||||
Err(e)
|
||||
})?;
|
||||
src_mapping.activate();
|
||||
|
|
@ -715,7 +722,7 @@ impl SystemServices {
|
|||
)
|
||||
.unwrap_or_else(|e| error = Some(e));
|
||||
}
|
||||
error.map_or_else(|| Ok(dest_virt), |e| Err(e))
|
||||
error.map_or_else(|| Ok(dest_virt), |e| panic!("unable to send: {:?}", e))
|
||||
}
|
||||
|
||||
/// Lend memory from one process to another.
|
||||
|
|
@ -739,7 +746,10 @@ impl SystemServices {
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// * **ShareViolation**: Tried to mutably share a region that was already shared
|
||||
/// * **ShareViolation**: Tried to mutably share a region that was already
|
||||
/// shared
|
||||
/// * **BadAddress**: The provided address was not valid
|
||||
/// * **BadAlignment**: The provided address or length was not page-aligned
|
||||
pub fn lend_memory(
|
||||
&mut self,
|
||||
src_virt: *mut usize,
|
||||
|
|
@ -752,13 +762,13 @@ impl SystemServices {
|
|||
return Err(xous::Error::BadAddress);
|
||||
}
|
||||
if len & 0xfff != 0 {
|
||||
return Err(xous::Error::BadAddress);
|
||||
return Err(xous::Error::BadAlignment);
|
||||
}
|
||||
if src_virt as usize & 0xfff != 0 {
|
||||
return Err(xous::Error::BadAddress);
|
||||
return Err(xous::Error::BadAlignment);
|
||||
}
|
||||
if dest_virt as usize & 0xfff != 0 {
|
||||
return Err(xous::Error::BadAddress);
|
||||
return Err(xous::Error::BadAlignment);
|
||||
}
|
||||
|
||||
let current_pid = self.current_pid();
|
||||
|
|
@ -795,7 +805,7 @@ impl SystemServices {
|
|||
0
|
||||
});
|
||||
}
|
||||
error.map_or_else(|| Ok(dest_virt), |e| Err(e))
|
||||
error.map_or_else(|| Ok(dest_virt), |e| panic!("unable to lend: {:?}", e))
|
||||
}
|
||||
|
||||
/// Return memory from one process back to another
|
||||
|
|
@ -854,6 +864,17 @@ impl SystemServices {
|
|||
error.map_or_else(|| Ok(dest_virt), |e| Err(e))
|
||||
}
|
||||
|
||||
/// Create a new thread in the current process. Execution begins at
|
||||
/// `entrypoint`, with the stack pointer set to `stack_pointer`. A single
|
||||
/// argument will be passed to the new function.
|
||||
///
|
||||
/// The return address of this thread will be `EXIT_THREAD`, which the
|
||||
/// kernel can trap on to indicate a thread exited.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// * **ContextNotAvailable**: The process has used all of its context
|
||||
/// slots.
|
||||
pub fn spawn_thread(
|
||||
&mut self,
|
||||
entrypoint: *mut usize,
|
||||
|
|
@ -893,6 +914,11 @@ impl SystemServices {
|
|||
|
||||
/// Allocate a new server ID for this process and return the address. If the
|
||||
/// server table is full, return an error.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// * **OutOfMemory**: A new page could not be assigned to store the server
|
||||
/// queue.
|
||||
pub fn create_server(&mut self, name: usize) -> Result<SID, xous::Error> {
|
||||
println!("Looking through server list for free server");
|
||||
println!(
|
||||
|
|
|
|||
|
|
@ -369,7 +369,11 @@ pub fn handle(call: SysCall) -> core::result::Result<xous::Result, xous::Error>
|
|||
// Unblock the client context to allow it to continue.
|
||||
println!("Unblocking PID {} CTX {}", client_pid, client_ctx);
|
||||
ss.ready_context(client_pid, client_ctx)?;
|
||||
ss.set_context_result(client_pid, client_ctx, xous::Result::MessageResult(arg1, arg2))?;
|
||||
ss.set_context_result(
|
||||
client_pid,
|
||||
client_ctx,
|
||||
xous::Result::MessageResult(arg1, arg2),
|
||||
)?;
|
||||
Ok(xous::Result::Ok)
|
||||
}
|
||||
SysCall::SendMessage(cid, message) => {
|
||||
|
|
@ -462,11 +466,24 @@ pub fn handle(call: SysCall) -> core::result::Result<xous::Result, xous::Error>
|
|||
"There are contexts available to handle this message. Marking PID {} as Ready",
|
||||
server_pid
|
||||
);
|
||||
let sender =
|
||||
ss.remember_server_message(sidx, pid, context_nr, &message, client_address)?;
|
||||
let sender = ss
|
||||
.remember_server_message(sidx, pid, context_nr, &message, client_address)
|
||||
.or_else(|e| {
|
||||
ss.server_from_sidx(sidx)
|
||||
.expect("server couldn't be located")
|
||||
.return_available_context(context_nr);
|
||||
Err(e)
|
||||
})?;
|
||||
let envelope = MessageEnvelope { sender, message };
|
||||
|
||||
ss.ready_context(server_pid, ctx_number)?;
|
||||
ss.ready_context(server_pid, ctx_number)
|
||||
.or_else(|e| {
|
||||
ss.server_from_sidx(sidx)
|
||||
.expect("server couldn't be located")
|
||||
.return_available_context(context_nr);
|
||||
Err(e)
|
||||
})?;
|
||||
|
||||
if blocking {
|
||||
println!("Activating Server context and switching away from Client");
|
||||
ss.activate_process_context(server_pid, ctx_number, !blocking, blocking)
|
||||
|
|
|
|||
|
|
@ -173,3 +173,37 @@ impl MemoryRange {
|
|||
self.addr.get() as *mut usize
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Result {
|
||||
Ok,
|
||||
Error(Error),
|
||||
MemoryAddress(*mut u8),
|
||||
MemoryRange(MemoryRange),
|
||||
ReadyContexts(
|
||||
usize, /* count */
|
||||
usize,
|
||||
/* pid0 */ usize, /* context0 */
|
||||
usize,
|
||||
/* pid1 */ usize, /* context1 */
|
||||
usize,
|
||||
/* pid2 */ usize, /* context2 */
|
||||
),
|
||||
ResumeProcess,
|
||||
ServerID(SID),
|
||||
ConnectionID(CID),
|
||||
Message(MessageEnvelope),
|
||||
ThreadID(CtxID),
|
||||
MessageResult(usize, usize),
|
||||
UnknownResult(usize, usize, usize, usize, usize, usize, usize),
|
||||
}
|
||||
|
||||
impl From<Error> for Result {
|
||||
fn from(e: Error) -> Self {
|
||||
Result::Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub type SyscallResult = core::result::Result<Result, Error>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
CpuID, CtxID, Error, MemoryAddress, MemoryFlags, MemoryMessage, MemoryRange, MemorySize,
|
||||
Message, MessageEnvelope, MessageSender, ScalarMessage, CID, PID, SID,
|
||||
CpuID, Error, MemoryAddress, MemoryFlags, MemoryMessage, MemoryRange, MemorySize,
|
||||
Message, MessageEnvelope, MessageSender, Result, ScalarMessage, SyscallResult, CID, PID, SID,
|
||||
};
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
|
|
@ -600,39 +600,6 @@ impl SysCall {
|
|||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Result {
|
||||
Ok,
|
||||
Error(Error),
|
||||
MemoryAddress(*mut u8),
|
||||
MemoryRange(MemoryRange),
|
||||
ReadyContexts(
|
||||
usize, /* count */
|
||||
usize,
|
||||
/* pid0 */ usize, /* context0 */
|
||||
usize,
|
||||
/* pid1 */ usize, /* context1 */
|
||||
usize,
|
||||
/* pid2 */ usize, /* context2 */
|
||||
),
|
||||
ResumeProcess,
|
||||
ServerID(SID),
|
||||
ConnectionID(CID),
|
||||
Message(MessageEnvelope),
|
||||
ThreadID(CtxID),
|
||||
MessageResult(usize, usize),
|
||||
UnknownResult(usize, usize, usize, usize, usize, usize, usize),
|
||||
}
|
||||
|
||||
impl From<Error> for Result {
|
||||
fn from(e: Error) -> Self {
|
||||
Result::Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub type SyscallResult = core::result::Result<Result, Error>;
|
||||
|
||||
extern "Rust" {
|
||||
fn _xous_syscall_rust(
|
||||
nr: usize,
|
||||
|
|
@ -790,7 +757,10 @@ pub fn receive_message(server: SID) -> core::result::Result<MessageEnvelope, Err
|
|||
/// * **ServerNotFound**: The server does not exist so the connection is now invalid
|
||||
/// * **BadAddress**: The client tried to pass a Memory message using an address it doesn't own
|
||||
/// * **Timeout**: The timeout limit has been reached
|
||||
pub fn send_message(connection: CID, message: Message) -> core::result::Result<(usize, usize), Error> {
|
||||
pub fn send_message(
|
||||
connection: CID,
|
||||
message: Message,
|
||||
) -> core::result::Result<(usize, usize), Error> {
|
||||
let result =
|
||||
rsyscall(SysCall::SendMessage(connection, message)).expect("couldn't send message");
|
||||
if let Result::MessageResult(arg1, arg2) = result {
|
||||
|
|
@ -832,13 +802,10 @@ pub fn rsyscall(call: SysCall) -> SyscallResult {
|
|||
pub unsafe fn dangerous_syscall(call: SysCall) -> SyscallResult {
|
||||
use core::mem::{transmute, MaybeUninit};
|
||||
let mut ret = MaybeUninit::uninit().assume_init();
|
||||
let presto =
|
||||
transmute::<_, (usize, usize, usize, usize, usize, usize, usize, usize)>(call);
|
||||
_xous_syscall_rust(
|
||||
presto.0, presto.1, presto.2, presto.3, presto.4, presto.5, presto.6, presto.7,
|
||||
&mut ret,
|
||||
)
|
||||
;
|
||||
let presto = transmute::<_, (usize, usize, usize, usize, usize, usize, usize, usize)>(call);
|
||||
_xous_syscall_rust(
|
||||
presto.0, presto.1, presto.2, presto.3, presto.4, presto.5, presto.6, presto.7, &mut ret,
|
||||
);
|
||||
match ret {
|
||||
Result::Error(e) => Err(e),
|
||||
other => Ok(other),
|
||||
|
|
|
|||
Loading…
Reference in a new issue