From 0ce45b145e6f66d582c42d447b6eee73a6485f5c Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 24 Jul 2020 12:24:01 +0800 Subject: [PATCH] kernel: proper type for static shared variables. * Changed the KERNEL_CHANNEL_* to Mutex 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. --- src/runtime/src/kernel/core1.rs | 56 +++++++++++++++++---------------- src/runtime/src/kernel/dma.rs | 6 ++-- src/runtime/src/kernel/mod.rs | 8 ++--- src/runtime/src/kernel/rpc.rs | 16 +++++----- 4 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/runtime/src/kernel/core1.rs b/src/runtime/src/kernel/core1.rs index 75c56c3d..a592e8e5 100644 --- a/src/runtime/src/kernel/core1.rs +++ b/src/runtime/src/kernel/core1.rs @@ -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, __modinit__: u32, typeinfo: Option, } @@ -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 = 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 {} diff --git a/src/runtime/src/kernel/dma.rs b/src/runtime/src/kernel/dma.rs index ba558354..51eecb44 100644 --- a/src/runtime/src/kernel/dma.rs +++ b/src/runtime/src/kernel/dma.rs @@ -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) { 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", diff --git a/src/runtime/src/kernel/mod.rs b/src/runtime/src/kernel/mod.rs index 7c5171f0..10451a77 100644 --- a/src/runtime/src/kernel/mod.rs +++ b/src/runtime/src/kernel/mod.rs @@ -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>> = Mutex::new(None); static CHANNEL_1TO0: Mutex>> = 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>> = Mutex::new(None); +static KERNEL_CHANNEL_1TO0: Mutex>> = Mutex::new(None); + +static mut KERNEL_IMAGE: *const core1::KernelImage = ptr::null(); diff --git a/src/runtime/src/kernel/rpc.rs b/src/runtime/src/kernel/rpc.rs index 79a1f911..e41c51e1 100644 --- a/src/runtime/src/kernel/rpc.rs +++ b/src/runtime/src/kernel/rpc.rs @@ -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, data: *const *const ()) { - let core1_tx: &mut sync_channel::Sender = unsafe { mem::transmute(KERNEL_CHANNEL_1TO0) }; + let mut core1_tx = KERNEL_CHANNEL_1TO0.lock(); let mut buffer = Vec::::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, data: *const *const ()) { @@ -28,10 +26,12 @@ pub extern fn rpc_send_async(service: u32, tag: &CSlice, data: *const *const } pub extern fn rpc_recv(slot: *mut ()) -> usize { - let core1_rx: &mut sync_channel::Receiver = unsafe { mem::transmute(KERNEL_CHANNEL_0TO1) }; - let core1_tx: &mut sync_channel::Sender = 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 {