Kernel: Added startup kernel

This commit is contained in:
pca006132 2020-07-08 15:54:50 +08:00
parent 67ff3c36e2
commit e263814546
2 changed files with 83 additions and 33 deletions

View File

@ -21,6 +21,7 @@ use libboard_zynq::{
}; };
use libasync::{smoltcp::{Sockets, TcpStream}, task}; use libasync::{smoltcp::{Sockets, TcpStream}, task};
use crate::config;
use crate::net_settings; use crate::net_settings;
use crate::proto_async::*; use crate::proto_async::*;
use crate::kernel; use crate::kernel;
@ -119,12 +120,17 @@ async fn read_string(stream: &TcpStream, max_length: usize) -> Result<String> {
Ok(String::from_utf8(bytes).map_err(|err| Error::Utf8Error(err.utf8_error()))?) Ok(String::from_utf8(bytes).map_err(|err| Error::Utf8Error(err.utf8_error()))?)
} }
async fn handle_run_kernel(stream: &TcpStream, control: &Rc<RefCell<kernel::Control>>) -> Result<()> { async fn handle_run_kernel(stream: Option<&TcpStream>, control: &Rc<RefCell<kernel::Control>>) -> Result<()> {
control.borrow_mut().tx.async_send(kernel::Message::StartRequest).await; control.borrow_mut().tx.async_send(kernel::Message::StartRequest).await;
loop { loop {
let reply = control.borrow_mut().rx.async_recv().await; let reply = control.borrow_mut().rx.async_recv().await;
match *reply { match *reply {
kernel::Message::RpcSend { is_async, data } => { kernel::Message::RpcSend { is_async, data } => {
if stream.is_none() {
error!("Unexpected RPC from startup/idle kernel!");
break
}
let stream = stream.unwrap();
write_header(stream, Reply::RPCRequest).await?; write_header(stream, Reply::RPCRequest).await?;
write_bool(stream, is_async).await?; write_bool(stream, is_async).await?;
stream.send(data.iter().copied()).await?; stream.send(data.iter().copied()).await?;
@ -183,23 +189,34 @@ async fn handle_run_kernel(stream: &TcpStream, control: &Rc<RefCell<kernel::Cont
} }
}, },
kernel::Message::KernelFinished => { kernel::Message::KernelFinished => {
write_header(stream, Reply::KernelFinished).await?; if let Some(stream) = stream {
write_header(stream, Reply::KernelFinished).await?;
}
break; break;
}, },
kernel::Message::KernelException(exception, backtrace) => { kernel::Message::KernelException(exception, backtrace) => {
write_header(stream, Reply::KernelException).await?; match stream {
write_chunk(stream, exception.name.as_ref()).await?; Some(stream) => {
write_chunk(stream, exception.message.as_ref()).await?; // only send the exception data to host if there is host,
write_i64(stream, exception.param[0] as i64).await?; // i.e. not idle/startup kernel.
write_i64(stream, exception.param[1] as i64).await?; write_header(stream, Reply::KernelException).await?;
write_i64(stream, exception.param[2] as i64).await?; write_chunk(stream, exception.name.as_ref()).await?;
write_chunk(stream, exception.file.as_ref()).await?; write_chunk(stream, exception.message.as_ref()).await?;
write_i32(stream, exception.line as i32).await?; write_i64(stream, exception.param[0] as i64).await?;
write_i32(stream, exception.column as i32).await?; write_i64(stream, exception.param[1] as i64).await?;
write_chunk(stream, exception.function.as_ref()).await?; write_i64(stream, exception.param[2] as i64).await?;
write_i32(stream, backtrace.len() as i32).await?; write_chunk(stream, exception.file.as_ref()).await?;
for &addr in backtrace { write_i32(stream, exception.line as i32).await?;
write_i32(stream, addr as i32).await?; write_i32(stream, exception.column as i32).await?;
write_chunk(stream, exception.function.as_ref()).await?;
write_i32(stream, backtrace.len() as i32).await?;
for &addr in backtrace {
write_i32(stream, addr as i32).await?;
}
},
None => {
error!("Uncaught kernel exception: {:?}", exception);
}
} }
break; break;
} }
@ -211,6 +228,39 @@ async fn handle_run_kernel(stream: &TcpStream, control: &Rc<RefCell<kernel::Cont
Ok(()) Ok(())
} }
async fn load_kernel(buffer: Vec<u8>, control: &Rc<RefCell<kernel::Control>>, stream: Option<&TcpStream>) -> Result<()> {
let mut control = control.borrow_mut();
control.restart();
control.tx.async_send(kernel::Message::LoadRequest(Arc::new(buffer))).await;
let reply = control.rx.async_recv().await;
match *reply {
kernel::Message::LoadCompleted => {
if let Some(stream) = stream {
write_header(stream, Reply::LoadCompleted).await?;
}
Ok(())
},
kernel::Message::LoadFailed => {
if let Some(stream) = stream {
write_header(stream, Reply::LoadFailed).await?;
write_chunk(stream, b"core1 failed to process data").await?;
} else {
error!("Kernel load failed");
}
Err(Error::UnexpectedPattern)
},
_ => {
error!("unexpected message from core1: {:?}", reply);
if let Some(stream) = stream {
write_header(stream, Reply::LoadFailed).await?;
write_chunk(stream, b"core1 sent unexpected reply").await?;
}
Err(Error::UnrecognizedPacket)
}
}
}
async fn handle_connection(stream: &TcpStream, control: Rc<RefCell<kernel::Control>>) -> Result<()> { async fn handle_connection(stream: &TcpStream, control: Rc<RefCell<kernel::Control>>) -> Result<()> {
expect(stream, b"ARTIQ coredev\n").await?; expect(stream, b"ARTIQ coredev\n").await?;
info!("received connection"); info!("received connection");
@ -227,25 +277,10 @@ async fn handle_connection(stream: &TcpStream, control: Rc<RefCell<kernel::Contr
}, },
Request::LoadKernel => { Request::LoadKernel => {
let buffer = read_bytes(stream, 1024*1024).await?; let buffer = read_bytes(stream, 1024*1024).await?;
let mut control = control.borrow_mut(); load_kernel(buffer, &control, Some(stream)).await?;
control.restart();
control.tx.async_send(kernel::Message::LoadRequest(Arc::new(buffer))).await;
let reply = control.rx.async_recv().await;
match *reply {
kernel::Message::LoadCompleted => write_header(stream, Reply::LoadCompleted).await?,
kernel::Message::LoadFailed => {
write_header(stream, Reply::LoadFailed).await?;
write_chunk(stream, b"core1 failed to process data").await?;
},
_ => {
error!("unexpected message from core1: {:?}", reply);
write_header(stream, Reply::LoadFailed).await?;
write_chunk(stream, b"core1 sent unexpected reply").await?;
}
}
}, },
Request::RunKernel => { Request::RunKernel => {
handle_run_kernel(stream, &control).await?; handle_run_kernel(Some(stream), &control).await?;
}, },
_ => { _ => {
error!("unexpected request from host: {:?}", request); error!("unexpected request from host: {:?}", request);
@ -294,9 +329,24 @@ pub fn main(timer: GlobalTimer) {
} }
}; };
let startup_kernel: Option<Vec<u8>>;
let cfg = config::Config::new();
startup_kernel = cfg.as_ref().ok().and_then(|cfg| cfg.read("startup").ok());
Sockets::init(32); Sockets::init(32);
let control: Rc<RefCell<kernel::Control>> = Rc::new(RefCell::new(kernel::Control::start())); let control: Rc<RefCell<kernel::Control>> = Rc::new(RefCell::new(kernel::Control::start()));
if let Some(buffer) = startup_kernel {
info!("Loading startup kernel...");
if let Ok(()) = task::block_on(load_kernel(buffer, &control, None)) {
info!("Starting startup kernel...");
let _ = task::block_on(handle_run_kernel(None, &control));
info!("Startup kernel finished!");
} else {
error!("Error loading startup kernel!");
}
}
task::spawn(async move { task::spawn(async move {
loop { loop {
let stream = TcpStream::accept(1381, 2048, 2048).await.unwrap(); let stream = TcpStream::accept(1381, 2048, 2048).await.unwrap();

View File

@ -77,7 +77,7 @@ impl Config {
Ok(Config { fs }) Ok(Config { fs })
} }
fn read<'b>(&self, key: &'b str) -> Result<'b, Vec<u8>> { pub fn read<'b>(&self, key: &'b str) -> Result<'b, Vec<u8>> {
let root_dir = self.fs.root_dir(); let root_dir = self.fs.root_dir();
let mut buffer: Vec<u8> = Vec::new(); let mut buffer: Vec<u8> = Vec::new();
match root_dir.open_file(&["/CONFIG/", key, ".BIN"].concat()) { match root_dir.open_file(&["/CONFIG/", key, ".BIN"].concat()) {