Merge branch 'master' into raw-syscalls

I cleaned up the #![feature(min_const_generics)] statements because the toolchain update made them unnecessary.
diff --git a/Makefile b/Makefile
index a37e40c..b8d1f70 100644
--- a/Makefile
+++ b/Makefile
@@ -84,12 +84,19 @@
 	# Important: This tests a platform without atomic instructions.
 	PLATFORM=opentitan cargo build --release --target=riscv32imc-unknown-none-elf --examples -p libtock -p libtock_core
 
+# Arguments to pass to cargo to exclude libtock_runtime and crates that depend
+# on libtock_runtime. Used when we need to build a crate for the host OS, as
+# libtock_runtime only suppors running on Tock.
+EXCLUDE_RUNTIME := --exclude libtock_runtime
+
 .PHONY: test
 test: examples test-qemu-hifive
 	LIBTOCK_PLATFORM=nrf52 PLATFORM=nrf52 cargo fmt --all -- --check
 	PLATFORM=nrf52 cargo clippy --all-targets --exclude libtock_runtime --workspace
 	LIBTOCK_PLATFORM=hifive1 cargo clippy --target=riscv32imac-unknown-none-elf -p libtock_runtime
-	PLATFORM=nrf52 cargo miri test --exclude libtock_runtime --workspace
+	PLATFORM=nrf52 cargo miri test $(EXCLUDE_RUNTIME) --workspace
+	MIRIFLAGS="-Zmiri-symbolic-alignment-check -Zmiri-track-raw-pointers" \
+		PLATFORM=nrf52 cargo miri test $(EXCLUDE_RUNTIME) --workspace
 	echo '[ SUCCESS ] libtock-rs tests pass'
 
 .PHONY: analyse-stack-sizes
diff --git a/core/platform/src/command_return_tests.rs b/core/platform/src/command_return_tests.rs
index 439f9e7..85583ad 100644
--- a/core/platform/src/command_return_tests.rs
+++ b/core/platform/src/command_return_tests.rs
@@ -130,7 +130,7 @@
     assert_eq!(command_return.get_failure_2_u32(), None);
     assert_eq!(
         command_return.get_failure_u64(),
-        Some((ErrorCode::Busy, 0x00001003_00001002))
+        Some((ErrorCode::Busy, 0x0000_1003_0000_1002))
     );
     assert_eq!(command_return.get_success_u32(), None);
     assert_eq!(command_return.get_success_2_u32(), None);
@@ -240,7 +240,10 @@
     assert_eq!(command_return.get_failure_u64(), None);
     assert_eq!(command_return.get_success_u32(), None);
     assert_eq!(command_return.get_success_2_u32(), None);
-    assert_eq!(command_return.get_success_u64(), Some(0x00001002_00001001));
+    assert_eq!(
+        command_return.get_success_u64(),
+        Some(0x0000_1002_0000_1001)
+    );
     assert_eq!(command_return.get_success_3_u32(), None);
     assert_eq!(command_return.get_success_u32_u64(), None);
     assert_eq!(command_return.return_variant(), return_variant::SUCCESS_U64);
@@ -299,7 +302,7 @@
     assert_eq!(command_return.get_success_3_u32(), None);
     assert_eq!(
         command_return.get_success_u32_u64(),
-        Some((1001, 0x00001003_00001002))
+        Some((1001, 0x0000_1003_0000_1002))
     );
     assert_eq!(
         command_return.return_variant(),
diff --git a/core/platform/src/lib.rs b/core/platform/src/lib.rs
index 78293e3..e189975 100644
--- a/core/platform/src/lib.rs
+++ b/core/platform/src/lib.rs
@@ -1,5 +1,5 @@
-#![feature(min_const_generics)] // TODO: Remove when toolchain updated.
 #![no_std]
+#![warn(unsafe_op_in_unsafe_fn)]
 
 mod async_traits;
 mod command_return;
diff --git a/core/runtime/src/lib.rs b/core/runtime/src/lib.rs
index bd890ea..f705c45 100644
--- a/core/runtime/src/lib.rs
+++ b/core/runtime/src/lib.rs
@@ -21,8 +21,6 @@
 #![feature(asm)]
 #![no_std]
 #![warn(unsafe_op_in_unsafe_fn)]
-// TODO: Remove after toolchain upgrade, these have been stabilized.
-#![feature(min_const_generics, unsafe_block_in_unsafe_fn)]
 
 mod startup;
 
diff --git a/core/src/entry_point/start_item_arm.rs b/core/src/entry_point/start_item_arm.rs
index 894088e..5d88d6b 100644
--- a/core/src/entry_point/start_item_arm.rs
+++ b/core/src/entry_point/start_item_arm.rs
@@ -1,18 +1,12 @@
-use core::hint;
-
 /// Tock programs' entry point. Called by the kernel at program start. Sets up
 /// the stack then calls rust_start() for the remainder of setup.
 #[doc(hidden)]
 #[no_mangle]
 #[naked]
 #[link_section = ".start"]
-pub unsafe extern "C" fn _start(
-    app_start: usize,
-    mem_start: usize,
-    _memory_len: usize,
-    app_heap_break: usize,
-) -> ! {
-    llvm_asm!("
+pub unsafe extern "C" fn _start() -> ! {
+    asm!(
+        "
         // Because ROPI-RWPI support in LLVM/rustc is incomplete, Rust
         // applications must be statically linked. An offset between the
         // location the program is linked at and its actual location in flash
@@ -102,12 +96,8 @@
         mov r2, r8
 
         // Call rust_start
-        bl rust_start"
-        :                                                              // No output operands
-        : "{r0}"(app_start), "{r1}"(mem_start), "{r3}"(app_heap_break) // Input operands
-        : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r12",
-          "cc", "memory"                                               // Clobbers
-        : "volatile"                                                   // Options
-    );
-    hint::unreachable_unchecked()
+        bl rust_start",
+        // No clobbers because we don't return.
+        options(noreturn),
+    )
 }
diff --git a/core/src/entry_point/start_item_riscv32.rs b/core/src/entry_point/start_item_riscv32.rs
index f8a0e19..ec63591 100644
--- a/core/src/entry_point/start_item_riscv32.rs
+++ b/core/src/entry_point/start_item_riscv32.rs
@@ -1,5 +1,3 @@
-use core::hint;
-
 /// Tock programs' entry point. Called by the kernel at program start. Sets up
 /// the stack then calls rust_start() for the remainder of setup.
 #[doc(hidden)]
@@ -14,12 +12,12 @@
 // Due to Rust issue: https://github.com/rust-lang/rust/issues/42779 we can't have
 // args to the function
 pub unsafe extern "C" fn _start() -> ! {
-    llvm_asm!(
-    // Compute the stack top.
-    //
-    // struct hdr* myhdr = (struct hdr*) app_start;
-    // uint32_t stacktop = (((uint32_t) mem_start + myhdr->stack_size + 7) & 0xfffffff8);
-    "lw   t0, 36(a0)         // t0 = myhdr->stack_size
+    asm!(
+        // Compute the stack top.
+        //
+        // struct hdr* myhdr = (struct hdr*) app_start;
+        // uint32_t stacktop = (((uint32_t) mem_start + myhdr->stack_size + 7) & 0xfffffff8);
+        "lw   t0, 36(a0)         // t0 = myhdr->stack_size
     addi t0, t0, 7          // t0 = myhdr->stack_size + 7
     add  t0, t0, a1         // t0 = mem_start + myhdr->stack_size + 7
     li   t1, 7              // t1 = 7
@@ -89,14 +87,10 @@
     mv   s0, sp             // Set the frame pointer to sp.
     mv   a1, s1             // second arg is stacktop
     mv   a2, t1             // third arg is app_heap_break that we told the kernel
-    jal  rust_start"
-    :                                                              // No output operands
-    :
-    : "memory", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17",
-      "x5", "x6", "x7", "x28", "x29", "x30", "x31", "x1"           // Clobbers
-    : "volatile"                                                   // Options
-    );
-    hint::unreachable_unchecked();
+    jal  rust_start",
+        // No clobbers needed for a noreturn asm! block.
+        options(noreturn),
+    )
 }
 
 /// Ensure an abort symbol exists.
diff --git a/core/src/lib.rs b/core/src/lib.rs
index 717dc41..6281d18 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -1,4 +1,4 @@
-#![feature(lang_items, llvm_asm, naked_functions)]
+#![feature(asm, lang_items, llvm_asm, naked_functions)]
 #![cfg_attr(any(target_arch = "arm", target_arch = "riscv32"), no_std)]
 #![cfg_attr(feature = "alloc", feature(alloc_error_handler))]
 
diff --git a/doc/MiriTips.md b/doc/MiriTips.md
new file mode 100644
index 0000000..5c88964
--- /dev/null
+++ b/doc/MiriTips.md
@@ -0,0 +1,42 @@
+Miri Tips
+=========
+
+`libtock-rs` runs most of its unit tests under
+[Miri](https://github.com/rust-lang/miri) to detect undefined behavior. However,
+Miri does not detect all undefined behavior encountered. This document lists
+techniques for maximizing the amount of undefined behavior identified by Miri.
+
+## Miri flags
+
+Miri has [configuration
+flags](https://github.com/rust-lang/miri#miri--z-flags-and-environment-variables),
+which can be set using the `MIRIFLAGS` environment variable. We run the tests
+both with and without `-Zmiri-track-raw-pointers`, as both versions of Stacked
+Borrows has undefined behavior the other does not (see [this
+discussion](https://github.com/rust-lang/miri/pull/1748) for more information).
+On the run with `-Zmiri-track-raw-pointers`, we also set
+`-Zmiri-symbolic-alignment-check` to make Miri's alignment check more pendantic.
+
+## Detecting invalid values
+
+Miri does not always detect undefined behavior when an invalid value is created
+but not used. Here are some cases that Miri currently accepts:
+
+1. Unused reference to an invalid value
+   (https://github.com/rust-lang/miri/issues/1638)
+1. Unused uninitialized value (https://github.com/rust-lang/miri/issues/1340)
+1. Slices pointing to invalid values
+   (https://github.com/rust-lang/miri/issues/1240)
+
+Note that copying the value around (including passing it to functions) does
+*not* count as a use for the purpose of this check.
+
+For types that implement `core::fmt::Debug` (i.e. most types), you can check a
+value is valid by attempting to debug-print it:
+
+```rust
+format!("{:?}", value);
+```
+
+If `value` is invalid, then Miri will identify undefined behavior in the above
+code.
diff --git a/layout_generic.ld b/layout_generic.ld
index 0bbef87..3a77ad7 100644
--- a/layout_generic.ld
+++ b/layout_generic.ld
@@ -24,9 +24,15 @@
     /* Section for just the app crt0 header.
      * This must be first so that the app can find it.
      */
-    .crt0_header :
+    /* Runtime setup logic. The crt0_header symbol is used by the entry point
+     * assembly. We have to include start here rather than .text because
+     * otherwise elf2tab fails to recognize that the process binary's flash
+     * region should start at the beginning of .start.
+     */
+    .start :
     {
         _beginning = .; /* Start of the app in flash. */
+        crt0_header = .;
         /**
          * Populate the header expected by `crt0`:
          *
@@ -68,6 +74,8 @@
          * between the header and subsequent .data section. It's unclear why,
          * but LLD is aligning sections to a multiple of 32 bytes. */
         . = ALIGN(32);
+
+        *(.start)
     } > FLASH =0xFF
 
     /* Text section, Code! */
@@ -75,7 +83,6 @@
     {
         . = ALIGN(4);
         _text = .;
-        KEEP (*(.start))
         *(.text*)
         *(.rodata*)
         KEEP (*(.syscalls))
@@ -140,30 +147,10 @@
     {
     } > 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.
-     *
-     * __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 :
-    {
-      /* (C++) Index entries for section unwinding */
-      *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-    } > FLASH
-    PROVIDE_HIDDEN (__exidx_end = .);
-
+    /* Sections we do not need. */
     /DISCARD/ :
     {
-      *(.eh_frame)
+      *(.ARM.exidx .eh_frame)
     }
 }
 
diff --git a/rust-toolchain b/rust-toolchain
index 0a379e7..1674405 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,7 +1,7 @@
 [toolchain]
 # See https://rust-lang.github.io/rustup-components-history/ for a list of
 # recently nightlies and what components are available for them.
-channel = "nightly-2020-08-20"
+channel = "nightly-2021-03-25"
 components = ["clippy", "miri", "rustfmt"]
 targets = ["thumbv7em-none-eabi",
            "riscv32imac-unknown-none-elf",
diff --git a/src/ble_composer.rs b/src/ble_composer.rs
index 589dfc3..d470378 100644
--- a/src/ble_composer.rs
+++ b/src/ble_composer.rs
@@ -15,7 +15,7 @@
 }
 
 impl BlePayload {
-    pub fn add(&mut self, kind: u8, content: &[u8]) -> Result<(), ()> {
+    pub fn add(&mut self, kind: u8, content: &[u8]) -> Result<(), Overflow> {
         self.check_can_write_num_bytes(content.len() + 2)?;
 
         self.bytes[self.occupied] = (content.len() + 1) as u8;
@@ -26,7 +26,7 @@
         Ok(())
     }
 
-    pub fn add_flag(&mut self, flag: u8) -> Result<(), ()> {
+    pub fn add_flag(&mut self, flag: u8) -> Result<(), Overflow> {
         self.check_can_write_num_bytes(3)?;
 
         self.bytes[self.occupied] = 2;
@@ -36,7 +36,7 @@
         Ok(())
     }
 
-    pub fn add_service_payload(&mut self, uuid: [u8; 2], content: &[u8]) -> Result<(), ()> {
+    pub fn add_service_payload(&mut self, uuid: [u8; 2], content: &[u8]) -> Result<(), Overflow> {
         self.check_can_write_num_bytes(4 + content.len())?;
         self.bytes[self.occupied] = (content.len() + 3) as u8;
         self.bytes[self.occupied + 1] = gap_types::SERVICE_DATA;
@@ -49,11 +49,11 @@
         Ok(())
     }
 
-    fn check_can_write_num_bytes(&self, number: usize) -> Result<(), ()> {
+    fn check_can_write_num_bytes(&self, number: usize) -> Result<(), Overflow> {
         if self.occupied + number <= self.bytes.len() {
             Ok(())
         } else {
-            Err(())
+            Err(Overflow)
         }
     }
 }
@@ -72,6 +72,10 @@
     }
 }
 
+// Error type returned when the buffer is too full to perform an operation.
+#[derive(Debug)]
+pub struct Overflow;
+
 #[cfg(test)]
 mod test {
     use super::*;
diff --git a/src/debug/mod.rs b/src/debug/mod.rs
index 85b4337..68d32eb 100644
--- a/src/debug/mod.rs
+++ b/src/debug/mod.rs
@@ -28,7 +28,7 @@
     write_as_hex(&mut buffer[12..22], *address);
     for index in 0..4 {
         let byte = *(address as *const u8).offset(index);
-        let byte_is_printable_char = byte >= 0x20 && byte < 0x80;
+        let byte_is_printable_char = (0x20..0x80).contains(&byte);
         if byte_is_printable_char {
             buffer[23 + index as usize] = byte;
         }
diff --git a/src/sensors/mod.rs b/src/sensors/mod.rs
index f3a0e7a..f9196d2 100644
--- a/src/sensors/mod.rs
+++ b/src/sensors/mod.rs
@@ -46,9 +46,9 @@
             }
         }
 
-        impl Into<i32> for $type_name {
-            fn into(self) -> i32 {
-                self.value
+        impl From<$type_name> for i32 {
+            fn from(sensor: $type_name) -> i32 {
+                sensor.value
             }
         }
 
diff --git a/test_runner/src/main.rs b/test_runner/src/main.rs
index b21b945..5ab9c1a 100644
--- a/test_runner/src/main.rs
+++ b/test_runner/src/main.rs
@@ -53,8 +53,8 @@
 }
 
 fn test_succeeded(input: String, failed_tests: &mut Vec<String>) -> Option<bool> {
-    let success = input.find("[      OK ]").is_some();
-    let failure = input.find("[ FAILURE ]").is_some();
+    let success = input.contains("[      OK ]");
+    let failure = input.contains("[ FAILURE ]");
     let input = input.replace("[      OK ]", "");
     let input = input.replace("[ FAILURE ]", "");
     let input = input.trim();
diff --git a/tools/print_sizes/src/main.rs b/tools/print_sizes/src/main.rs
index dcd7777..12f05c4 100644
--- a/tools/print_sizes/src/main.rs
+++ b/tools/print_sizes/src/main.rs
@@ -117,18 +117,21 @@
         .expect("No examples found");
     let section_width = 7;
 
-    // TODO: We do not currently print out .rodata's size. Currently, the linker
-    // script embeds .rodata in .text, so we don't see it as a separate section
-    // here. We should modify the linker script to put .rodata in its own
-    // section. Until that is done, .rodata's size will be counted as part of
-    // .text, so we'll just print .text's size for now.
     println!(
-        "{0:1$} {2:3$} {4:>7$} {5:>7$} {6:>7$}",
-        "Example", name_width, "Architecture", arch_width, ".bss", ".data", ".text", section_width
+        "{0:1$} {2:3$} {4:>8$} {5:>8$} {6:>8$} {7:>8$}",
+        "Example",
+        name_width,
+        "Architecture",
+        arch_width,
+        ".bss",
+        ".data",
+        ".text",
+        ".rodata",
+        section_width
     );
     for data in example_data {
         println!(
-            "{0:1$} {2:3$} {4:7$} {5:7$} {6:7$}",
+            "{0:1$} {2:3$} {4:8$} {5:8$} {6:8$} {7:8$}",
             data.name,
             name_width,
             data.arch,
@@ -136,6 +139,7 @@
             data.sizes.bss,
             data.sizes.data,
             data.sizes.text,
+            data.sizes.rodata,
             section_width
         );
     }