From c2cf60e7f65cd039a23459a21b016390338f0993 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 2 Feb 2017 00:51:58 +0000 Subject: [PATCH] firmware: use the cslice crate to get rid of unsafe code in ksupport. --- artiq/firmware/Cargo.lock | 7 +++++ artiq/firmware/ksupport/Cargo.toml | 1 + artiq/firmware/ksupport/lib.rs | 48 +++++++++++------------------- artiq/firmware/ksupport/rtio.rs | 7 ++--- artiq/runtime/artiq_personality.c | 3 +- artiq/runtime/artiq_personality.h | 8 +++-- artiq/runtime/ksupport_glue.c | 18 +++++++---- 7 files changed, 50 insertions(+), 42 deletions(-) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 6a8a8f509..20b5f9e1c 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -29,6 +29,11 @@ name = "byteorder" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cslice" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fringe" version = "1.1.0" @@ -54,6 +59,7 @@ dependencies = [ "board 0.0.0", "build_artiq 0.0.0", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "std_artiq 0.0.0", ] @@ -144,6 +150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" +"checksum cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a" "checksum fringe 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "987689dcfad85eee8d76b477865641ec483e63fb86d52966bfc350c4a647d78a" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70" diff --git a/artiq/firmware/ksupport/Cargo.toml b/artiq/firmware/ksupport/Cargo.toml index ab47557f4..f8e8a4e4b 100644 --- a/artiq/firmware/ksupport/Cargo.toml +++ b/artiq/firmware/ksupport/Cargo.toml @@ -17,3 +17,4 @@ alloc_none = { path = "../liballoc_none" } std_artiq = { path = "../libstd_artiq" } board = { path = "../libboard" } byteorder = { version = "1.0", default-features = false } +cslice = { version = "0.3" } diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index d30eca5ca..3c2d62333 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -7,6 +7,7 @@ extern crate std_artiq as std; extern crate libc; extern crate byteorder; extern crate board; +extern crate cslice; #[path = "../runtime/mailbox.rs"] mod mailbox; @@ -50,6 +51,7 @@ macro_rules! artiq_raise { use core::{mem, ptr, slice, str}; use std::io::Cursor; use libc::{c_char, size_t}; +use cslice::{CSlice, CMutSlice, AsCSlice}; use kernel_proto::*; use dyld::Library; @@ -99,34 +101,22 @@ pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u3 loop {} } -#[repr(C)] -pub struct ArtiqList { - ptr: *const T, - len: usize -} - -impl ArtiqList { - pub fn from_slice(slice: &'static [T]) -> ArtiqList { - ArtiqList { ptr: slice.as_ptr(), len: slice.len() } - } - - pub unsafe fn as_slice(&self) -> &[T] { - slice::from_raw_parts(self.ptr, self.len) - } -} - static mut NOW: u64 = 0; #[no_mangle] -pub extern fn send_to_core_log(ptr: *const u8, len: usize) { - send(&LogSlice(unsafe { - str::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) - })) +pub extern fn send_to_core_log(text: CSlice) { + match str::from_utf8(text.as_ref()) { + Ok(s) => send(&LogSlice(s)), + Err(e) => { + send(&LogSlice(str::from_utf8(&text.as_ref()[..e.valid_up_to()]).unwrap())); + send(&LogSlice("(invalid utf-8)\n")); + } + } } #[no_mangle] -pub extern fn send_to_rtio_log(timestamp: i64, ptr: *const u8, len: usize) { - rtio::log(timestamp, unsafe { slice::from_raw_parts(ptr, len) }) +pub extern fn send_to_rtio_log(timestamp: i64, text: CSlice) { + rtio::log(timestamp, text.as_ref()) } extern fn abort() -> ! { @@ -185,9 +175,7 @@ extern fn recv_rpc(slot: *mut ()) -> usize { #[no_mangle] pub extern fn __artiq_terminate(exception: *const kernel_proto::Exception, - backtrace_data: *mut usize, - backtrace_size: usize) -> ! { - let backtrace = unsafe { slice::from_raw_parts_mut(backtrace_data, backtrace_size) }; + mut backtrace: CMutSlice) -> ! { let mut cursor = 0; for index in 0..backtrace.len() { if backtrace[index] > kernel_proto::KERNELCPU_PAYLOAD_ADDRESS { @@ -195,7 +183,7 @@ pub extern fn __artiq_terminate(exception: *const kernel_proto::Exception, cursor += 1; } } - let backtrace = &mut backtrace[0..cursor]; + let backtrace = &mut backtrace.as_mut()[0..cursor]; send(&NowSave(unsafe { NOW })); send(&RunException { @@ -218,21 +206,21 @@ extern fn watchdog_clear(id: i32) { send(&WatchdogClear { id: id as usize }) } -extern fn cache_get(key: *const u8) -> ArtiqList { +extern fn cache_get(key: *const u8) -> CSlice<'static, i32> { extern { fn strlen(s: *const c_char) -> size_t; } let key = unsafe { slice::from_raw_parts(key, strlen(key as *const c_char)) }; let key = unsafe { str::from_utf8_unchecked(key) }; send(&CacheGetRequest { key: key }); - recv!(&CacheGetReply { value } => ArtiqList::from_slice(value)) + recv!(&CacheGetReply { value } => value.as_c_slice()) } -extern fn cache_put(key: *const u8, list: ArtiqList) { +extern fn cache_put(key: *const u8, list: CSlice) { extern { fn strlen(s: *const c_char) -> size_t; } let key = unsafe { slice::from_raw_parts(key, strlen(key as *const c_char)) }; let key = unsafe { str::from_utf8_unchecked(key) }; - send(&CachePutRequest { key: key, value: unsafe { list.as_slice() } }); + send(&CachePutRequest { key: key, value: list.as_ref() }); recv!(&CachePutReply { succeeded } => { if !succeeded { artiq_raise!("CacheError", "cannot put into a busy cache row") diff --git a/artiq/firmware/ksupport/rtio.rs b/artiq/firmware/ksupport/rtio.rs index 76b05fb8a..53443e763 100644 --- a/artiq/firmware/ksupport/rtio.rs +++ b/artiq/firmware/ksupport/rtio.rs @@ -1,9 +1,9 @@ #[path = "../runtime/kernel_proto.rs"] mod kernel_proto; -use board::csr; use core::ptr::{read_volatile, write_volatile}; -use ::ArtiqList; +use cslice::CSlice; +use board::csr; use ::send; use kernel_proto::*; @@ -84,12 +84,11 @@ pub extern fn output(timestamp: i64, channel: i32, addr: i32, data: i32) { } } -pub extern fn output_wide(timestamp: i64, channel: i32, addr: i32, list: ArtiqList) { +pub extern fn output_wide(timestamp: i64, channel: i32, addr: i32, data: CSlice) { unsafe { csr::rtio::chan_sel_write(channel as u32); csr::rtio::o_timestamp_write(timestamp as u64); csr::rtio::o_address_write(addr as u32); - let data = list.as_slice(); for i in 0..data.len() { rtio_o_data_write(i, data[i] as u32) } diff --git a/artiq/runtime/artiq_personality.c b/artiq/runtime/artiq_personality.c index 2cc5704b4..48dcf900d 100644 --- a/artiq/runtime/artiq_personality.c +++ b/artiq/runtime/artiq_personality.c @@ -308,7 +308,8 @@ static _Unwind_Reason_Code __artiq_uncaught_exception( if(actions & _UA_END_OF_STACK) { EH_LOG0("end of stack"); - __artiq_terminate(&inflight->artiq, inflight->backtrace, inflight->backtrace_size); + struct slice backtrace = { inflight->backtrace, inflight->backtrace_size }; + __artiq_terminate(&inflight->artiq, backtrace); } else { EH_LOG0("continue"); return _URC_NO_REASON; diff --git a/artiq/runtime/artiq_personality.h b/artiq/runtime/artiq_personality.h index b1ed1b8d9..6f75ae2d8 100644 --- a/artiq/runtime/artiq_personality.h +++ b/artiq/runtime/artiq_personality.h @@ -4,6 +4,11 @@ #include #include +struct slice { + void *ptr; + size_t len; +}; + struct artiq_exception { union { uintptr_t typeinfo; @@ -43,8 +48,7 @@ void __artiq_reraise(void) /* Called by the runtime */ void __artiq_terminate(struct artiq_exception *artiq_exn, - uintptr_t *backtrace, - size_t backtrace_size) + struct slice backtrace) __attribute__((noreturn)); #ifdef __cplusplus diff --git a/artiq/runtime/ksupport_glue.c b/artiq/runtime/ksupport_glue.c index 6525b4314..0a6cd3eea 100644 --- a/artiq/runtime/ksupport_glue.c +++ b/artiq/runtime/ksupport_glue.c @@ -6,8 +6,13 @@ #include #include -void send_to_core_log(const char *ptr, size_t length); -void send_to_rtio_log(long long int timestamp, const char *ptr, size_t length); +struct slice { + void *ptr; + size_t len; +}; + +void send_to_core_log(struct slice str); +void send_to_rtio_log(long long int timestamp, struct slice data); #define KERNELCPU_EXEC_ADDRESS 0x40800000 #define KERNELCPU_PAYLOAD_ADDRESS 0x40840000 @@ -28,7 +33,8 @@ int fprintf(FILE *stream, const char *fmt, ...) vsnprintf(buf, size + 1, fmt, args); va_end(args); - send_to_core_log(buf, size); + struct slice str = { buf, size }; + send_to_core_log(str); return 0; } @@ -113,7 +119,8 @@ int core_log(const char *fmt, ...) vsnprintf(buf, size + 1, fmt, args); va_end(args); - send_to_core_log(buf, size); + struct slice str = { buf, size }; + send_to_core_log(str); return 0; } @@ -132,5 +139,6 @@ void rtio_log(long long int timestamp, const char *fmt, ...) vsnprintf(buf, size + 1, fmt, args); va_end(args); - send_to_rtio_log(timestamp, buf, size); + struct slice str = { buf, size }; + send_to_rtio_log(timestamp, str); }