send RPC requests to comms CPU, handle kernel termination

This commit is contained in:
Sebastien Bourdeauducq 2020-06-05 11:48:34 +08:00
parent 8e68e65ca7
commit a915ed172a
3 changed files with 64 additions and 6 deletions

View File

@ -69,7 +69,7 @@ impl<'a> Write for Cursor<&'a mut [u8]> {
} }
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
impl Write for Cursor<::alloc::vec::Vec<u8>> { impl Write for Cursor<&mut ::alloc::vec::Vec<u8>> {
type WriteError = !; type WriteError = !;
type FlushError = !; type FlushError = !;

View File

@ -139,6 +139,21 @@ async fn handle_connection(stream: &TcpStream, control: Rc<RefCell<kernel::Contr
Request::RunKernel => { Request::RunKernel => {
let mut control = control.borrow_mut(); let mut control = control.borrow_mut();
control.tx.async_send(kernel::Message::StartRequest).await; control.tx.async_send(kernel::Message::StartRequest).await;
loop {
let reply = control.rx.async_recv().await;
match *reply {
kernel::Message::KernelFinished => {
write_header(&stream, Reply::KernelFinished).await?;
break;
},
kernel::Message::RpcSend { is_async, data } => {
debug!("RPC: is_async={} data={:?}", is_async, data);
},
_ => {
error!("received unexpected message from core1 while kernel was running: {:?}", reply);
}
}
}
} }
_ => return Err(Error::UnrecognizedPacket) _ => return Err(Error::UnrecognizedPacket)
} }

View File

@ -1,11 +1,14 @@
use core::{ptr, mem}; use core::{ptr, mem};
use log::{debug, error}; use log::{debug, error};
use alloc::{vec::Vec, sync::Arc}; use alloc::{vec::Vec, sync::Arc};
use cslice::CSlice;
use libcortex_a9::{mutex::Mutex, sync_channel::{self, sync_channel}}; use libcortex_a9::{mutex::Mutex, sync_channel::{self, sync_channel}};
use libsupport_zynq::boot::Core1; use libsupport_zynq::boot::Core1;
use dyld; use dyld;
use io;
use crate::rpc;
use crate::rtio; use crate::rtio;
@ -15,6 +18,8 @@ pub enum Message {
LoadCompleted, LoadCompleted,
LoadFailed, LoadFailed,
StartRequest, StartRequest,
KernelFinished,
RpcSend { is_async: bool, data: Arc<Vec<u8>> },
} }
static CHANNEL_0TO1: Mutex<Option<sync_channel::Receiver<Message>>> = Mutex::new(None); static CHANNEL_0TO1: Mutex<Option<sync_channel::Receiver<Message>>> = Mutex::new(None);
@ -57,6 +62,34 @@ impl Control {
} }
} }
static mut KERNEL_CHANNEL_0TO1: *mut () = ptr::null_mut();
static mut KERNEL_CHANNEL_1TO0: *mut () = ptr::null_mut();
extern fn rpc_send(service: u32, tag: &CSlice<u8>, data: *const *const ()) {
let core1_rx: &mut sync_channel::Receiver<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_0TO1) };
let core1_tx: &mut sync_channel::Sender<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) };
let mut buffer = Arc::new(Vec::<u8>::new());
{
let mut writer = io::Cursor::new(Arc::get_mut(&mut buffer).unwrap());
rpc::send_args(&mut writer, service, tag.as_ref(), data).expect("RPC encoding failed");
}
core1_tx.send(Message::RpcSend { is_async: false, data: buffer })
}
extern fn rpc_send_async(service: u32, tag: &CSlice<u8>, data: *const *const ()) {
let core1_tx: &mut sync_channel::Sender<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) };
let mut buffer = Arc::new(Vec::<u8>::new());
{
let mut writer = io::Cursor::new(Arc::get_mut(&mut buffer).unwrap());
rpc::send_args(&mut writer, service, tag.as_ref(), data).expect("RPC encoding failed");
}
core1_tx.send(Message::RpcSend { is_async: true, data: buffer })
}
extern fn rpc_recv(slot: *mut ()) -> usize {
unimplemented!();
}
macro_rules! api { macro_rules! api {
($i:ident) => ({ ($i:ident) => ({
extern { static $i: u8; } extern { static $i: u8; }
@ -77,6 +110,10 @@ fn resolve(required: &[u8]) -> Option<u32> {
api!(at_mu = rtio::at_mu), api!(at_mu = rtio::at_mu),
api!(delay_mu = rtio::delay_mu), api!(delay_mu = rtio::delay_mu),
api!(rpc_send = rpc_send),
api!(rpc_send_async = rpc_send_async),
api!(rpc_recv = rpc_recv),
api!(rtio_init = rtio::init), api!(rtio_init = rtio::init),
api!(rtio_get_destination_status = rtio::get_destination_status), api!(rtio_get_destination_status = rtio::get_destination_status),
api!(rtio_get_counter = rtio::get_counter), api!(rtio_get_counter = rtio::get_counter),
@ -108,10 +145,11 @@ pub fn main_core1() {
while core1_rx.is_none() { while core1_rx.is_none() {
core1_rx = CHANNEL_0TO1.lock().take(); core1_rx = CHANNEL_0TO1.lock().take();
} }
let core1_rx = core1_rx.unwrap(); let mut core1_rx = core1_rx.unwrap();
let mut current_modinit: Option<u32> = None; let mut current_modinit: Option<u32> = None;
for message in core1_rx { loop {
let message = core1_rx.recv();
match *message { match *message {
Message::LoadRequest(data) => { Message::LoadRequest(data) => {
match dyld::load(&data, &resolve) { match dyld::load(&data, &resolve) {
@ -127,11 +165,11 @@ pub fn main_core1() {
let __modinit__ = library.lookup(b"__modinit__").unwrap(); let __modinit__ = library.lookup(b"__modinit__").unwrap();
current_modinit = Some(__modinit__); current_modinit = Some(__modinit__);
debug!("kernel loaded"); debug!("kernel loaded");
core1_tx.send(Message::LoadCompleted) core1_tx.send(Message::LoadCompleted);
}, },
Err(error) => { Err(error) => {
error!("failed to load shared library: {}", error); error!("failed to load shared library: {}", error);
core1_tx.send(Message::LoadFailed) core1_tx.send(Message::LoadFailed);
} }
} }
}, },
@ -139,10 +177,15 @@ pub fn main_core1() {
debug!("kernel starting"); debug!("kernel starting");
if let Some(__modinit__) = current_modinit { if let Some(__modinit__) = current_modinit {
unsafe { unsafe {
KERNEL_CHANNEL_0TO1 = mem::transmute(&mut core1_rx);
KERNEL_CHANNEL_1TO0 = mem::transmute(&mut core1_tx);
(mem::transmute::<u32, fn()>(__modinit__))(); (mem::transmute::<u32, fn()>(__modinit__))();
KERNEL_CHANNEL_0TO1 = ptr::null_mut();
KERNEL_CHANNEL_1TO0 = ptr::null_mut();
} }
} }
debug!("kernel terminated"); debug!("kernel finished");
core1_tx.send(Message::KernelFinished);
} }
_ => error!("Core1 received unexpected message: {:?}", message), _ => error!("Core1 received unexpected message: {:?}", message),
} }