diff --git a/.gitmodules b/.gitmodules index 8516e2a7..7f566d97 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "tock"] path = tock - url = https://github.com/helena-project/tock + url = https://github.com/tock/tock diff --git a/.vscode/settings.json b/.vscode/settings.json index 90395e23..cf3bf02b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { "editor.formatOnSave": true, - "rust-client.channel": "nightly-2018-04-12", + "rust-client.channel": "nightly-2018-04-19", "rust.target": "thumbv7em-none-eabi", -} \ No newline at end of file +} diff --git a/Cargo.toml b/Cargo.toml index 6b6c6299..8e26084a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Tock Project Developers "] license = "MIT/Apache-2.0" [dependencies] -linked_list_allocator = "0.5.0" +linked_list_allocator = "0.6.0" [dev-dependencies] corepack = { version = "0.3.1", default-features = false, features = ["alloc"] } diff --git a/layout.ld b/layout.ld index 4df68f94..ad5035f3 100644 --- a/layout.ld +++ b/layout.ld @@ -20,7 +20,7 @@ MEMORY { } SECTIONS { -/* Text section, Code! */ + /* Text section, Code! */ .text : { _text = .; @@ -38,6 +38,7 @@ SECTIONS { * uint32_t bss_start; * uint32_t bss_size; * uint32_t reldata_start; + * uint32_t stack_size; * }; */ /* Offset of GOT symbols in flash */ @@ -59,6 +60,8 @@ SECTIONS { /* First address offset after program flash, where elf2tbf places * .rel.data section */ LONG(LOADADDR(.endsec) - _text); + /* The size of the stack requested by this application */ + LONG(STACK_SIZE); KEEP (*(.start)) *(.text*) @@ -70,13 +73,13 @@ SECTIONS { } > FLASH =0xFF -/* App state section. Used for persistent app data. */ + /* App state section. Used for persistent app data. */ .app_state : { KEEP (*(.app_state)) } > FLASH =0xFF -/* Global Offset Table */ + /* Global Offset Table */ .got : { _got = .; @@ -84,17 +87,17 @@ SECTIONS { *(.got.plt*) } > SRAM AT > FLASH -/* Data section, static initialized variables - * Note: This is placed in Flash after the text section, but needs to be - * moved to SRAM at runtime - */ + /* Data section, static initialized variables + * Note: This is placed in Flash after the text section, but needs to be + * moved to SRAM at runtime + */ .data : { _data = .; KEEP(*(.data*)) } > SRAM AT > FLASH -/* BSS section, static uninitialized variables */ + /* BSS section, static uninitialized variables */ .bss : { _bss = .; @@ -102,10 +105,10 @@ SECTIONS { *(COMMON) } > SRAM -/* + /* * __NOTE__: The following symbols are used only to hint to elf2tbf how much * total memory to request from the OS. - */ + */ .stack : { . += STACK_SIZE; @@ -126,19 +129,19 @@ SECTIONS { { } > FLASH -/* ARM Exception support - * - * This contains compiler-generated support for unwinding the stack, - * consisting of key-value pairs of function addresses and information on - * how to unwind stack frames. - * https://wiki.linaro.org/KenWerner/Sandbox/libunwind?action=AttachFile&do=get&target=libunwind-LDS.pdf - * - * .ARM.exidx is sorted, so has to go in its own output section. + /* ARM Exception support + * + * This contains compiler-generated support for unwinding the stack, + * consisting of key-value pairs of function addresses and information on + * how to unwind stack frames. + * https://wiki.linaro.org/KenWerner/Sandbox/libunwind?action=AttachFile&do=get&target=libunwind-LDS.pdf + * + * .ARM.exidx is sorted, so has to go in its own output section. * * __NOTE__: It's at the end because we currently don't actually serialize * it to the binary in elf2tbf. If it was before the RAM sections, it would * through off our calculations of the header. - */ + */ PROVIDE_HIDDEN (__exidx_start = .); .ARM.exidx : { @@ -147,5 +150,4 @@ SECTIONS { } > FLASH PROVIDE_HIDDEN (__exidx_end = .); - } diff --git a/rust-toolchain b/rust-toolchain index 555ca90e..b7e7556a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2018-04-12 +nightly-2018-04-19 diff --git a/rustfmt.toml b/rustfmt.toml index f2e8f369..810ab5bd 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,5 +1,4 @@ reorder_imports = true -reorder_imported_names = true reorder_modules = true use_field_init_shorthand = true use_try_shorthand = true diff --git a/src/entry_point.rs b/src/entry_point.rs index a0c984de..8142710e 100644 --- a/src/entry_point.rs +++ b/src/entry_point.rs @@ -1,23 +1,21 @@ extern crate linked_list_allocator; use self::linked_list_allocator::Heap; -use alloc::allocator::Alloc; -use alloc::allocator::AllocErr; -use alloc::allocator::Layout; -use alloc::string::String; -use console::Console; +use core::alloc::Alloc; +use core::alloc::GlobalAlloc; +use core::alloc::Layout; +use core::alloc::Opaque; use core::mem; use core::ptr; -use fmt; +use core::ptr::NonNull; use syscalls; -const HEAP_SIZE: usize = 0x200; -const STACK_SIZE: usize = 0x400; +const HEAP_SIZE: usize = 0x400; // None-threaded heap wrapper based on `r9` register instead of global variable -pub(crate) struct StackOwnedHeap; +pub(crate) struct TockAllocator; -impl StackOwnedHeap { +impl TockAllocator { unsafe fn heap(&self) -> &mut Heap { let heap: *mut Heap; asm!("mov $0, r9" : "=r"(heap) : : : "volatile"); @@ -28,26 +26,25 @@ impl StackOwnedHeap { /// /// # Unsafety /// - /// This function must be called at most once. The heap_buffer must remain valid until the end of the process. + /// This function must be called at most once. The memory between [`heap_location`] and [`heap_top`] must not overlap with any other memory section. #[inline(never)] - unsafe fn init(&mut self, heap_buffer: &mut [u8]) { - let heap_location = heap_buffer.as_ptr() as usize; - asm!("mov r9, $0" : : "r"(heap_location) : : "volatile"); - let heap = heap_location as *mut Heap; + unsafe fn init(&mut self, heap_bottom: usize, heap_top: usize) { + asm!("mov r9, $0" : : "r"(heap_bottom) : : "volatile"); - let heap_bottom = heap_location + mem::size_of::(); - let heap_top = heap_location + heap_buffer.len(); - *heap = Heap::new(heap_bottom, heap_top - heap_bottom); + let effective_heap_bottom = heap_bottom + mem::size_of::(); + + let heap = heap_bottom as *mut Heap; + *heap = Heap::new(effective_heap_bottom, heap_top - effective_heap_bottom); } } -unsafe impl<'a> Alloc for &'a StackOwnedHeap { - unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { - self.heap().alloc(layout) +unsafe impl GlobalAlloc for TockAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut Opaque { + self.heap().alloc(layout).unwrap().as_ptr() } - unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { - self.heap().dealloc(ptr, layout) + unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) { + self.heap().dealloc(NonNull::new_unchecked(ptr), layout) } } @@ -56,35 +53,24 @@ unsafe impl<'a> Alloc for &'a StackOwnedHeap { #[no_mangle] #[naked] #[link_section = ".start"] -pub extern "C" fn _start( - _text_start: usize, +pub unsafe extern "C" fn _start( + text_start: usize, mem_start: usize, _memory_len: usize, _app_heap_break: usize, ) -> ! { - unsafe { - asm!("mov sp, $0" : : "r"(mem_start + HEAP_SIZE + STACK_SIZE) : "memory" : "volatile" ); - run_with_new_stack() - } -} - -#[naked] -#[inline(never)] -unsafe fn run_with_new_stack() -> ! { extern "C" { // This function is created internally by`rustc`. See `src/lang_items.rs` for more details. fn main(argc: isize, argv: *const *const u8) -> isize; } - let mut heap: [u8; HEAP_SIZE as usize] = [0; HEAP_SIZE as usize]; - StackOwnedHeap.init(&mut heap); + let stack_size = *(text_start as *const usize).offset(9); + let real_stack_top = mem_start + stack_size; + // Set the effective stack top below the real stack stop and use the space in between for the heap + let effective_stack_top = real_stack_top - HEAP_SIZE; + TockAllocator.init(effective_stack_top, real_stack_top); - let mut console = Console::new(); - console.write(String::from( - "\nProcess started\n===============\nHeap position: ", - )); - console.write(fmt::u32_as_hex(heap.as_ptr() as u32)); - console.write(String::from("\n\n")); + asm!("mov sp, $0" : : "r"(effective_stack_top) : "memory" : "volatile" ); main(0, ptr::null()); diff --git a/src/ipc/server.rs b/src/ipc/server.rs index 3f49225c..3120c5a5 100644 --- a/src/ipc/server.rs +++ b/src/ipc/server.rs @@ -22,6 +22,7 @@ impl IpcServerCallback { impl SubscribableCallback for IpcServerCallback { fn call_rust(&mut self, arg0: usize, arg1: usize, arg2: usize) { + // FIXME: This is unsafe because IpcServerCallback can be subscribed on any driver let mut v = unsafe { slice::from_raw_parts_mut(arg2 as *mut u8, arg1) }; (self.callback)(arg0, arg1, &mut v); } diff --git a/src/lib.rs b/src/lib.rs index d7bc8739..dc561035 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,4 +33,4 @@ mod syscalls; #[cfg(target_arch = "arm")] #[global_allocator] -static ALLOCATOR: entry_point::StackOwnedHeap = entry_point::StackOwnedHeap; +static ALLOCATOR: entry_point::TockAllocator = entry_point::TockAllocator; diff --git a/src/shared_memory.rs b/src/shared_memory.rs index 538c5897..1d4a4f9e 100644 --- a/src/shared_memory.rs +++ b/src/shared_memory.rs @@ -2,12 +2,24 @@ use core::ptr; use syscalls; pub struct SharedMemory<'a> { - pub driver_number: usize, - pub allow_number: usize, - pub buffer_to_share: &'a mut [u8], + driver_number: usize, + allow_number: usize, + buffer_to_share: &'a mut [u8], } impl<'a> SharedMemory<'a> { + pub fn new( + driver_number: usize, + allow_number: usize, + buffer_to_share: &'a mut [u8], + ) -> SharedMemory<'a> { + SharedMemory { + driver_number, + allow_number, + buffer_to_share, + } + } + pub fn read_bytes(&self, destination: &mut [u8]) { safe_copy(self.buffer_to_share, destination); } diff --git a/src/syscalls.rs b/src/syscalls.rs index 7e8d5a0a..095c520c 100644 --- a/src/syscalls.rs +++ b/src/syscalls.rs @@ -110,11 +110,11 @@ pub fn allow( ) }; if return_code == 0 { - Ok(SharedMemory { + Ok(SharedMemory::new( driver_number, allow_number, buffer_to_share, - }) + )) } else { Err(return_code) } @@ -123,7 +123,7 @@ pub fn allow( pub unsafe fn allow_ptr(major: usize, minor: usize, slice: *mut u8, len: usize) -> isize { let res; asm!("svc 3" : "={r0}"(res) - : "{r0}"(major) "{r1}"(minor) "{r2}"(slice as *mut u8) "{r3}"(len) + : "{r0}"(major) "{r1}"(minor) "{r2}"(slice) "{r3}"(len) : "memory" : "volatile"); res diff --git a/tock b/tock index 8940d97c..fcf63601 160000 --- a/tock +++ b/tock @@ -1 +1 @@ -Subproject commit 8940d97cb09b24e987289c6587e16790a4dabaaa +Subproject commit fcf63601f0c4ee86d78e2c708bd0de1f77a009ab