Merge #275 #276

275: Add `libtock_runtime` startup code. r=alistair23 a=jrvanwhy

This includes:

1. `rust_start`: The first Rust code to run in a process
1. `set_main!`: Used to specify `main` in a process binary
1. `stack_size!`: Used to specify the stack size in a process binary
1. Documentation of the startup sequence, including the 3 above steps.

The documentation refers to a two things that haven't been implemented yet:
1. Debug syscalls performed by `rust_start` -- unimplemented because `memop` is
   still unimplemented.
1. The `exit` system call.

276: Add a tock2 submodule with a tock-2.0-dev kernel. r=alistair23 a=jrvanwhy

I intend to use this kernel in integration tests for the Tock 2.0 crates. When we are ready to remove Tock 1.x support, I will remove the duplicate submodule.

Co-authored-by: Johnathan Van Why <jrvanwhy@google.com>
diff --git a/.gitmodules b/.gitmodules
index 45ddcde..d21db5e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
 [submodule "tock"]
 	path = tock
 	url = https://github.com/tock/tock.git
+[submodule "tock2"]
+	path = tock2
+	url = https://github.com/tock/tock.git
diff --git a/Makefile b/Makefile
index e228ab3..a37e40c 100644
--- a/Makefile
+++ b/Makefile
@@ -54,6 +54,14 @@
 	$(MAKE) -C tock/boards/hifive1 \
 		$(CURDIR)/tock/target/riscv32imac-unknown-none-elf/release/hifive1.elf
 
+# Builds a Tock 2.0 kernel for the HiFive board for use by QEMU tests.
+# TODO: After Tock 2.0 is released, we should merge the tock/ and tock2/
+# submodules and only build Tock 2.0 kernels.
+.PHONY: kernel-hifive-2
+kernel-hifive-2:
+	$(MAKE) -C tock2/boards/hifive1 \
+		$(CURDIR)/tock2/target/riscv32imac-unknown-none-elf/release/hifive1.elf
+
 # Prints out the sizes of the example binaries.
 .PHONY: print-sizes
 print-sizes: examples
diff --git a/core/runtime/src/lib.rs b/core/runtime/src/lib.rs
index b0daf03..7e2e1ca 100644
--- a/core/runtime/src/lib.rs
+++ b/core/runtime/src/lib.rs
@@ -21,6 +21,8 @@
 #![feature(asm)]
 #![no_std]
 
+mod startup;
+
 /// TockSyscalls implements `libtock_platform::Syscalls`.
 pub struct TockSyscalls;
 
diff --git a/core/runtime/src/startup.rs b/core/runtime/src/startup.rs
new file mode 100644
index 0000000..f99d402
--- /dev/null
+++ b/core/runtime/src/startup.rs
@@ -0,0 +1,61 @@
+//! Runtime components related to process startup.
+
+/// `set_main!` is used to tell `libtock_runtime` where the process binary's
+/// `main` function is. The process binary's `main` function must have the
+/// signature `FnOnce() -> !`.
+///
+/// # Example
+/// ```
+/// libtock_runtime::set_main!{main};
+///
+/// fn main() -> ! { /* Omitted */ }
+/// ```
+// set_main! generates a function called `libtock_unsafe_main`, which is called
+// by `rust_start`. The function has `unsafe` in its name because implementing
+// it is `unsafe` (it *must* have the signature `libtock_unsafe_main() -> !`),
+// but there is no way to enforce the use of `unsafe` through the type system.
+// This function calls the client-provided function, which enforces its type
+// signature.
+#[macro_export]
+macro_rules! set_main {
+    {$name:ident} => {
+        #[no_mangle]
+        fn libtock_unsafe_main() -> ! {
+            $name()
+        }
+    }
+}
+
+/// Executables must specify their stack size by using the `stack_size!` macro.
+/// It takes a single argument, the desired stack size in bytes. Example:
+/// ```
+/// stack_size!{0x400}
+/// ```
+// stack_size works by putting a symbol equal to the size of the stack in the
+// .stack_buffer section. The linker script uses the .stack_buffer section to
+// size the stack. flash.sh looks for the symbol by name (hence #[no_mangle]) to
+// determine the size of the stack to pass to elf2tab.
+#[macro_export]
+macro_rules! stack_size {
+    {$size:expr} => {
+        #[no_mangle]
+        #[link_section = ".stack_buffer"]
+        pub static mut STACK_MEMORY: [u8; $size] = [0; $size];
+    }
+}
+
+// rust_start is the first Rust code to execute in the process. It is called
+// from start, which is written directly in assembly.
+#[no_mangle]
+extern "C" fn rust_start() -> ! {
+    // TODO: Call memop() to inform the kernel of the stack and heap sizes +
+    // locations. Also, perhaps we should support calling a heap initialization
+    // function?
+
+    extern "Rust" {
+        fn libtock_unsafe_main() -> !;
+    }
+    unsafe {
+        libtock_unsafe_main();
+    }
+}
diff --git a/doc/Startup.md b/doc/Startup.md
new file mode 100644
index 0000000..88816ab
--- /dev/null
+++ b/doc/Startup.md
@@ -0,0 +1,60 @@
+Startup
+=======
+
+This document describes the `libtock_runtime` startup process, up until the
+process binary's `main` starts executing.
+
+## Step 1: `start` assembly
+
+The first code to start executing is in a symbol called `start`, which is
+written in handwritten assembly. These implementations are specific to each
+architecture, and live in `runtime/asm`. This assembly does the following:
+
+1. Checks the initial program counter value against the correct `start` address.
+   This verifies the process was deployed at the direct address in non-volatile
+   storage. This is necessary because `libtock-rs` apps are statically-linked,
+   and an incorrect location would cause undefined behavior. If this check
+   fails, an error may be reported (if the `low_level_debug` capsule is present)
+   and the process terminates.
+1. Moves the process break to make room for the stack, `.data`, and `.bss`. The
+   process break is the top of the process-accessible RAM. The process break is
+   initially moved to be shortly after the end of the `.bss` section (depending
+   on alignment constraints).
+1. Initialize the stack. The initial stack pointer value is provided by the
+   linker script, which calculates it using a symbol called `STACK_MEMORY` in
+   the `.stack_buffer` section.
+1. Copies `.data` from non-volatile storage into RAM. The .data section contains
+   read-write global variables (e.g. `static mut` values) that have nonzero
+   initial values.
+1. Zeroes out `.bss`. `.bss` contains read-write global variables that have zero
+   initial values.
+1. Calls `rust_start`.
+
+## Step 2: `rust_start`
+
+`rust_start` is the first Rust code to execute in a process. It is defined in
+the `libtock_runtime::startup` module. It runs some higher-level initialization,
+such as giving debug information (stack and heap addresses) to the kernel.
+`rust_start` then calls `libtock_unsafe_main`.
+
+## Step 3: `libtock_unsafe_main`
+
+`libtock_unsafe_main` is a shim used to direct execution from `libtock_runtime`
+to the process binary's `main` function. It is generated by the
+`libtock_runtime::set_main!` macro. `libtock_unsafe_main` just calls the
+user-provided `main` function.
+
+## Step 4: `main`
+
+At this point, the user's `main` starts executing, and `libtock_runtime` is no
+longer in control. Note that unlike most Rust programs, `main` is expected to
+*not* return. Process binaries can loop forever or use the `exit` system call to
+terminate when they are done executing (which may be done as the last statement
+of `main`).
+
+## Appendix: Why `#![no_main]`?
+
+Writing a `#![no_std]` `bin` crate currently requires using either `#![no_main]`
+or the `start` unstable feature. Because we want to move `libtock-rs` to stable
+Rust eventually (hopefully soon after `asm` is stabilized), `libtock-rs` expects
+process binaries to be `#![no_main]`.
diff --git a/tock2 b/tock2
new file mode 160000
index 0000000..17e698e
--- /dev/null
+++ b/tock2
@@ -0,0 +1 @@
+Subproject commit 17e698e8fb2c9628624398435f75db0f5a50dbcd