forked from M-Labs/artiq-zynq
send RPC requests to comms CPU, handle kernel termination
This commit is contained in:
parent
8e68e65ca7
commit
a915ed172a
|
@ -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 = !;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue