forked from M-Labs/artiq-zynq
kernel: proper type for static shared variables.
* Changed the KERNEL_CHANNEL_* to Mutex<T> with proper type, remove the need for unsafe. * Exposed a const pointer to KernelImage, with UnsafeCell holding the library field for unbind with interior mutability.
This commit is contained in:
parent
0310421085
commit
0ce45b145e
@ -1,6 +1,6 @@
|
||||
//! Kernel prologue/epilogue that runs on the 2nd CPU core
|
||||
|
||||
use core::{mem, ptr};
|
||||
use core::{mem, ptr, cell::UnsafeCell};
|
||||
use alloc::borrow::ToOwned;
|
||||
use log::{debug, info, error};
|
||||
use cslice::CSlice;
|
||||
@ -9,7 +9,6 @@ use libcortex_a9::{
|
||||
enable_fpu,
|
||||
cache::{dcci_slice, iciallu, bpiall},
|
||||
asm::{dsb, isb},
|
||||
sync_channel
|
||||
};
|
||||
use dyld::{self, Library};
|
||||
use crate::eh_artiq;
|
||||
@ -19,13 +18,10 @@ use super::{
|
||||
dma::init_dma,
|
||||
CHANNEL_0TO1, CHANNEL_1TO0,
|
||||
KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0,
|
||||
KERNEL_LIBRARY,
|
||||
KERNEL_IMAGE,
|
||||
Message,
|
||||
};
|
||||
|
||||
/// will contain the kernel image address on the heap
|
||||
static mut KERNEL_LOAD_ADDR: usize = 0;
|
||||
|
||||
unsafe fn attribute_writeback(typeinfo: *const ()) {
|
||||
struct Attr {
|
||||
offset: usize,
|
||||
@ -65,8 +61,8 @@ unsafe fn attribute_writeback(typeinfo: *const ()) {
|
||||
}
|
||||
}
|
||||
|
||||
struct KernelImage {
|
||||
library: Library,
|
||||
pub struct KernelImage {
|
||||
library: UnsafeCell<Library>,
|
||||
__modinit__: u32,
|
||||
typeinfo: Option<u32>,
|
||||
}
|
||||
@ -89,21 +85,21 @@ impl KernelImage {
|
||||
}
|
||||
|
||||
Ok(KernelImage {
|
||||
library,
|
||||
library: UnsafeCell::new(library),
|
||||
__modinit__,
|
||||
typeinfo,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_library_ptr(&mut self) -> *mut Library {
|
||||
&mut self.library as *mut Library
|
||||
pub unsafe fn rebind(&self, name: &[u8], addr: *const ()) -> Result<(), dyld::Error> {
|
||||
let library = self.library.get().as_mut().unwrap();
|
||||
library.rebind(name, addr)
|
||||
}
|
||||
|
||||
pub unsafe fn exec(&mut self) {
|
||||
pub unsafe fn exec(&self) {
|
||||
// Flush data cache entries for the image in DDR, including
|
||||
// Memory/Instruction Synchronization Barriers
|
||||
dcci_slice(self.library.image.data);
|
||||
dsb();
|
||||
dcci_slice(self.library.get().as_ref().unwrap().image.data);
|
||||
iciallu();
|
||||
bpiall();
|
||||
dsb();
|
||||
@ -115,6 +111,12 @@ impl KernelImage {
|
||||
attribute_writeback(typeinfo as *const ());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_load_addr(&self) -> usize {
|
||||
unsafe {
|
||||
self.library.get().as_ref().unwrap().image.as_ptr() as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -148,11 +150,7 @@ pub fn main_core1() {
|
||||
let result = dyld::load(&data, &resolve)
|
||||
.and_then(KernelImage::new);
|
||||
match result {
|
||||
Ok(mut kernel) => {
|
||||
unsafe {
|
||||
KERNEL_LOAD_ADDR = kernel.library.image.as_ptr() as usize;
|
||||
KERNEL_LIBRARY = kernel.get_library_ptr();
|
||||
}
|
||||
Ok(kernel) => {
|
||||
loaded_kernel = Some(kernel);
|
||||
debug!("kernel loaded");
|
||||
core1_tx.send(Message::LoadCompleted);
|
||||
@ -165,14 +163,16 @@ pub fn main_core1() {
|
||||
},
|
||||
Message::StartRequest => {
|
||||
info!("kernel starting");
|
||||
if let Some(mut kernel) = loaded_kernel.take() {
|
||||
if let Some(kernel) = loaded_kernel.take() {
|
||||
core::mem::replace(&mut *KERNEL_CHANNEL_0TO1.lock(), Some(core1_rx));
|
||||
core::mem::replace(&mut *KERNEL_CHANNEL_1TO0.lock(), Some(core1_tx));
|
||||
unsafe {
|
||||
KERNEL_CHANNEL_0TO1 = mem::transmute(&mut core1_rx);
|
||||
KERNEL_CHANNEL_1TO0 = mem::transmute(&mut core1_tx);
|
||||
KERNEL_IMAGE = &kernel as *const KernelImage;
|
||||
kernel.exec();
|
||||
KERNEL_CHANNEL_0TO1 = ptr::null_mut();
|
||||
KERNEL_CHANNEL_1TO0 = ptr::null_mut();
|
||||
KERNEL_IMAGE = ptr::null();
|
||||
}
|
||||
core1_rx = core::mem::replace(&mut *KERNEL_CHANNEL_0TO1.lock(), None).unwrap();
|
||||
core1_tx = core::mem::replace(&mut *KERNEL_CHANNEL_1TO0.lock(), None).unwrap();
|
||||
}
|
||||
info!("kernel finished");
|
||||
core1_tx.send(Message::KernelFinished);
|
||||
@ -185,7 +185,7 @@ pub fn main_core1() {
|
||||
/// Called by eh_artiq
|
||||
pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'static mut [usize]) -> ! {
|
||||
let load_addr = unsafe {
|
||||
KERNEL_LOAD_ADDR
|
||||
KERNEL_IMAGE.as_ref().unwrap().get_load_addr()
|
||||
};
|
||||
let mut cursor = 0;
|
||||
// The address in the backtrace is relocated, so we have to convert it back to the address in
|
||||
@ -197,8 +197,10 @@ pub fn terminate(exception: &'static eh_artiq::Exception<'static>, backtrace: &'
|
||||
}
|
||||
}
|
||||
|
||||
let core1_tx: &mut sync_channel::Sender<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) };
|
||||
core1_tx.send(Message::KernelException(exception, &backtrace[..cursor]));
|
||||
{
|
||||
let mut core1_tx = KERNEL_CHANNEL_1TO0.lock();
|
||||
core1_tx.as_mut().unwrap().send(Message::KernelException(exception, &backtrace[..cursor]));
|
||||
}
|
||||
// TODO: remove after implementing graceful kernel termination.
|
||||
error!("Core1 uncaught exception");
|
||||
loop {}
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
};
|
||||
use alloc::{vec::Vec, string::String, collections::BTreeMap, str};
|
||||
use cslice::CSlice;
|
||||
use super::KERNEL_LIBRARY;
|
||||
use super::KERNEL_IMAGE;
|
||||
use core::mem;
|
||||
use log::debug;
|
||||
|
||||
@ -136,7 +136,7 @@ pub extern fn dma_record_start(name: CSlice<u8>) {
|
||||
artiq_raise!("DMAError", "DMA is already recording")
|
||||
}
|
||||
|
||||
let library = KERNEL_LIBRARY.as_mut().unwrap();
|
||||
let library = KERNEL_IMAGE.as_ref().unwrap();
|
||||
library.rebind(b"rtio_output",
|
||||
dma_record_output as *const ()).unwrap();
|
||||
library.rebind(b"rtio_output_wide",
|
||||
@ -156,7 +156,7 @@ pub extern fn dma_record_stop(duration: i64) {
|
||||
artiq_raise!("DMAError", "DMA is not recording")
|
||||
}
|
||||
|
||||
let library = KERNEL_LIBRARY.as_mut().unwrap();
|
||||
let library = KERNEL_IMAGE.as_ref().unwrap();
|
||||
library.rebind(b"rtio_output",
|
||||
rtio::output as *const ()).unwrap();
|
||||
library.rebind(b"rtio_output_wide",
|
||||
|
@ -1,7 +1,6 @@
|
||||
use core::ptr;
|
||||
use alloc::{vec::Vec, sync::Arc, string::String};
|
||||
|
||||
use dyld::Library;
|
||||
use libcortex_a9::{mutex::Mutex, sync_channel};
|
||||
use crate::eh_artiq;
|
||||
|
||||
@ -39,7 +38,8 @@ pub enum Message {
|
||||
static CHANNEL_0TO1: Mutex<Option<sync_channel::Receiver<Message>>> = Mutex::new(None);
|
||||
static CHANNEL_1TO0: Mutex<Option<sync_channel::Sender<Message>>> = Mutex::new(None);
|
||||
|
||||
static mut KERNEL_CHANNEL_0TO1: *mut () = ptr::null_mut();
|
||||
static mut KERNEL_CHANNEL_1TO0: *mut () = ptr::null_mut();
|
||||
static mut KERNEL_LIBRARY: *mut Library = ptr::null_mut();
|
||||
static KERNEL_CHANNEL_0TO1: Mutex<Option<sync_channel::Receiver<Message>>> = Mutex::new(None);
|
||||
static KERNEL_CHANNEL_1TO0: Mutex<Option<sync_channel::Sender<Message>>> = Mutex::new(None);
|
||||
|
||||
static mut KERNEL_IMAGE: *const core1::KernelImage = ptr::null();
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
//! Kernel-side RPC API
|
||||
|
||||
use core::mem;
|
||||
use alloc::{vec::Vec, sync::Arc};
|
||||
use cslice::{CSlice, AsCSlice};
|
||||
|
||||
use libcortex_a9::sync_channel;
|
||||
use crate::eh_artiq;
|
||||
use crate::rpc::send_args;
|
||||
use super::{
|
||||
@ -13,10 +11,10 @@ use super::{
|
||||
};
|
||||
|
||||
fn rpc_send_common(is_async: bool, service: u32, tag: &CSlice<u8>, data: *const *const ()) {
|
||||
let core1_tx: &mut sync_channel::Sender<Message> = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) };
|
||||
let mut core1_tx = KERNEL_CHANNEL_1TO0.lock();
|
||||
let mut buffer = Vec::<u8>::new();
|
||||
send_args(&mut buffer, service, tag.as_ref(), data).expect("RPC encoding failed");
|
||||
core1_tx.send(Message::RpcSend { is_async: is_async, data: Arc::new(buffer) });
|
||||
core1_tx.as_mut().unwrap().send(Message::RpcSend { is_async, data: Arc::new(buffer) });
|
||||
}
|
||||
|
||||
pub extern fn rpc_send(service: u32, tag: &CSlice<u8>, data: *const *const ()) {
|
||||
@ -28,10 +26,12 @@ pub extern fn rpc_send_async(service: u32, tag: &CSlice<u8>, data: *const *const
|
||||
}
|
||||
|
||||
pub extern fn rpc_recv(slot: *mut ()) -> usize {
|
||||
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) };
|
||||
core1_tx.send(Message::RpcRecvRequest(slot));
|
||||
let reply = core1_rx.recv();
|
||||
let reply = {
|
||||
let mut core1_rx = KERNEL_CHANNEL_0TO1.lock();
|
||||
let mut core1_tx = KERNEL_CHANNEL_1TO0.lock();
|
||||
core1_tx.as_mut().unwrap().send(Message::RpcRecvRequest(slot));
|
||||
core1_rx.as_mut().unwrap().recv()
|
||||
};
|
||||
match *reply {
|
||||
Message::RpcRecvReply(Ok(alloc_size)) => alloc_size,
|
||||
Message::RpcRecvReply(Err(exception)) => unsafe {
|
||||
|
Loading…
Reference in New Issue
Block a user