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/.cargo/config b/.cargo/config
index 96fe275..8292c1c 100644
--- a/.cargo/config
+++ b/.cargo/config
@@ -6,10 +6,6 @@
rthumbv7em = "run --release --target=thumbv7em-none-eabi --example"
rtv7em = "rthumbv7em"
-# Deny warnings on all architectures. build.rustflags cannot be used here as the lower section would override its effect.
-[target.'cfg(all())']
-rustflags = ["-D", "warnings"]
-
# Common settings for all embedded targets
[target.'cfg(any(target_arch = "arm", target_arch = "riscv32"))']
rustflags = [
diff --git a/.github/workflows/artifacts.yml b/.github/workflows/artifacts.yml
index 94a8b10..d394011 100644
--- a/.github/workflows/artifacts.yml
+++ b/.github/workflows/artifacts.yml
@@ -12,6 +12,7 @@
- name: Install dependencies
run: |
+ sudo apt-get install binutils-riscv64-unknown-elf
cargo install elf2tab --version 0.4.0
- name: Build Hello World
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5bdae5f..e9b448b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,9 +16,9 @@
# Using ubuntu-latest can cause breakage when ubuntu-latest is updated to
# point at a new Ubuntu version. Instead, explicitly specify the version, so
# we can update when we need to. This *could* break if we don't update it
- # until support for 18.04 is dropped, but it is likely we'll have a reason
+ # until support for 20.04 is dropped, but it is likely we'll have a reason
# to update to a newer Ubuntu before then anyway.
- runs-on: ubuntu-18.04
+ runs-on: ubuntu-20.04
steps:
# Clones a single commit from the libtock-rs repository. The commit cloned
@@ -35,8 +35,16 @@
# makefile can be tested locally. We experimentally determined that -j2 is
# optimal for the Azure Standard_DS2_v2 VM, which is the VM type used by
# GitHub Actions at the time of this writing.
+ #
+ # We have to append the "-D warnings" flag to .cargo/config rather than
+ # using the RUSTFLAGS environment variable because if we set RUSTFLAGS
+ # cargo will ignore the rustflags config in .cargo/config, breaking
+ # relocation.
- name: Build and Test
run: |
+ sudo apt-get install binutils-riscv64-unknown-elf
cd "${GITHUB_WORKSPACE}"
+ echo "[target.'cfg(all())']" >> .cargo/config
+ echo 'rustflags = ["-D", "warnings"]' >> .cargo/config
make -j2 setup
make -j2 test
diff --git a/.github/workflows/mac-os.yml b/.github/workflows/mac-os.yml
new file mode 100644
index 0000000..c813ace
--- /dev/null
+++ b/.github/workflows/mac-os.yml
@@ -0,0 +1,27 @@
+# This workflow verifies libtock-rs is usable on Mac OS.
+
+name: ci-mac-os
+
+# We run this workflow during pull request review, but not for Bors merges, as
+# it takes over an hour to run.
+on: pull_request
+
+jobs:
+ ci-mac-os:
+ runs-on: macos-10.15
+
+ steps:
+ # Clones a single commit from the libtock-rs repository. The commit cloned
+ # is a merge commit between the PR's target branch and the PR's source.
+ - name: Clone repository
+ uses: actions/checkout@v2.3.0
+
+ # Install the toolchains we need, then run `cargo build`.
+ - name: Build and Test
+ run: |
+ brew tap riscv/riscv
+ brew update
+ brew install riscv-gnu-toolchain --with-multilib
+ cd "${GITHUB_WORKSPACE}"
+ LIBTOCK_PLATFORM=hifive1 cargo build -p libtock_runtime \
+ --target=riscv32imac-unknown-none-elf
diff --git a/.github/workflows/size-diff.yml b/.github/workflows/size-diff.yml
index cbf2939..33a0870 100644
--- a/.github/workflows/size-diff.yml
+++ b/.github/workflows/size-diff.yml
@@ -17,9 +17,9 @@
# Using ubuntu-latest can cause breakage when ubuntu-latest is updated to
# point at a new Ubuntu version. Instead, explicitly specify the version, so
# we can update when we need to. This *could* break if we don't update it
- # until support for 18.04 is dropped, but it is likely we'll have a reason
+ # until support for 20.04 is dropped, but it is likely we'll have a reason
# to update to a newer Ubuntu before then anyway.
- runs-on: ubuntu-18.04
+ runs-on: ubuntu-20.04
steps:
# Clones a single commit from the libtock-rs repository. The commit cloned
@@ -39,6 +39,7 @@
# master.
- name: Compute sizes
run: |
+ sudo apt-get install binutils-riscv64-unknown-elf
UPSTREAM_REMOTE_NAME="${UPSTREAM_REMOTE_NAME:-origin}"
GITHUB_BASE_REF="${GITHUB_BASE_REF:-master}"
cd "${GITHUB_WORKSPACE}"
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 da40d28..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
@@ -79,8 +87,9 @@
.PHONY: test
test: examples test-qemu-hifive
LIBTOCK_PLATFORM=nrf52 PLATFORM=nrf52 cargo fmt --all -- --check
- LIBTOCK_PLATFORM=nrf52 PLATFORM=nrf52 cargo clippy --workspace --all-targets
- LIBTOCK_PLATFORM=nrf52 PLATFORM=nrf52 cargo miri test --workspace
+ 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
echo '[ SUCCESS ] libtock-rs tests pass'
.PHONY: analyse-stack-sizes
diff --git a/core/platform/src/command_return.rs b/core/platform/src/command_return.rs
index 7fa7302..9d84572 100644
--- a/core/platform/src/command_return.rs
+++ b/core/platform/src/command_return.rs
@@ -1,22 +1,43 @@
use crate::{return_variant, ErrorCode, ReturnVariant};
+use core::mem::transmute;
+
/// The response type from `command`. Can represent a successful value or a
/// failure.
#[derive(Clone, Copy)]
pub struct CommandReturn {
- pub(crate) return_variant: ReturnVariant,
+ return_variant: ReturnVariant,
// r1, r2, and r3 should only contain 32-bit values. However, these are
// converted directly from usizes returned by RawSyscalls::four_arg_syscall.
// To avoid casting twice (both when converting to a Command Return and when
// calling a get_*() function), we store the usizes directly. Then using the
// CommandReturn only involves one conversion for each of r1, r2, and r3,
// performed in the get_*() functions.
- pub(crate) r1: usize,
- pub(crate) r2: usize,
- pub(crate) r3: usize,
+
+ // Safety invariant on r1: If return_variant is failure variant, r1 must be
+ // a valid ErrorCode.
+ r1: usize,
+ r2: usize,
+ r3: usize,
}
impl CommandReturn {
+ /// # Safety
+ /// If return_variant is a failure variant, r1 must be a valid ErrorCode.
+ #[cfg(test)] // Will be removed when command() is implemented.
+ pub(crate) unsafe fn new(
+ return_variant: ReturnVariant,
+ r1: usize,
+ r2: usize,
+ r3: usize,
+ ) -> Self {
+ CommandReturn {
+ return_variant,
+ r1,
+ r2,
+ r3,
+ }
+ }
// I generally expect CommandReturn to be used with pattern matching, e.g.:
//
// let command_return = Syscalls::command(314, 1, 1, 2);
@@ -85,7 +106,7 @@
if !self.is_failure() {
return None;
}
- Some(self.r1.into())
+ Some(unsafe { transmute(self.r1 as u16) })
}
/// Returns the error code and value if this CommandReturn is of type
@@ -94,7 +115,7 @@
if !self.is_failure_u32() {
return None;
}
- Some((self.r1.into(), self.r2 as u32))
+ Some((unsafe { transmute(self.r1 as u16) }, self.r2 as u32))
}
/// Returns the error code and return values if this CommandReturn is of
@@ -103,7 +124,11 @@
if !self.is_failure_2_u32() {
return None;
}
- Some((self.r1.into(), self.r2 as u32, self.r3 as u32))
+ Some((
+ unsafe { transmute(self.r1 as u16) },
+ self.r2 as u32,
+ self.r3 as u32,
+ ))
}
/// Returns the error code and return value if this CommandReturn is of type
@@ -112,7 +137,10 @@
if !self.is_failure_u64() {
return None;
}
- Some((self.r1.into(), self.r2 as u64 + ((self.r3 as u64) << 32)))
+ Some((
+ unsafe { transmute(self.r1 as u16) },
+ self.r2 as u64 + ((self.r3 as u64) << 32),
+ ))
}
/// Returns the value if this CommandReturn is of type Success with u32.
diff --git a/core/platform/src/command_return_tests.rs b/core/platform/src/command_return_tests.rs
index 1712f71..439f9e7 100644
--- a/core/platform/src/command_return_tests.rs
+++ b/core/platform/src/command_return_tests.rs
@@ -1,12 +1,14 @@
-use crate::{error_code, return_variant, CommandReturn};
+use crate::{return_variant, CommandReturn, ErrorCode};
#[test]
fn failure() {
- let command_return = CommandReturn {
- return_variant: return_variant::FAILURE,
- r1: error_code::RESERVE.into(),
- r2: 1002,
- r3: 1003,
+ let command_return = unsafe {
+ CommandReturn::new(
+ return_variant::FAILURE,
+ ErrorCode::Reserve as usize,
+ 1002,
+ 1003,
+ )
};
assert_eq!(command_return.is_failure(), true);
assert_eq!(command_return.is_failure_u32(), false);
@@ -18,7 +20,7 @@
assert_eq!(command_return.is_success_u64(), false);
assert_eq!(command_return.is_success_3_u32(), false);
assert_eq!(command_return.is_success_u32_u64(), false);
- assert_eq!(command_return.get_failure(), Some(error_code::RESERVE));
+ assert_eq!(command_return.get_failure(), Some(ErrorCode::Reserve));
assert_eq!(command_return.get_failure_u32(), None);
assert_eq!(command_return.get_failure_2_u32(), None);
assert_eq!(command_return.get_failure_u64(), None);
@@ -32,11 +34,13 @@
#[test]
fn failure_u32() {
- let command_return = CommandReturn {
- return_variant: return_variant::FAILURE_U32,
- r1: error_code::OFF.into(),
- r2: 1002,
- r3: 1003,
+ let command_return = unsafe {
+ CommandReturn::new(
+ return_variant::FAILURE_U32,
+ ErrorCode::Off as usize,
+ 1002,
+ 1003,
+ )
};
assert_eq!(command_return.is_failure(), false);
assert_eq!(command_return.is_failure_u32(), true);
@@ -51,7 +55,7 @@
assert_eq!(command_return.get_failure(), None);
assert_eq!(
command_return.get_failure_u32(),
- Some((error_code::OFF, 1002))
+ Some((ErrorCode::Off, 1002))
);
assert_eq!(command_return.get_failure_2_u32(), None);
assert_eq!(command_return.get_failure_u64(), None);
@@ -65,11 +69,13 @@
#[test]
fn failure_2_u32() {
- let command_return = CommandReturn {
- return_variant: return_variant::FAILURE_2_U32,
- r1: error_code::ALREADY.into(),
- r2: 1002,
- r3: 1003,
+ let command_return = unsafe {
+ CommandReturn::new(
+ return_variant::FAILURE_2_U32,
+ ErrorCode::Already as usize,
+ 1002,
+ 1003,
+ )
};
assert_eq!(command_return.is_failure(), false);
assert_eq!(command_return.is_failure_u32(), false);
@@ -85,7 +91,7 @@
assert_eq!(command_return.get_failure_u32(), None);
assert_eq!(
command_return.get_failure_2_u32(),
- Some((error_code::ALREADY, 1002, 1003))
+ Some((ErrorCode::Already, 1002, 1003))
);
assert_eq!(command_return.get_failure_u64(), None);
assert_eq!(command_return.get_success_u32(), None);
@@ -101,11 +107,13 @@
#[test]
fn failure_u64() {
- let command_return = CommandReturn {
- return_variant: return_variant::FAILURE_U64,
- r1: error_code::BUSY.into(),
- r2: 0x00001002,
- r3: 0x00001003,
+ let command_return = unsafe {
+ CommandReturn::new(
+ return_variant::FAILURE_U64,
+ ErrorCode::Busy as usize,
+ 0x1002,
+ 0x1003,
+ )
};
assert_eq!(command_return.is_failure(), false);
assert_eq!(command_return.is_failure_u32(), false);
@@ -122,7 +130,7 @@
assert_eq!(command_return.get_failure_2_u32(), None);
assert_eq!(
command_return.get_failure_u64(),
- Some((error_code::BUSY, 0x00001003_00001002))
+ Some((ErrorCode::Busy, 0x00001003_00001002))
);
assert_eq!(command_return.get_success_u32(), None);
assert_eq!(command_return.get_success_2_u32(), None);
@@ -134,12 +142,7 @@
#[test]
fn success() {
- let command_return = CommandReturn {
- return_variant: return_variant::SUCCESS,
- r1: 1001,
- r2: 1002,
- r3: 1003,
- };
+ let command_return = unsafe { CommandReturn::new(return_variant::SUCCESS, 1001, 1002, 1003) };
assert_eq!(command_return.is_failure(), false);
assert_eq!(command_return.is_failure_u32(), false);
assert_eq!(command_return.is_failure_2_u32(), false);
@@ -164,12 +167,8 @@
#[test]
fn success_u32() {
- let command_return = CommandReturn {
- return_variant: return_variant::SUCCESS_U32,
- r1: 1001,
- r2: 1002,
- r3: 1003,
- };
+ let command_return =
+ unsafe { CommandReturn::new(return_variant::SUCCESS_U32, 1001, 1002, 1003) };
assert_eq!(command_return.is_failure(), false);
assert_eq!(command_return.is_failure_u32(), false);
assert_eq!(command_return.is_failure_2_u32(), false);
@@ -194,12 +193,8 @@
#[test]
fn success_2_u32() {
- let command_return = CommandReturn {
- return_variant: return_variant::SUCCESS_2_U32,
- r1: 1001,
- r2: 1002,
- r3: 1003,
- };
+ let command_return =
+ unsafe { CommandReturn::new(return_variant::SUCCESS_2_U32, 1001, 1002, 1003) };
assert_eq!(command_return.is_failure(), false);
assert_eq!(command_return.is_failure_u32(), false);
assert_eq!(command_return.is_failure_2_u32(), false);
@@ -227,12 +222,8 @@
#[test]
fn success_u64() {
- let command_return = CommandReturn {
- return_variant: return_variant::SUCCESS_U64,
- r1: 0x00001001,
- r2: 0x00001002,
- r3: 1003,
- };
+ let command_return =
+ unsafe { CommandReturn::new(return_variant::SUCCESS_U64, 0x1001, 0x1002, 1003) };
assert_eq!(command_return.is_failure(), false);
assert_eq!(command_return.is_failure_u32(), false);
assert_eq!(command_return.is_failure_2_u32(), false);
@@ -257,12 +248,8 @@
#[test]
fn success_3_u32() {
- let command_return = CommandReturn {
- return_variant: return_variant::SUCCESS_3_U32,
- r1: 1001,
- r2: 1002,
- r3: 1003,
- };
+ let command_return =
+ unsafe { CommandReturn::new(return_variant::SUCCESS_3_U32, 1001, 1002, 1003) };
assert_eq!(command_return.is_failure(), false);
assert_eq!(command_return.is_failure_u32(), false);
assert_eq!(command_return.is_failure_2_u32(), false);
@@ -290,12 +277,8 @@
#[test]
fn success_u32_u64() {
- let command_return = CommandReturn {
- return_variant: return_variant::SUCCESS_U32_U64,
- r1: 1001,
- r2: 0x00001002,
- r3: 0x00001003,
- };
+ let command_return =
+ unsafe { CommandReturn::new(return_variant::SUCCESS_U32_U64, 1001, 0x1002, 0x1003) };
assert_eq!(command_return.is_failure(), false);
assert_eq!(command_return.is_failure_u32(), false);
assert_eq!(command_return.is_failure_2_u32(), false);
diff --git a/core/platform/src/error_code.rs b/core/platform/src/error_code.rs
index 63cc34e..276e703 100644
--- a/core/platform/src/error_code.rs
+++ b/core/platform/src/error_code.rs
@@ -1,39 +1,232 @@
-/// A system call error code. This can either be an error code returned by the
-/// kernel or BADRVAL, which indicates the kernel returned the wrong type of
-/// response to a system call.
-// ErrorCode is not an enum so that conversion from the kernel's return value (a
-// `usize` in a register) is free.
+/// An error code returned by the kernel.
// TODO: derive(Debug) is currently only enabled for test builds, which is
// necessary so it can be used in assert_eq!. We should develop a lighter-weight
// Debug implementation and see if it is small enough to enable on non-Debug
// builds.
#[cfg_attr(test, derive(Debug))]
#[derive(Clone, Copy, PartialEq, Eq)]
-pub struct ErrorCode(usize);
+#[repr(u16)] // To facilitate use with transmute() in CommandReturn
+#[rustfmt::skip]
+pub enum ErrorCode {
+ Fail = 1,
+ Busy = 2,
+ Already = 3,
+ Off = 4,
+ Reserve = 5,
+ Invalid = 6,
+ Size = 7,
+ Cancel = 8,
+ NoMem = 9,
+ NoSupport = 10,
+ NoDevice = 11,
+ Uninstalled = 12,
+ NoAck = 13,
-impl From<usize> for ErrorCode {
- fn from(value: usize) -> ErrorCode {
- ErrorCode(value)
- }
+ // Error codes reserved for future use. We have to include these for future
+ // compatibility -- this allows process binaries compiled with this version
+ // of libtock-rs to run on future kernel versions that may return a larger
+ // variety of error codes.
+ N00014 = 14, N00015 = 15,
+ N00016 = 16, N00017 = 17, N00018 = 18, N00019 = 19, N00020 = 20,
+ N00021 = 21, N00022 = 22, N00023 = 23, N00024 = 24, N00025 = 25,
+ N00026 = 26, N00027 = 27, N00028 = 28, N00029 = 29, N00030 = 30,
+ N00031 = 31, N00032 = 32, N00033 = 33, N00034 = 34, N00035 = 35,
+ N00036 = 36, N00037 = 37, N00038 = 38, N00039 = 39, N00040 = 40,
+ N00041 = 41, N00042 = 42, N00043 = 43, N00044 = 44, N00045 = 45,
+ N00046 = 46, N00047 = 47, N00048 = 48, N00049 = 49, N00050 = 50,
+ N00051 = 51, N00052 = 52, N00053 = 53, N00054 = 54, N00055 = 55,
+ N00056 = 56, N00057 = 57, N00058 = 58, N00059 = 59, N00060 = 60,
+ N00061 = 61, N00062 = 62, N00063 = 63, N00064 = 64, N00065 = 65,
+ N00066 = 66, N00067 = 67, N00068 = 68, N00069 = 69, N00070 = 70,
+ N00071 = 71, N00072 = 72, N00073 = 73, N00074 = 74, N00075 = 75,
+ N00076 = 76, N00077 = 77, N00078 = 78, N00079 = 79, N00080 = 80,
+ N00081 = 81, N00082 = 82, N00083 = 83, N00084 = 84, N00085 = 85,
+ N00086 = 86, N00087 = 87, N00088 = 88, N00089 = 89, N00090 = 90,
+ N00091 = 91, N00092 = 92, N00093 = 93, N00094 = 94, N00095 = 95,
+ N00096 = 96, N00097 = 97, N00098 = 98, N00099 = 99, N00100 = 100,
+ N00101 = 101, N00102 = 102, N00103 = 103, N00104 = 104, N00105 = 105,
+ N00106 = 106, N00107 = 107, N00108 = 108, N00109 = 109, N00110 = 110,
+ N00111 = 111, N00112 = 112, N00113 = 113, N00114 = 114, N00115 = 115,
+ N00116 = 116, N00117 = 117, N00118 = 118, N00119 = 119, N00120 = 120,
+ N00121 = 121, N00122 = 122, N00123 = 123, N00124 = 124, N00125 = 125,
+ N00126 = 126, N00127 = 127, N00128 = 128, N00129 = 129, N00130 = 130,
+ N00131 = 131, N00132 = 132, N00133 = 133, N00134 = 134, N00135 = 135,
+ N00136 = 136, N00137 = 137, N00138 = 138, N00139 = 139, N00140 = 140,
+ N00141 = 141, N00142 = 142, N00143 = 143, N00144 = 144, N00145 = 145,
+ N00146 = 146, N00147 = 147, N00148 = 148, N00149 = 149, N00150 = 150,
+ N00151 = 151, N00152 = 152, N00153 = 153, N00154 = 154, N00155 = 155,
+ N00156 = 156, N00157 = 157, N00158 = 158, N00159 = 159, N00160 = 160,
+ N00161 = 161, N00162 = 162, N00163 = 163, N00164 = 164, N00165 = 165,
+ N00166 = 166, N00167 = 167, N00168 = 168, N00169 = 169, N00170 = 170,
+ N00171 = 171, N00172 = 172, N00173 = 173, N00174 = 174, N00175 = 175,
+ N00176 = 176, N00177 = 177, N00178 = 178, N00179 = 179, N00180 = 180,
+ N00181 = 181, N00182 = 182, N00183 = 183, N00184 = 184, N00185 = 185,
+ N00186 = 186, N00187 = 187, N00188 = 188, N00189 = 189, N00190 = 190,
+ N00191 = 191, N00192 = 192, N00193 = 193, N00194 = 194, N00195 = 195,
+ N00196 = 196, N00197 = 197, N00198 = 198, N00199 = 199, N00200 = 200,
+ N00201 = 201, N00202 = 202, N00203 = 203, N00204 = 204, N00205 = 205,
+ N00206 = 206, N00207 = 207, N00208 = 208, N00209 = 209, N00210 = 210,
+ N00211 = 211, N00212 = 212, N00213 = 213, N00214 = 214, N00215 = 215,
+ N00216 = 216, N00217 = 217, N00218 = 218, N00219 = 219, N00220 = 220,
+ N00221 = 221, N00222 = 222, N00223 = 223, N00224 = 224, N00225 = 225,
+ N00226 = 226, N00227 = 227, N00228 = 228, N00229 = 229, N00230 = 230,
+ N00231 = 231, N00232 = 232, N00233 = 233, N00234 = 234, N00235 = 235,
+ N00236 = 236, N00237 = 237, N00238 = 238, N00239 = 239, N00240 = 240,
+ N00241 = 241, N00242 = 242, N00243 = 243, N00244 = 244, N00245 = 245,
+ N00246 = 246, N00247 = 247, N00248 = 248, N00249 = 249, N00250 = 250,
+ N00251 = 251, N00252 = 252, N00253 = 253, N00254 = 254, N00255 = 255,
+ N00256 = 256, N00257 = 257, N00258 = 258, N00259 = 259, N00260 = 260,
+ N00261 = 261, N00262 = 262, N00263 = 263, N00264 = 264, N00265 = 265,
+ N00266 = 266, N00267 = 267, N00268 = 268, N00269 = 269, N00270 = 270,
+ N00271 = 271, N00272 = 272, N00273 = 273, N00274 = 274, N00275 = 275,
+ N00276 = 276, N00277 = 277, N00278 = 278, N00279 = 279, N00280 = 280,
+ N00281 = 281, N00282 = 282, N00283 = 283, N00284 = 284, N00285 = 285,
+ N00286 = 286, N00287 = 287, N00288 = 288, N00289 = 289, N00290 = 290,
+ N00291 = 291, N00292 = 292, N00293 = 293, N00294 = 294, N00295 = 295,
+ N00296 = 296, N00297 = 297, N00298 = 298, N00299 = 299, N00300 = 300,
+ N00301 = 301, N00302 = 302, N00303 = 303, N00304 = 304, N00305 = 305,
+ N00306 = 306, N00307 = 307, N00308 = 308, N00309 = 309, N00310 = 310,
+ N00311 = 311, N00312 = 312, N00313 = 313, N00314 = 314, N00315 = 315,
+ N00316 = 316, N00317 = 317, N00318 = 318, N00319 = 319, N00320 = 320,
+ N00321 = 321, N00322 = 322, N00323 = 323, N00324 = 324, N00325 = 325,
+ N00326 = 326, N00327 = 327, N00328 = 328, N00329 = 329, N00330 = 330,
+ N00331 = 331, N00332 = 332, N00333 = 333, N00334 = 334, N00335 = 335,
+ N00336 = 336, N00337 = 337, N00338 = 338, N00339 = 339, N00340 = 340,
+ N00341 = 341, N00342 = 342, N00343 = 343, N00344 = 344, N00345 = 345,
+ N00346 = 346, N00347 = 347, N00348 = 348, N00349 = 349, N00350 = 350,
+ N00351 = 351, N00352 = 352, N00353 = 353, N00354 = 354, N00355 = 355,
+ N00356 = 356, N00357 = 357, N00358 = 358, N00359 = 359, N00360 = 360,
+ N00361 = 361, N00362 = 362, N00363 = 363, N00364 = 364, N00365 = 365,
+ N00366 = 366, N00367 = 367, N00368 = 368, N00369 = 369, N00370 = 370,
+ N00371 = 371, N00372 = 372, N00373 = 373, N00374 = 374, N00375 = 375,
+ N00376 = 376, N00377 = 377, N00378 = 378, N00379 = 379, N00380 = 380,
+ N00381 = 381, N00382 = 382, N00383 = 383, N00384 = 384, N00385 = 385,
+ N00386 = 386, N00387 = 387, N00388 = 388, N00389 = 389, N00390 = 390,
+ N00391 = 391, N00392 = 392, N00393 = 393, N00394 = 394, N00395 = 395,
+ N00396 = 396, N00397 = 397, N00398 = 398, N00399 = 399, N00400 = 400,
+ N00401 = 401, N00402 = 402, N00403 = 403, N00404 = 404, N00405 = 405,
+ N00406 = 406, N00407 = 407, N00408 = 408, N00409 = 409, N00410 = 410,
+ N00411 = 411, N00412 = 412, N00413 = 413, N00414 = 414, N00415 = 415,
+ N00416 = 416, N00417 = 417, N00418 = 418, N00419 = 419, N00420 = 420,
+ N00421 = 421, N00422 = 422, N00423 = 423, N00424 = 424, N00425 = 425,
+ N00426 = 426, N00427 = 427, N00428 = 428, N00429 = 429, N00430 = 430,
+ N00431 = 431, N00432 = 432, N00433 = 433, N00434 = 434, N00435 = 435,
+ N00436 = 436, N00437 = 437, N00438 = 438, N00439 = 439, N00440 = 440,
+ N00441 = 441, N00442 = 442, N00443 = 443, N00444 = 444, N00445 = 445,
+ N00446 = 446, N00447 = 447, N00448 = 448, N00449 = 449, N00450 = 450,
+ N00451 = 451, N00452 = 452, N00453 = 453, N00454 = 454, N00455 = 455,
+ N00456 = 456, N00457 = 457, N00458 = 458, N00459 = 459, N00460 = 460,
+ N00461 = 461, N00462 = 462, N00463 = 463, N00464 = 464, N00465 = 465,
+ N00466 = 466, N00467 = 467, N00468 = 468, N00469 = 469, N00470 = 470,
+ N00471 = 471, N00472 = 472, N00473 = 473, N00474 = 474, N00475 = 475,
+ N00476 = 476, N00477 = 477, N00478 = 478, N00479 = 479, N00480 = 480,
+ N00481 = 481, N00482 = 482, N00483 = 483, N00484 = 484, N00485 = 485,
+ N00486 = 486, N00487 = 487, N00488 = 488, N00489 = 489, N00490 = 490,
+ N00491 = 491, N00492 = 492, N00493 = 493, N00494 = 494, N00495 = 495,
+ N00496 = 496, N00497 = 497, N00498 = 498, N00499 = 499, N00500 = 500,
+ N00501 = 501, N00502 = 502, N00503 = 503, N00504 = 504, N00505 = 505,
+ N00506 = 506, N00507 = 507, N00508 = 508, N00509 = 509, N00510 = 510,
+ N00511 = 511, N00512 = 512, N00513 = 513, N00514 = 514, N00515 = 515,
+ N00516 = 516, N00517 = 517, N00518 = 518, N00519 = 519, N00520 = 520,
+ N00521 = 521, N00522 = 522, N00523 = 523, N00524 = 524, N00525 = 525,
+ N00526 = 526, N00527 = 527, N00528 = 528, N00529 = 529, N00530 = 530,
+ N00531 = 531, N00532 = 532, N00533 = 533, N00534 = 534, N00535 = 535,
+ N00536 = 536, N00537 = 537, N00538 = 538, N00539 = 539, N00540 = 540,
+ N00541 = 541, N00542 = 542, N00543 = 543, N00544 = 544, N00545 = 545,
+ N00546 = 546, N00547 = 547, N00548 = 548, N00549 = 549, N00550 = 550,
+ N00551 = 551, N00552 = 552, N00553 = 553, N00554 = 554, N00555 = 555,
+ N00556 = 556, N00557 = 557, N00558 = 558, N00559 = 559, N00560 = 560,
+ N00561 = 561, N00562 = 562, N00563 = 563, N00564 = 564, N00565 = 565,
+ N00566 = 566, N00567 = 567, N00568 = 568, N00569 = 569, N00570 = 570,
+ N00571 = 571, N00572 = 572, N00573 = 573, N00574 = 574, N00575 = 575,
+ N00576 = 576, N00577 = 577, N00578 = 578, N00579 = 579, N00580 = 580,
+ N00581 = 581, N00582 = 582, N00583 = 583, N00584 = 584, N00585 = 585,
+ N00586 = 586, N00587 = 587, N00588 = 588, N00589 = 589, N00590 = 590,
+ N00591 = 591, N00592 = 592, N00593 = 593, N00594 = 594, N00595 = 595,
+ N00596 = 596, N00597 = 597, N00598 = 598, N00599 = 599, N00600 = 600,
+ N00601 = 601, N00602 = 602, N00603 = 603, N00604 = 604, N00605 = 605,
+ N00606 = 606, N00607 = 607, N00608 = 608, N00609 = 609, N00610 = 610,
+ N00611 = 611, N00612 = 612, N00613 = 613, N00614 = 614, N00615 = 615,
+ N00616 = 616, N00617 = 617, N00618 = 618, N00619 = 619, N00620 = 620,
+ N00621 = 621, N00622 = 622, N00623 = 623, N00624 = 624, N00625 = 625,
+ N00626 = 626, N00627 = 627, N00628 = 628, N00629 = 629, N00630 = 630,
+ N00631 = 631, N00632 = 632, N00633 = 633, N00634 = 634, N00635 = 635,
+ N00636 = 636, N00637 = 637, N00638 = 638, N00639 = 639, N00640 = 640,
+ N00641 = 641, N00642 = 642, N00643 = 643, N00644 = 644, N00645 = 645,
+ N00646 = 646, N00647 = 647, N00648 = 648, N00649 = 649, N00650 = 650,
+ N00651 = 651, N00652 = 652, N00653 = 653, N00654 = 654, N00655 = 655,
+ N00656 = 656, N00657 = 657, N00658 = 658, N00659 = 659, N00660 = 660,
+ N00661 = 661, N00662 = 662, N00663 = 663, N00664 = 664, N00665 = 665,
+ N00666 = 666, N00667 = 667, N00668 = 668, N00669 = 669, N00670 = 670,
+ N00671 = 671, N00672 = 672, N00673 = 673, N00674 = 674, N00675 = 675,
+ N00676 = 676, N00677 = 677, N00678 = 678, N00679 = 679, N00680 = 680,
+ N00681 = 681, N00682 = 682, N00683 = 683, N00684 = 684, N00685 = 685,
+ N00686 = 686, N00687 = 687, N00688 = 688, N00689 = 689, N00690 = 690,
+ N00691 = 691, N00692 = 692, N00693 = 693, N00694 = 694, N00695 = 695,
+ N00696 = 696, N00697 = 697, N00698 = 698, N00699 = 699, N00700 = 700,
+ N00701 = 701, N00702 = 702, N00703 = 703, N00704 = 704, N00705 = 705,
+ N00706 = 706, N00707 = 707, N00708 = 708, N00709 = 709, N00710 = 710,
+ N00711 = 711, N00712 = 712, N00713 = 713, N00714 = 714, N00715 = 715,
+ N00716 = 716, N00717 = 717, N00718 = 718, N00719 = 719, N00720 = 720,
+ N00721 = 721, N00722 = 722, N00723 = 723, N00724 = 724, N00725 = 725,
+ N00726 = 726, N00727 = 727, N00728 = 728, N00729 = 729, N00730 = 730,
+ N00731 = 731, N00732 = 732, N00733 = 733, N00734 = 734, N00735 = 735,
+ N00736 = 736, N00737 = 737, N00738 = 738, N00739 = 739, N00740 = 740,
+ N00741 = 741, N00742 = 742, N00743 = 743, N00744 = 744, N00745 = 745,
+ N00746 = 746, N00747 = 747, N00748 = 748, N00749 = 749, N00750 = 750,
+ N00751 = 751, N00752 = 752, N00753 = 753, N00754 = 754, N00755 = 755,
+ N00756 = 756, N00757 = 757, N00758 = 758, N00759 = 759, N00760 = 760,
+ N00761 = 761, N00762 = 762, N00763 = 763, N00764 = 764, N00765 = 765,
+ N00766 = 766, N00767 = 767, N00768 = 768, N00769 = 769, N00770 = 770,
+ N00771 = 771, N00772 = 772, N00773 = 773, N00774 = 774, N00775 = 775,
+ N00776 = 776, N00777 = 777, N00778 = 778, N00779 = 779, N00780 = 780,
+ N00781 = 781, N00782 = 782, N00783 = 783, N00784 = 784, N00785 = 785,
+ N00786 = 786, N00787 = 787, N00788 = 788, N00789 = 789, N00790 = 790,
+ N00791 = 791, N00792 = 792, N00793 = 793, N00794 = 794, N00795 = 795,
+ N00796 = 796, N00797 = 797, N00798 = 798, N00799 = 799, N00800 = 800,
+ N00801 = 801, N00802 = 802, N00803 = 803, N00804 = 804, N00805 = 805,
+ N00806 = 806, N00807 = 807, N00808 = 808, N00809 = 809, N00810 = 810,
+ N00811 = 811, N00812 = 812, N00813 = 813, N00814 = 814, N00815 = 815,
+ N00816 = 816, N00817 = 817, N00818 = 818, N00819 = 819, N00820 = 820,
+ N00821 = 821, N00822 = 822, N00823 = 823, N00824 = 824, N00825 = 825,
+ N00826 = 826, N00827 = 827, N00828 = 828, N00829 = 829, N00830 = 830,
+ N00831 = 831, N00832 = 832, N00833 = 833, N00834 = 834, N00835 = 835,
+ N00836 = 836, N00837 = 837, N00838 = 838, N00839 = 839, N00840 = 840,
+ N00841 = 841, N00842 = 842, N00843 = 843, N00844 = 844, N00845 = 845,
+ N00846 = 846, N00847 = 847, N00848 = 848, N00849 = 849, N00850 = 850,
+ N00851 = 851, N00852 = 852, N00853 = 853, N00854 = 854, N00855 = 855,
+ N00856 = 856, N00857 = 857, N00858 = 858, N00859 = 859, N00860 = 860,
+ N00861 = 861, N00862 = 862, N00863 = 863, N00864 = 864, N00865 = 865,
+ N00866 = 866, N00867 = 867, N00868 = 868, N00869 = 869, N00870 = 870,
+ N00871 = 871, N00872 = 872, N00873 = 873, N00874 = 874, N00875 = 875,
+ N00876 = 876, N00877 = 877, N00878 = 878, N00879 = 879, N00880 = 880,
+ N00881 = 881, N00882 = 882, N00883 = 883, N00884 = 884, N00885 = 885,
+ N00886 = 886, N00887 = 887, N00888 = 888, N00889 = 889, N00890 = 890,
+ N00891 = 891, N00892 = 892, N00893 = 893, N00894 = 894, N00895 = 895,
+ N00896 = 896, N00897 = 897, N00898 = 898, N00899 = 899, N00900 = 900,
+ N00901 = 901, N00902 = 902, N00903 = 903, N00904 = 904, N00905 = 905,
+ N00906 = 906, N00907 = 907, N00908 = 908, N00909 = 909, N00910 = 910,
+ N00911 = 911, N00912 = 912, N00913 = 913, N00914 = 914, N00915 = 915,
+ N00916 = 916, N00917 = 917, N00918 = 918, N00919 = 919, N00920 = 920,
+ N00921 = 921, N00922 = 922, N00923 = 923, N00924 = 924, N00925 = 925,
+ N00926 = 926, N00927 = 927, N00928 = 928, N00929 = 929, N00930 = 930,
+ N00931 = 931, N00932 = 932, N00933 = 933, N00934 = 934, N00935 = 935,
+ N00936 = 936, N00937 = 937, N00938 = 938, N00939 = 939, N00940 = 940,
+ N00941 = 941, N00942 = 942, N00943 = 943, N00944 = 944, N00945 = 945,
+ N00946 = 946, N00947 = 947, N00948 = 948, N00949 = 949, N00950 = 950,
+ N00951 = 951, N00952 = 952, N00953 = 953, N00954 = 954, N00955 = 955,
+ N00956 = 956, N00957 = 957, N00958 = 958, N00959 = 959, N00960 = 960,
+ N00961 = 961, N00962 = 962, N00963 = 963, N00964 = 964, N00965 = 965,
+ N00966 = 966, N00967 = 967, N00968 = 968, N00969 = 969, N00970 = 970,
+ N00971 = 971, N00972 = 972, N00973 = 973, N00974 = 974, N00975 = 975,
+ N00976 = 976, N00977 = 977, N00978 = 978, N00979 = 979, N00980 = 980,
+ N00981 = 981, N00982 = 982, N00983 = 983, N00984 = 984, N00985 = 985,
+ N00986 = 986, N00987 = 987, N00988 = 988, N00989 = 989, N00990 = 990,
+ N00991 = 991, N00992 = 992, N00993 = 993, N00994 = 994, N00995 = 995,
+ N00996 = 996, N00997 = 997, N00998 = 998, N00999 = 999, N01000 = 1000,
+ N01001 = 1001, N01002 = 1002, N01003 = 1003, N01004 = 1004, N01005 = 1005,
+ N01006 = 1006, N01007 = 1007, N01008 = 1008, N01009 = 1009, N01010 = 1010,
+ N01011 = 1011, N01012 = 1012, N01013 = 1013, N01014 = 1014, N01015 = 1015,
+ N01016 = 1016, N01017 = 1017, N01018 = 1018, N01019 = 1019, N01020 = 1020,
+ N01021 = 1021, N01022 = 1022, N01023 = 1023,
}
-
-impl From<ErrorCode> for usize {
- fn from(error_code: ErrorCode) -> usize {
- error_code.0
- }
-}
-
-pub const FAIL: ErrorCode = ErrorCode(1);
-pub const BUSY: ErrorCode = ErrorCode(2);
-pub const ALREADY: ErrorCode = ErrorCode(3);
-pub const OFF: ErrorCode = ErrorCode(4);
-pub const RESERVE: ErrorCode = ErrorCode(5);
-pub const INVALID: ErrorCode = ErrorCode(6);
-pub const SIZE: ErrorCode = ErrorCode(7);
-pub const CANCEL: ErrorCode = ErrorCode(8);
-pub const NOMEM: ErrorCode = ErrorCode(9);
-pub const NOSUPPORT: ErrorCode = ErrorCode(10);
-pub const NODEVICE: ErrorCode = ErrorCode(11);
-pub const UNINSTALLED: ErrorCode = ErrorCode(12);
-pub const NOACK: ErrorCode = ErrorCode(13);
-pub const BADRVAL: ErrorCode = ErrorCode(1024);
diff --git a/core/platform/src/lib.rs b/core/platform/src/lib.rs
index 45021ca..d57644b 100644
--- a/core/platform/src/lib.rs
+++ b/core/platform/src/lib.rs
@@ -2,7 +2,7 @@
mod async_traits;
mod command_return;
-pub mod error_code;
+mod error_code;
mod raw_syscalls;
pub mod return_variant;
mod syscalls;
diff --git a/core/runtime/asm/asm_riscv32.S b/core/runtime/asm/asm_riscv32.S
new file mode 100644
index 0000000..db1036e
--- /dev/null
+++ b/core/runtime/asm/asm_riscv32.S
@@ -0,0 +1,86 @@
+/* rt_header is defined by the general linker script (libtock_layout.ld). It has
+ * the following layout:
+ *
+ * Field | Offset
+ * ------------------------------------
+ * Address of the start symbol | 0
+ * Initial process break | 4
+ * Top of the stack | 8
+ * Size of .data | 12
+ * Start of .data in flash | 16
+ * Start of .data in ram | 20
+ * Size of .bss | 24
+ * Start of .bss in ram | 28
+ */
+
+/* start is the entry point -- the first code executed by the kernel. The kernel
+ * passes arguments through 4 registers:
+ *
+ * a0 Pointer to beginning of the process binary's code. The linker script
+ * locates rt_header at this address.
+ *
+ * a1 Address of the beginning of the process's usable memory region.
+ * a2 Size of the process' allocated memory region (including grant region)
+ * a3 Process break provided by the kernel.
+ *
+ * We currently only use the value in a0. It is copied into a5 early on because
+ * a0-a4 are needed to invoke system calls.
+ */
+.section .start, "ax"
+.globl start
+start:
+ /* First, verify the process binary was loaded at the correct address. The
+ * check is performed by comparing the program counter at the start to the
+ * address of `start`, which is stored in rt_header. */
+ auipc s0, 0 /* s0 = pc */
+ mv a5, a0 /* Save rt_header so syscalls don't overwrite it */
+ lw s1, 0(a5) /* s1 = rt_header.start */
+ beq s0, s1, .Lset_brk /* Skip error handling code if pc is correct */
+ /* If the beq on the previous line did not jump, then the binary is not at
+ * the correct location. Report the error via LowLevelDebug then exit. */
+ li a0, 8 /* LowLevelDebug driver number */
+ li a1, 1 /* Command: Print alert code */
+ li a2, 2 /* Alert code 2 (incorrect location) */
+ li a4, 2 /* `command` class */
+ ecall
+ li a0, 0 /* exit-terminate */
+ /* TODO: Set a completion code, once completion codes are decided */
+ li a4, 6 /* `exit` class */
+ ecall
+
+.Lset_brk:
+ /* memop(): set brk to rt_header's initial break value */
+ li a0, 0 /* operation: set break */
+ lw a1, 4(a5) /* rt_header's initial process break */
+ li a4, 5 /* `memop` class */
+ ecall
+
+ /* Set the stack pointer */
+ lw sp, 8(a5) /* sp = rt_header._stack_top */
+
+ /* Copy .data into place. */
+ lw a0, 12(a5) /* remaining = rt_header.data_size */
+ beqz a0, .Lzero_bss /* Jump to zero_bss if remaining is zero */
+ lw a1, 16(a5) /* src = rt_header.data_flash_start */
+ lw a2, 20(a5) /* dest = rt_header.data_ram_start */
+.Ldata_loop_body:
+ lw a3, 0(a1) /* a3 = *src */
+ sw a3, 0(a2) /* *dest = a3 */
+ addi a0, a0, -4 /* remaining -= 4 */
+ addi a1, a1, 4 /* src += 4 */
+ addi a2, a2, 4 /* dest += 4 */
+ bnez a0, .Ldata_loop_body /* Iterate again if remaining != 0 */
+
+.Lzero_bss:
+ lw a0, 24(a5) /* remaining = rt_header.bss_size */
+ beqz a0, .Lcall_rust_start /* Jump to call_Main if remaining is zero */
+ lw a1, 28(a5) /* dest = rt_header.bss_start */
+.Lbss_loop_body:
+ sb zero, 0(a1) /* *dest = zero */
+ addi a0, a0, -1 /* remaining -= 1 */
+ addi a1, a1, 1 /* dest += 1 */
+ bnez a0, .Lbss_loop_body /* Iterate again if remaining != 0 */
+
+.Lcall_rust_start:
+ /* Note: rust_start must be a diverging function (i.e. return `!`) */
+ jal rust_start
diff --git a/core/runtime/asm/start_prototype.rs b/core/runtime/asm/start_prototype.rs
new file mode 100644
index 0000000..26c036d
--- /dev/null
+++ b/core/runtime/asm/start_prototype.rs
@@ -0,0 +1,94 @@
+// This file is not compiled or tested! It is kept in this repository in case
+// future libtock_runtime developers want to use it. To use this file, copy it
+// into libtock_runtime's src/ directory and add mod start_prototype; to
+// libtock_runtime's lib.rs.
+
+// The `start` symbol must be written purely in assembly, because it has an ABI
+// that the Rust compiler doesn't know (e.g. it does not expect the stack to be
+// set up). One way to write a correct `start` implementation is to write it in
+// Rust using the C ABI, compile that implementation, then tweak the assembly by
+// hand. This is a Rust version of `start` for developers who are working on
+// `start`.
+
+#[repr(C)]
+struct RtHeader {
+ start: usize,
+ initial_break: usize,
+ stack_top: usize,
+ data_size: usize,
+ data_flash_start: *const u32,
+ data_ram_start: *mut u32,
+ bss_size: usize,
+ bss_start: *mut u8,
+}
+
+#[link_section = ".start"]
+#[no_mangle]
+extern fn start_prototype(
+ rt_header: &RtHeader,
+ _memory_start: usize,
+ _memory_len: usize,
+ _app_break: usize,
+) -> ! {
+ use crate::TockSyscalls;
+ use libtock_platform::{OneArgMemop, RawSyscalls, YieldType};
+
+ let pc: usize;
+ #[cfg(target_arch = "riscv32")]
+ unsafe {
+ asm!("auipc {}, 0", lateout(reg) pc, options(nomem, nostack, preserves_flags));
+ }
+ if pc != rt_header.start {
+ // Binary is in an incorrect location: report an error via
+ // LowLevelDebug.
+ unsafe {
+ TockSyscalls::four_arg_syscall(8, 1, 2, 0, 2);
+ }
+ // TODO: Replace with an Exit call when exit is implemented.
+ loop {
+ TockSyscalls::raw_yield(YieldType::Wait);
+ }
+ }
+
+ // Set the app break.
+ // TODO: Replace with Syscalls::memop_brk() when that is implemented.
+ TockSyscalls::one_arg_memop(OneArgMemop::Brk, rt_header.initial_break);
+
+ // Set the stack pointer.
+ #[cfg(target_arch = "riscv32")]
+ unsafe {
+ asm!("mv sp, {}", in(reg) rt_header.stack_top, options(nomem, preserves_flags));
+ }
+
+ // Copy .data into place. Uses a manual loop rather than
+ // `core::ptr::copy*()` to avoid relying on `memcopy` or `memmove`.
+ let mut remaining = rt_header.data_size;
+ let mut src = rt_header.data_flash_start;
+ let mut dest = rt_header.data_ram_start;
+ while remaining > 0 {
+ unsafe {
+ core::ptr::write(dest, *(src));
+ src = src.add(1);
+ dest = dest.add(1);
+ }
+ remaining -= 4;
+ }
+
+ // Zero .bss. Uses a manual loop and volatile write to avoid relying on
+ // `memset`.
+ let mut remaining = rt_header.bss_size;
+ let mut dest = rt_header.bss_start;
+ while remaining > 0 {
+ unsafe {
+ core::ptr::write_volatile(dest, 0);
+ dest = dest.add(1);
+ }
+ remaining -= 1;
+ }
+
+ extern {
+ fn rust_start() -> !;
+ }
+
+ unsafe { rust_start(); }
+}
diff --git a/core/runtime/build.rs b/core/runtime/build.rs
index d0281b5..347d82c 100644
--- a/core/runtime/build.rs
+++ b/core/runtime/build.rs
@@ -1,6 +1,8 @@
use std::fs::copy;
use std::path::PathBuf;
+mod extern_asm;
+
// auto_layout() identifies the correct linker scripts to use based on the
// LIBTOCK_PLATFORM environment variable, and copies the linker scripts into
// OUT_DIR. The cargo invocation must pass -C link-arg=-Tlayout.ld to rustc
@@ -8,7 +10,7 @@
#[cfg(not(feature = "no_auto_layout"))]
fn auto_layout(out_dir: &str) {
const PLATFORM_CFG_VAR: &str = "LIBTOCK_PLATFORM";
- const LAYOUT_GENERIC_FILENAME: &str = "layout_generic.ld";
+ const LAYOUT_GENERIC_FILENAME: &str = "libtock_layout.ld";
// Note: we need to print these rerun-if commands before using the variable
// or file, so that if the build script fails cargo knows when to re-run it.
@@ -49,7 +51,9 @@
#[cfg(not(feature = "no_auto_layout"))]
auto_layout(out_dir);
- // This link search path is used by both auto_layout() and extern_asm().
- // TODO: Add external assembly and extern_asm().
+ extern_asm::build_and_link(out_dir);
+
+ // This link search path is used by both auto_layout() and
+ // extern_asm::build_and_link().
println!("cargo:rustc-link-search={}", out_dir);
}
diff --git a/core/runtime/extern_asm.rs b/core/runtime/extern_asm.rs
new file mode 100644
index 0000000..d0488f8
--- /dev/null
+++ b/core/runtime/extern_asm.rs
@@ -0,0 +1,140 @@
+//! Build script module for compiling the external assembly (used for the entry
+//! point) and linking it into the process binary. Requires out_dir to be added
+//! to rustc's link search path.
+
+pub(crate) fn build_and_link(out_dir: &str) {
+ use std::env::var;
+ let arch = var("CARGO_CFG_TARGET_ARCH").expect("Unable to read CARGO_CFG_TARGET_ARCH");
+
+ // Identify the toolchain configurations to try for the target architecture.
+ // We support trying multiple toolchains because not all toolchains are
+ // available on every OS that we want to support development on.
+ let build_configs = match arch.as_str() {
+ "riscv32" => &[
+ // First try riscv64-unknown-elf, as it is the toolchain used by
+ // libtock-c and the toolchain used in the CI environment.
+ AsmBuildConfig {
+ triple: "riscv64-unknown-elf",
+ as_extra_args: &["-march=rv32imc"],
+ strip: true,
+ },
+ // Second try riscv32-unknown-elf. This is the best match for Tock's
+ // risc-v targets, but is not as widely available (and has not been
+ // tested with libtock-rs yet).
+ AsmBuildConfig {
+ triple: "riscv32-unknown-elf",
+ as_extra_args: &[],
+ strip: false, // Untested, may need to change.
+ },
+ // Last try riscv64-linux-gnu, as it is the only option on Debian 10
+ AsmBuildConfig {
+ triple: "riscv64-linux-gnu",
+ as_extra_args: &["-march=rv32imc"],
+ strip: true,
+ },
+ ],
+ unknown_arch => {
+ panic!("Unsupported architecture {}", unknown_arch);
+ }
+ };
+
+ // Loop through toolchain configs until one works.
+ for &build_config in build_configs {
+ if try_build(&arch, build_config, out_dir).is_ok() {
+ return;
+ }
+ }
+}
+
+#[derive(Clone, Copy)]
+struct AsmBuildConfig {
+ // Triple name, which is prepended to the command names.
+ triple: &'static str,
+
+ // Extra arguments to pass to the assembler.
+ as_extra_args: &'static [&'static str],
+
+ // Do we need to strip the object file before packing it into the library
+ // archive? This should be set to true on platforms where the assembler adds
+ // local symbols to the object file.
+ strip: bool,
+}
+
+// Indicates the toolchain in the build config is unavailable.
+struct ToolchainUnavailable;
+
+fn try_build(
+ arch: &str,
+ build_config: AsmBuildConfig,
+ out_dir: &str,
+) -> Result<(), ToolchainUnavailable> {
+ use std::path::PathBuf;
+ use std::process::Command;
+
+ // Invoke the assembler to produce an object file.
+ let asm_source = &format!("asm/asm_{}.S", arch);
+ let obj_file_path = [out_dir, "libtock_rt_asm.o"].iter().collect::<PathBuf>();
+ let obj_file = obj_file_path.to_str().expect("Non-Unicode obj_file_path");
+ let as_result = Command::new(format!("{}-as", build_config.triple))
+ .args(build_config.as_extra_args)
+ .args(&[asm_source, "-o", obj_file])
+ .status();
+
+ match as_result {
+ Err(error) => {
+ if error.kind() == std::io::ErrorKind::NotFound {
+ // This `as` command does not exist. Return an error so
+ // build_an_link can try another config (if one is available).
+ return Err(ToolchainUnavailable);
+ } else {
+ panic!("Error invoking assembler: {}", error);
+ }
+ }
+ Ok(status) => {
+ assert!(status.success(), "Assembler returned an error");
+ }
+ }
+
+ // At this point, we know this toolchain is installed. We will fail if later
+ // commands are uninstalled rather than trying a different build config.
+
+ println!("cargo:rerun-if-changed={}", asm_source);
+
+ // Run `strip` if necessary.
+ if build_config.strip {
+ let strip_cmd = format!("{}-strip", build_config.triple);
+ let status = Command::new(&strip_cmd)
+ .args(&["-K", "start", "-K", "rust_start", obj_file])
+ .status()
+ .unwrap_or_else(|_| panic!("Failed to invoke {}", strip_cmd));
+ assert!(status.success(), "{} returned an error", strip_cmd);
+ }
+
+ // Remove the archive file in case there is something unexpected in it. This
+ // prevents issues from persisting across invocations of this script.
+ const ARCHIVE_NAME: &str = "tock_rt_asm";
+ let archive_path: PathBuf = [out_dir, &format!("lib{}.a", ARCHIVE_NAME)]
+ .iter()
+ .collect();
+ if let Err(error) = std::fs::remove_file(&archive_path) {
+ if error.kind() != std::io::ErrorKind::NotFound {
+ panic!("Unable to remove archive file {}", archive_path.display());
+ }
+ }
+
+ // Create the library archive.
+ let ar_cmd = format!("{}-ar", build_config.triple);
+ let archive = archive_path.to_str().expect("Non-Unicode archive_path");
+ let status = std::process::Command::new(&ar_cmd)
+ // c == Do not complain if archive needs to be created.
+ // r == Insert or replace file in archive.
+ .args(&["cr", archive, obj_file])
+ .status()
+ .unwrap_or_else(|_| panic!("Failed to invoke {}", ar_cmd));
+ assert!(status.success(), "{} returned an error", ar_cmd);
+
+ // Tell rustc to link the binary against the library archive.
+ println!("cargo:rustc-link-lib=static={}", ARCHIVE_NAME);
+
+ Ok(())
+}
diff --git a/core/runtime/layout_generic.ld b/core/runtime/layout_generic.ld
deleted file mode 100644
index 0bbef87..0000000
--- a/core/runtime/layout_generic.ld
+++ /dev/null
@@ -1,171 +0,0 @@
-/* Userland Generic Layout
- *
- * Currently, due to incomplete ROPI-RWPI support in rustc (see
- * https://github.com/tock/libtock-rs/issues/28), this layout implements static
- * linking. An application init script must define the FLASH and SRAM address
- * ranges as well as MPU_MIN_ALIGN before including this layout file.
- *
- * Here is a an example application linker script to get started:
- * MEMORY {
- * /* FLASH memory region must start immediately *after* the Tock
- * * Binary Format headers, which means you need to offset the
- * * beginning of FLASH memory region relative to where the
- * * application is loaded.
- * FLASH (rx) : ORIGIN = 0x10030, LENGTH = 0x0FFD0
- * SRAM (RWX) : ORIGIN = 0x20000, LENGTH = 0x10000
- * }
- * MPU_MIN_ALIGN = 8K;
- * INCLUDE ../libtock-rs/layout.ld
- */
-
-ENTRY(_start)
-
-SECTIONS {
- /* Section for just the app crt0 header.
- * This must be first so that the app can find it.
- */
- .crt0_header :
- {
- _beginning = .; /* Start of the app in flash. */
- /**
- * Populate the header expected by `crt0`:
- *
- * struct hdr {
- * uint32_t got_sym_start;
- * uint32_t got_start;
- * uint32_t got_size;
- * uint32_t data_sym_start;
- * uint32_t data_start;
- * uint32_t data_size;
- * uint32_t bss_start;
- * uint32_t bss_size;
- * uint32_t reldata_start;
- * uint32_t stack_size;
- * };
- */
- /* Offset of GOT symbols in flash */
- LONG(LOADADDR(.got) - _beginning);
- /* Offset of GOT section in memory */
- LONG(_got);
- /* Size of GOT section */
- LONG(SIZEOF(.got));
- /* Offset of data symbols in flash */
- LONG(LOADADDR(.data) - _beginning);
- /* Offset of data section in memory */
- LONG(_data);
- /* Size of data section */
- LONG(SIZEOF(.data));
- /* Offset of BSS section in memory */
- LONG(_bss);
- /* Size of BSS section */
- LONG(SIZEOF(.bss));
- /* First address offset after program flash, where elf2tab places
- * .rel.data section */
- LONG(LOADADDR(.endflash) - _beginning);
- /* The size of the stack requested by this application */
- LONG(_stack_top_aligned - _sstack);
- /* Pad the header out to a multiple of 32 bytes so there is not a gap
- * between the header and subsequent .data section. It's unclear why,
- * but LLD is aligning sections to a multiple of 32 bytes. */
- . = ALIGN(32);
- } > FLASH =0xFF
-
- /* Text section, Code! */
- .text :
- {
- . = ALIGN(4);
- _text = .;
- KEEP (*(.start))
- *(.text*)
- *(.rodata*)
- KEEP (*(.syscalls))
- *(.ARM.extab*)
- . = ALIGN(4); /* Make sure we're word-aligned here */
- _etext = .;
- } > FLASH =0xFF
-
- /* Application stack */
- .stack (NOLOAD) :
- {
- /* elf2tab requires that the `_sram_origin` symbol be present to
- * mark the first address in the SRAM memory. Since ELF files do
- * not really need to specify this address as they only care about
- * loading into flash, we need to manually mark this address for
- * elf2tab. elf2tab will use it to add a fixed address header in the
- * TBF header if needed.
- */
- _sram_origin = .;
- _sstack = .;
- KEEP(*(.stack_buffer))
- _stack_top_unaligned = .;
- . = ALIGN(8);
- _stack_top_aligned = .;
- } > SRAM
-
- /* 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 : AT (_etext)
- {
- . = ALIGN(4); /* Make sure we're word-aligned here */
- _data = .;
- KEEP(*(.data*))
- *(.sdata*) /* RISC-V small-pointer data section */
- . = ALIGN(4); /* Make sure we're word-aligned at the end of flash */
- } > SRAM
-
- /* Global Offset Table */
- .got :
- {
- . = ALIGN(4); /* Make sure we're word-aligned here */
- _got = .;
- *(.got*)
- *(.got.plt*)
- . = ALIGN(4);
- } > SRAM
-
- /* BSS section, static uninitialized variables */
- .bss :
- {
- . = ALIGN(4); /* Make sure we're word-aligned here */
- _bss = .;
- KEEP(*(.bss* .sbss*))
- *(COMMON)
- . = ALIGN(4);
- } > SRAM
-
- /* End of flash. */
- .endflash :
- {
- } > 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 = .);
-
- /DISCARD/ :
- {
- *(.eh_frame)
- }
-}
-
-ASSERT((_stack_top_aligned - _stack_top_unaligned) == 0, "
-STACK_SIZE must be 8 byte multiple")
diff --git a/core/runtime/layouts/apollo3.ld b/core/runtime/layouts/apollo3.ld
index 8713c27..464cf98 100644
--- a/core/runtime/layouts/apollo3.ld
+++ b/core/runtime/layouts/apollo3.ld
@@ -1,11 +1,9 @@
/* Layout for the Apollo3 MCU, used by the examples in this repository. */
MEMORY {
- /* The application region is 64 bytes (0x40) */
- FLASH (rx) : ORIGIN = 0x00040040, LENGTH = 0x0005FFC0
- SRAM (rwx) : ORIGIN = 0x10002000, LENGTH = 0x2000
+ FLASH (X) : ORIGIN = 0x00040000, LENGTH = 0x00060000
+ RAM (W) : ORIGIN = 0x10002000, LENGTH = 0x2000
}
-MPU_MIN_ALIGN = 8K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/hail.ld b/core/runtime/layouts/hail.ld
index 179a883..db48142 100644
--- a/core/runtime/layouts/hail.ld
+++ b/core/runtime/layouts/hail.ld
@@ -1,11 +1,9 @@
/* Layout for the Hail board, used by the examples in this repository. */
MEMORY {
- /* The application region is 64 bytes (0x40) */
- FLASH (rx) : ORIGIN = 0x00030040, LENGTH = 0x0005FFC0
- SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 62K
+ FLASH (X) : ORIGIN = 0x00030000, LENGTH = 0x00060000
+ RAM (W) : ORIGIN = 0x20004000, LENGTH = 62K
}
-MPU_MIN_ALIGN = 8K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/hifive1.ld b/core/runtime/layouts/hifive1.ld
index 20294ce..78dc51b 100644
--- a/core/runtime/layouts/hifive1.ld
+++ b/core/runtime/layouts/hifive1.ld
@@ -1,18 +1,12 @@
/* Layout for the RISC-V 32 boards, used by the examples in this repository. */
MEMORY {
- /*
- * The TBF header can change in size so use 0x40 combined with
- * --protected-region-size with elf2tab to cover a header upto that
- * size.
- *
- * Note that the SRAM address may need to be changed depending on
+ /* Note that the SRAM address may need to be changed depending on
* the kernel binary, check for the actual address of APP_MEMORY!
*/
- FLASH (rx) : ORIGIN = 0x20040040, LENGTH = 32M
- SRAM (rwx) : ORIGIN = 0x80002400, LENGTH = 0x1C00
+ FLASH (X) : ORIGIN = 0x20040000, LENGTH = 32M
+ RAM (W) : ORIGIN = 0x80002400, LENGTH = 0x1C00
}
-MPU_MIN_ALIGN = 1K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/imxrt1050.ld b/core/runtime/layouts/imxrt1050.ld
index 3e7f904..1458870 100644
--- a/core/runtime/layouts/imxrt1050.ld
+++ b/core/runtime/layouts/imxrt1050.ld
@@ -1,11 +1,9 @@
/* Layout for the iMX.RT1050 board, used by the examples in this repository. */
MEMORY {
- /* The application region is 64 bytes (0x40) */
- FLASH (rx) : ORIGIN = 0x63002040, LENGTH = 0xFFFFC0
- SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 112K
+ FLASH (X) : ORIGIN = 0x63002000, LENGTH = 0x1000000
+ RAM (W) : ORIGIN = 0x20004000, LENGTH = 112K
}
-MPU_MIN_ALIGN = 8K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/msp432.ld b/core/runtime/layouts/msp432.ld
index 2c9d2a4..170d4b1 100644
--- a/core/runtime/layouts/msp432.ld
+++ b/core/runtime/layouts/msp432.ld
@@ -1,9 +1,7 @@
MEMORY {
- /* The application region is 64 bytes (0x40) */
- FLASH (rx) : ORIGIN = 0x00020040, LENGTH = 0x0001FFC0
- SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 0x2000
+ FLASH (X) : ORIGIN = 0x00020000, LENGTH = 0x00020000
+ RAM (W) : ORIGIN = 0x20004000, LENGTH = 0x2000
}
-MPU_MIN_ALIGN = 8K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/nrf52.ld b/core/runtime/layouts/nrf52.ld
index 942e86b..fbbcdc3 100644
--- a/core/runtime/layouts/nrf52.ld
+++ b/core/runtime/layouts/nrf52.ld
@@ -1,11 +1,9 @@
/* Layout for the nRF52-DK, used by the examples in this repository. */
MEMORY {
- /* The application region is 64 bytes (0x40) */
- FLASH (rx) : ORIGIN = 0x00030040, LENGTH = 0x0005FFC0
- SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 62K
+ FLASH (X) : ORIGIN = 0x00030000, LENGTH = 0x00060000
+ RAM (W) : ORIGIN = 0x20004000, LENGTH = 62K
}
-MPU_MIN_ALIGN = 8K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/nrf52840.ld b/core/runtime/layouts/nrf52840.ld
index 31bf346..06b6f6b 100644
--- a/core/runtime/layouts/nrf52840.ld
+++ b/core/runtime/layouts/nrf52840.ld
@@ -1,11 +1,9 @@
/* Layout for the nRF52840-DK, usable by the examples in this repository. */
MEMORY {
- /* The application region is 64 bytes (0x40) */
- FLASH (rx) : ORIGIN = 0x00030040, LENGTH = 0x000CFFC0
- SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 62K
+ FLASH (X) : ORIGIN = 0x00030000, LENGTH = 0x000D0000
+ RAM (W) : ORIGIN = 0x20004000, LENGTH = 62K
}
-MPU_MIN_ALIGN = 8K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/nucleo_f429zi.ld b/core/runtime/layouts/nucleo_f429zi.ld
index 3e407b4..a9c634a 100644
--- a/core/runtime/layouts/nucleo_f429zi.ld
+++ b/core/runtime/layouts/nucleo_f429zi.ld
@@ -1,11 +1,9 @@
/* Layout for the Nucleo F429zi, used by the examples in this repository. */
MEMORY {
- /* The application region is 64 bytes (0x40) */
- FLASH (rx) : ORIGIN = 0x08040040, LENGTH = 255K
- SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 112K
+ FLASH (X) : ORIGIN = 0x08040000, LENGTH = 255K
+ RAM (W) : ORIGIN = 0x20004000, LENGTH = 112K
}
-MPU_MIN_ALIGN = 8K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/nucleo_f446re.ld b/core/runtime/layouts/nucleo_f446re.ld
index 83e698b..d3953f5 100644
--- a/core/runtime/layouts/nucleo_f446re.ld
+++ b/core/runtime/layouts/nucleo_f446re.ld
@@ -1,11 +1,9 @@
/* Layout for the Nucleo F446re, used by the examples in this repository. */
MEMORY {
- /* The application region is 64 bytes (0x40) */
- FLASH (rx) : ORIGIN = 0x08040040, LENGTH = 255K
- SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 176K
+ FLASH (X) : ORIGIN = 0x08040000, LENGTH = 255K
+ RAM (W) : ORIGIN = 0x20004000, LENGTH = 176K
}
-MPU_MIN_ALIGN = 8K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/opentitan.ld b/core/runtime/layouts/opentitan.ld
index ada781c..50ea340 100644
--- a/core/runtime/layouts/opentitan.ld
+++ b/core/runtime/layouts/opentitan.ld
@@ -1,18 +1,12 @@
/* Layout for the RISC-V 32 boards, used by the examples in this repository. */
MEMORY {
- /*
- * The TBF header can change in size so use 0x40 combined with
- * --protected-region-size with elf2tab to cover a header upto that
- * size.
- *
- * Note that the SRAM address may need to be changed depending on
+ /* Note that the SRAM address may need to be changed depending on
* the kernel binary, check for the actual address of APP_MEMORY!
*/
- FLASH (rx) : ORIGIN = 0x20030040, LENGTH = 32M
- SRAM (rwx) : ORIGIN = 0x10004000, LENGTH = 512K
+ FLASH (X) : ORIGIN = 0x20030000, LENGTH = 32M
+ RAM (W) : ORIGIN = 0x10004000, LENGTH = 512K
}
-MPU_MIN_ALIGN = 1K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/layouts/stm32f3discovery.ld b/core/runtime/layouts/stm32f3discovery.ld
index 9368003..05b0b54 100644
--- a/core/runtime/layouts/stm32f3discovery.ld
+++ b/core/runtime/layouts/stm32f3discovery.ld
@@ -1,11 +1,9 @@
/* Layout for the stm32f3discovery board, usable by the examples in this repository. */
MEMORY {
- /* The application region is 64 bytes (0x40) */
- FLASH (rx) : ORIGIN = 0x08020040, LENGTH = 0x00020000
- SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 48K
+ FLASH (X) : ORIGIN = 0x08020000, LENGTH = 0x00020000
+ RAM (W) : ORIGIN = 0x20004000, LENGTH = 48K
}
-MPU_MIN_ALIGN = 8K;
-
-INCLUDE layout_generic.ld
+TBF_HEADER_SIZE = 0x40;
+INCLUDE libtock_layout.ld
diff --git a/core/runtime/libtock_layout.ld b/core/runtime/libtock_layout.ld
new file mode 100644
index 0000000..fcff09a
--- /dev/null
+++ b/core/runtime/libtock_layout.ld
@@ -0,0 +1,129 @@
+/* Layout file for Tock process binaries that use libtock-rs. This currently
+ * implements static linking, because we do not have a working
+ * position-independent relocation solution. This layout works for all
+ * platforms libtock-rs supports (ARM and RISC-V).
+ *
+ * This layout should be included by a script that defines the FLASH and RAM
+ * regions for the board as well as TBF_HEADER_SIZE. Here is a an example
+ * process binary linker script to get started:
+ * MEMORY {
+ * FLASH (X) : ORIGIN = 0x10000, LENGTH = 0x10000
+ * RAM (W) : ORIGIN = 0x20000, LENGTH = 0x10000
+ * }
+ * TBF_HEADER_SIZE = 0x40;
+ * INCLUDE ../libtock-rs/layout.ld
+ *
+ * FLASH refers to the area the process binary occupies in flash, including TBF
+ * headers. RAM refers to the area the process will have access to in memory.
+ * STACK_SIZE is the size of the process' stack (this layout file may round the
+ * stack size up for alignment purposes). TBF_HEADER_SIZE must correspond to the
+ * --protected-region-size flag passed to elf2tab.
+ *
+ * This places the flash sections in the following order:
+ * 1. .rt_header -- Constants used by runtime initialization.
+ * 2. .text -- Executable code.
+ * 3. .rodata -- Read-only global data (e.g. most string constants).
+ * 4. .data -- Read-write data, copied to RAM at runtime.
+ *
+ * This places the RAM sections in the following order:
+ * 1. .stack -- The stack grows downward. Putting it first gives us
+ * MPU-based overflow detection.
+ * 2. .data -- Read-write data, initialized by copying from flash.
+ * 3. .bss -- Zero-initialized read-write global data.
+ * 4. Heap -- The heap (optional) comes after .bss and grows upwards to
+ * the process break.
+ */
+
+/* TODO: Should TBF_HEADER_SIZE be configured via a similar mechanism to the
+ * stack size? We should see if that is possible.
+ */
+
+/* GNU LD looks for `start` as an entry point by default, while LLVM's LLD looks
+ * for `_start`. To be compatible with both, we manually specify an entry point.
+ */
+ENTRY(start)
+
+SECTIONS {
+ /* Sections located in FLASH at runtime.
+ */
+
+ /* Add a section where elf2tab will place the TBF headers, so that the rest
+ * of the FLASH sections are in the right locations. */
+ .tbf_header (NOLOAD) : {
+ . = . + TBF_HEADER_SIZE;
+ } > FLASH
+
+ /* Runtime header. Contains values the linker knows that the runtime needs
+ * to look up.
+ */
+ .rt_header : {
+ rt_header = .;
+ LONG(start);
+ LONG(ADDR(.bss) + SIZEOF(.bss)); /* Initial process break */
+ LONG(_stack_top);
+ LONG(SIZEOF(.data));
+ LONG(LOADADDR(.data));
+ LONG(ADDR(.data));
+ LONG(SIZEOF(.bss));
+ LONG(ADDR(.bss));
+ } > FLASH
+
+ /* Text section -- the application's code. */
+ .text ALIGN(4) : {
+ *(.start)
+ *(.text)
+ } > FLASH
+
+ /* Read-only data section. Contains strings and other global constants. */
+ .rodata ALIGN(4) : {
+ *(.rodata)
+ /* .data is placed after .rodata in flash. data_flash_start is used by
+ * AT() to place .data in flash as well as in rt_header.
+ */
+ _data_flash_start = .;
+ } > FLASH
+
+ /* Sections located in RAM at runtime.
+ */
+
+ /* Reserve space for the stack. Aligned to a multiple of 16 bytes for the
+ * RISC-V calling convention:
+ * https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf
+ */
+ .stack (NOLOAD) : {
+ KEEP(*(.stack_buffer))
+ . = ALIGN(16);
+ _stack_top = .; /* Used in rt_header */
+ } > RAM
+
+ /* Read-write data section. This is deployed as part of FLASH but is copied
+ * into RAM at runtime.
+ */
+ .data ALIGN(4) : AT(_data_flash_start) {
+ data_ram_start = .;
+ /* .sdata is the RISC-V small data section */
+ *(.sdata .data)
+ /* Pad to word alignment so the relocation loop can use word-sized
+ * copies.
+ */
+ . = ALIGN(4);
+ } > RAM
+
+ /* BSS section. These are zero-initialized static variables. This section is
+ * not copied from FLASH into RAM but rather directly initialized, and is
+ * mainly put in this linker script so that we get an error if it overflows
+ * the RAM region.
+ */
+ .bss ALIGN(4) (NOLOAD) : {
+ /* .sbss is the RISC-V small data section */
+ *(.sbss .bss)
+ } > RAM
+
+ _heap_start = ADDR(.bss) + SIZEOF(.bss); /* Used by rt_header */
+
+ /* Sections we do not need. */
+ /DISCARD/ :
+ {
+ *(.ARM.exidx .eh_frame)
+ }
+}
diff --git a/tock2 b/tock2
new file mode 160000
index 0000000..17e698e
--- /dev/null
+++ b/tock2
@@ -0,0 +1 @@
+Subproject commit 17e698e8fb2c9628624398435f75db0f5a50dbcd