Replace sw/tock_matcha contents with a stub TockOS application that will become our root app for Shodan. Change-Id: I37ce52af83c597a94aac262f4eb9b481a8ff35b1
diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..62f8ccd --- /dev/null +++ b/.cargo/config.toml
@@ -0,0 +1,11 @@ +[build] +target = "riscv32imc-unknown-none-elf" +target-dir = "../../out/matcha" +rustflags = [ + "-C", "relocation-model=static", + "-C", "link-arg=-Tlayout_matcha.ld", +] + +# this doesn't work in our version of cargo yet +#[env] +#PLATFORM = "opentitan"
diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8cd968c --- /dev/null +++ b/Cargo.toml
@@ -0,0 +1,11 @@ +[package] +name = "matcha" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libtock = { path = "../libtock-rs" } +libtock_core = { path = "../libtock-rs/core" } +libtock_codegen = { path = "../libtock-rs/codegen" }
diff --git a/Makefile.common b/Makefile.common deleted file mode 100644 index 822ba83..0000000 --- a/Makefile.common +++ /dev/null
@@ -1,294 +0,0 @@ -# Force the Shell to be bash as some systems have strange default shells -SHELL := bash - -# Remove built-in rules and variables -# n.b. no-op for make --version < 4.0 -MAKEFLAGS += -r -MAKEFLAGS += -R - -# The absolute path of the directory containing this `Makefile.common` file. -MAKEFILE_COMMON_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))../tock/boards/ - -# The absolute path of Tock's root directory. -# This is currently the parent directory of MAKEFILE_COMMON_PATH. -TOCK_ROOT_DIRECTORY := $(dir $(abspath $(MAKEFILE_COMMON_PATH))) - -# Common defaults that specific boards can override, but likely do not need to. -TOOLCHAIN ?= llvm -CARGO ?= cargo -RUSTUP ?= rustup - -# Default location of target directory (relative to board makefile) -# passed to cargo --target_dir -TARGET_DIRECTORY ?= $(TOCK_ROOT_DIRECTORY)target/ - -# RUSTC_FLAGS allows boards to define board-specific options. -# This will hopefully move into Cargo.toml (or Cargo.toml.local) eventually. -# lld uses the page size to align program sections. It defaults to 4096 and this -# puts a gap between before the .relocate section. `zmax-page-size=512` tells -# lld the actual page size so it doesn't have to be conservative. -RUSTC_FLAGS ?= \ - -C link-arg=-Tlayout.ld \ - -C linker=rust-lld \ - -C linker-flavor=ld.lld \ - -C relocation-model=dynamic-no-pic \ - -C link-arg=-zmax-page-size=512 \ - -C link-arg=-icf=all \ - -# RISC-V-specific flags. -ifneq ($(findstring riscv32i, $(TARGET)),) - # NOTE: This flag causes kernel panics on some ARM cores. Since the - # size benefit is almost exclusively for RISC-V, we only apply it for - # those targets. - RUSTC_FLAGS += -C force-frame-pointers=no -endif - -# RUSTC_FLAGS_TOCK by default extends RUSTC_FLAGS with options -# that are global to all Tock boards. -# -# We use `remap-path-prefix` to remove user-specific filepath strings for error -# reporting from appearing in the generated binary. -RUSTC_FLAGS_TOCK ?= \ - $(RUSTC_FLAGS) \ - --remap-path-prefix=$(TOCK_ROOT_DIRECTORY)= \ - -# Disallow warnings for continuous integration builds. Disallowing them here -# ensures that warnings during testing won't prevent compilation from succeeding. -ifeq ($(CI),true) - RUSTC_FLAGS_TOCK += -D warnings -endif - -# The following flags should only be passed to the board's binary crate, but -# not to any of its dependencies (the kernel, capsules, chips, etc.). The -# dependencies wouldn't use it, but because the link path is different for each -# board, Cargo wouldn't be able to cache builds of the dependencies. -# -# Indeed, as far as Cargo is concerned, building the kernel with -# `-C link-arg=-L/tock/boards/imix` is different than building the kernel with -# `-C link-arg=-L/tock/boards/hail`, so Cargo would have to rebuild the kernel -# for each board instead of caching it per board (even if in reality the same -# kernel is built because the link-arg isn't used by the kernel). -# -# Ultimately, this should move to the Cargo.toml, for example when -# https://github.com/rust-lang/cargo/pull/7811 is merged into Cargo. -# -# The difference between `RUSTC_FLAGS_TOCK` and `RUSTC_FLAGS_FOR_BIN` is that -# the former is forwarded to all the dependencies (being passed to cargo via -# the `RUSTFLAGS` environment variable), whereas the latter is only applied to -# the final binary crate (being passed as parameter to `cargo rustc`). -RUSTC_FLAGS_FOR_BIN ?= \ - -C link-arg=-L$(abspath .) \ - -# http://stackoverflow.com/questions/10858261/abort-makefile-if-variable-not-set -# Check that given variables are set and all have non-empty values, print an -# error otherwise. -check_defined = $(strip $(foreach 1,$1,$(if $(value $1),,$(error Undefined variable "$1")))) - -# Check that we know the basics of what we are compiling for. -# `PLATFORM`: The name of the board that the kernel is being compiled for. -# `TARGET` : The Rust target architecture the kernel is being compiled for. -$(call check_defined, PLATFORM) -$(call check_defined, TARGET) - -# Location of target-specific build -TARGET_PATH := $(TARGET_DIRECTORY)$(TARGET) - -# If environment variable V is non-empty, be verbose. -ifneq ($(V),) - Q = - VERBOSE = --verbose -else - Q = @ - VERBOSE = -endif - -# Ask git what version of the Tock kernel we are compiling, so we can include -# this within the binary. If Tock is not within a git repo then we fallback to -# a set string which should be updated with every release. -export TOCK_KERNEL_VERSION := $(shell cd $(TOCK_ROOT_DIRECTORY) && git describe --tags --always 2> /dev/null || echo "1.4+") - -# Validate that rustup is new enough. -MINIMUM_RUSTUP_VERSION := 1.11.0 -RUSTUP_VERSION := $(strip $(word 2, $(shell $(RUSTUP) --version))) -ifeq ($(shell $(TOCK_ROOT_DIRECTORY)tools/semver.sh $(RUSTUP_VERSION) \< $(MINIMUM_RUSTUP_VERSION)), true) - $(warning Required tool `$(RUSTUP)` is out-of-date.) - $(warning Running `$(RUSTUP) update` in 3 seconds (ctrl-c to cancel)) - $(shell sleep 3s) - DUMMY := $(shell $(RUSTUP) update) -endif - -# Verify that various required Rust components are installed. All of these steps -# only have to be done once per Rust version, but will take some time when -# compiling for the first time. -LLVM_TOOLS_INSTALLED := $(shell $(RUSTUP) component list | grep 'llvm-tools-preview.*(installed)' > /dev/null; echo $$?) -ifeq ($(LLVM_TOOLS_INSTALLED),1) - $(shell $(RUSTUP) component add llvm-tools-preview) -endif -ifneq ($(shell $(RUSTUP) component list | grep rust-src),rust-src (installed)) - $(shell $(RUSTUP) component add rust-src) -endif -ifneq ($(shell $(RUSTUP) target list | grep "$(TARGET) (installed)"),$(TARGET) (installed)) - $(shell $(RUSTUP) target add $(TARGET)) -endif - -# If the user is using the standard toolchain we need to get the full path. -# rustup should take care of this for us by putting in a proxy in .cargo/bin, -# but until that is setup we workaround it. -ifeq ($(TOOLCHAIN),llvm) - TOOLCHAIN = "$(shell dirname $(shell find `rustc --print sysroot` -name llvm-size))/llvm" -endif - -# Set variables of the key tools we need to compile a Tock kernel. -SIZE ?= $(TOOLCHAIN)-size -OBJCOPY ?= $(TOOLCHAIN)-objcopy -OBJDUMP ?= $(TOOLCHAIN)-objdump - -# Set additional flags to produce binary from .elf. -# * --strip-sections prevents enormous binaries when SRAM is below flash. -# * --remove-section .apps prevents the .apps section from being included in the -# kernel binary file. This section is a placeholder for optionally including -# application binaries, and only needs to exist in the .elf. By removing it, -# we prevent the kernel binary from overwriting applications. -OBJCOPY_FLAGS ?= --strip-sections -S --remove-section .apps -# This make variable allows board-specific Makefiles to pass down options to -# the Cargo build command. For example, in boards/<custom_board>/Makefile: -# `CARGO_FLAGS += --features=foo` would pass feature `foo` to the top level -# Cargo.toml. -CARGO_FLAGS ?= -# Add default flags to cargo. Boards can add additional options in CARGO_FLAGS -CARGO_FLAGS_TOCK ?= $(VERBOSE) --target=$(TARGET) --package $(PLATFORM) --target-dir=$(TARGET_DIRECTORY) $(CARGO_FLAGS) -# Set the default flags we need for objdump to get a .lst file. -OBJDUMP_FLAGS ?= --disassemble-all --source --section-headers --demangle -# Set default flags for size -SIZE_FLAGS ?= - -# Need an extra flag for OBJDUMP if we are on a thumb platform. -ifneq (,$(findstring thumb,$(TARGET))) - OBJDUMP_FLAGS += --arch-name=thumb -endif - -# Check whether the system already has a sha256sum application -# present, if not use the custom shipped one -ifeq (, $(shell sha256sum --version 2>/dev/null)) - # No system sha256sum available - SHA256SUM := $(CARGO) run --manifest-path $(TOCK_ROOT_DIRECTORY)tools/sha256sum/Cargo.toml -- 2>/dev/null -else - # Use system sha256sum - SHA256SUM := sha256sum -endif - -# Dump configuration for verbose builds -ifneq ($(V),) - $(info ) - $(info *******************************************************) - $(info TOCK KERNEL BUILD SYSTEM -- VERBOSE BUILD CONFIGURATION) - $(info *******************************************************) - $(info MAKEFILE_COMMON_PATH = $(MAKEFILE_COMMON_PATH)) - $(info TOCK_ROOT_DIRECTORY = $(TOCK_ROOT_DIRECTORY)) - $(info TARGET_DIRECTORY = $(TARGET_DIRECTORY)) - $(info ) - $(info PLATFORM = $(PLATFORM)) - $(info TARGET = $(TARGET)) - $(info TOCK_KERNEL_VERSION = $(TOCK_KERNEL_VERSION)) - $(info RUSTC_FLAGS = $(RUSTC_FLAGS)) - $(info RUSTC_FLAGS_TOCK = $(RUSTC_FLAGS_TOCK)) - $(info MAKEFLAGS = $(MAKEFLAGS)) - $(info OBJDUMP_FLAGS = $(OBJDUMP_FLAGS)) - $(info OBJCOPY_FLAGS = $(OBJCOPY_FLAGS)) - $(info CARGO_FLAGS = $(CARGO_FLAGS)) - $(info CARGO_FLAGS_TOCK = $(CARGO_FLAGS_TOCK)) - $(info SIZE_FLAGS = $(SIZE_FLAGS)) - $(info ) - $(info TOOLCHAIN = $(TOOLCHAIN)) - $(info SIZE = $(SIZE)) - $(info OBJCOPY = $(OBJCOPY)) - $(info OBJDUMP = $(OBJDUMP)) - $(info CARGO = $(CARGO)) - $(info RUSTUP = $(RUSTUP)) - $(info SHA256SUM = $(SHA256SUM)) - $(info ) - $(info cargo --version = $(shell $(CARGO) --version)) - $(info rustc --version = $(shell rustc --version)) - $(info rustup --version = $(shell $(RUSTUP) --version)) - $(info *******************************************************) - $(info ) -endif - -.PRECIOUS: %.elf -# Support rules - -# User-facing targets -.PHONY: all -all: release - -# `make check` runs the Rust compiler but does not actually output the final -# binary. This makes checking for Rust errors much faster. -.PHONY: check -check: - $(Q)$(CARGO) check $(VERBOSE) $(CARGO_FLAGS_TOCK) - - -.PHONY: clean -clean:: - $(Q)$(CARGO) clean $(VERBOSE) --target-dir=$(TARGET_DIRECTORY) - -.PHONY: release -release: $(TARGET_PATH)/release/$(PLATFORM).bin - -.PHONY: debug -debug: $(TARGET_PATH)/debug/$(PLATFORM).bin - -.PHONY: debug-lst -debug-lst: $(TARGET_PATH)/debug/$(PLATFORM).lst - -.PHONY: doc -doc: | target - @# This mess is all to work around rustdoc giving no way to return an - @# error if there are warnings. This effectively simulates that. - $(Q)RUSTDOCFLAGS='-Z unstable-options --document-hidden-items -D warnings' $(CARGO) --color=always doc $(VERBOSE) --release --package $(PLATFORM) --target-dir=$(TARGET_DIRECTORY) 2>&1 | tee /dev/tty | grep -q warning && (echo "Warnings detected during doc build" && if [[ $$CI == "true" ]]; then echo "Erroring due to CI context" && exit 33; fi) || if [ $$? -eq 33 ]; then exit 1; fi - - -.PHONY: lst -lst: $(TARGET_PATH)/release/$(PLATFORM).lst - -# Helper rule for showing the TARGET used by this board. Useful when building -# the documentation for all boards. -.PHONY: show-target -show-target: - $(info $(TARGET)) - -# Support rules - -target: - @mkdir -p $(TARGET_PATH) - -# Cargo outputs an elf file (just without a file extension) -%.elf: % - $(Q)cp $< $@ - - -%.bin: %.elf - $(Q)$(OBJCOPY) --output-target=binary $(OBJCOPY_FLAGS) $< $@ - $(Q)$(SHA256SUM) $@ - -%.lst: %.elf - $(Q)$(OBJDUMP) $(OBJDUMP_FLAGS) $< > $@ - - -$(TOCK_ROOT_DIRECTORY)tools/sha256sum/target/debug/sha256sum: - $(Q)$(CARGO) build $(VERBOSE) --manifest-path $(TOCK_ROOT_DIRECTORY)tools/sha256sum/Cargo.toml - - -# Cargo-drivers -# We want to always invoke cargo (yay nested build systems), so these need to -# be phony, which means they can't be pattern rules. - -.PHONY: $(TARGET_PATH)/release/$(PLATFORM) -$(TARGET_PATH)/release/$(PLATFORM): - $(Q)RUSTFLAGS="$(RUSTC_FLAGS_TOCK)" $(CARGO) rustc $(CARGO_FLAGS_TOCK) --bin $(PLATFORM) --release -- $(RUSTC_FLAGS_FOR_BIN) - $(Q)$(SIZE) $(SIZE_FLAGS) $@ - -.PHONY: $(TARGET_PATH)/debug/$(PLATFORM) -$(TARGET_PATH)/debug/$(PLATFORM): - $(Q)RUSTFLAGS="$(RUSTC_FLAGS_TOCK)" $(CARGO) rustc $(CARGO_FLAGS_TOCK) --bin $(PLATFORM) -- $(RUSTC_FLAGS_FOR_BIN) - $(Q)$(SIZE) $(SIZE_FLAGS) $@
diff --git a/boards/opentitan-matcha/Cargo.lock b/boards/opentitan-matcha/Cargo.lock deleted file mode 100644 index 92c2512..0000000 --- a/boards/opentitan-matcha/Cargo.lock +++ /dev/null
@@ -1,88 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "capsules" -version = "0.1.0" -dependencies = [ - "enum_primitive", - "kernel", -] - -[[package]] -name = "components" -version = "0.1.0" -dependencies = [ - "capsules", - "kernel", -] - -[[package]] -name = "enum_primitive" -version = "0.1.0" - -[[package]] -name = "kernel" -version = "0.1.0" -dependencies = [ - "tock-cells", - "tock-registers", -] - -[[package]] -name = "lowrisc" -version = "0.1.0" -dependencies = [ - "kernel", - "rv32i", - "tock-rt0", -] - -[[package]] -name = "matcha" -version = "0.1.0" -dependencies = [ - "kernel", - "lowrisc", - "rv32i", -] - -[[package]] -name = "opentitan-matcha" -version = "0.1.0" -dependencies = [ - "capsules", - "components", - "kernel", - "lowrisc", - "matcha", - "rv32i", -] - -[[package]] -name = "riscv-csr" -version = "0.1.0" -dependencies = [ - "tock-registers", -] - -[[package]] -name = "rv32i" -version = "0.1.0" -dependencies = [ - "kernel", - "riscv-csr", - "tock-registers", - "tock-rt0", -] - -[[package]] -name = "tock-cells" -version = "0.1.0" - -[[package]] -name = "tock-registers" -version = "0.5.0" - -[[package]] -name = "tock-rt0" -version = "0.1.0"
diff --git a/boards/opentitan-matcha/Cargo.toml b/boards/opentitan-matcha/Cargo.toml deleted file mode 100644 index 6d99d20..0000000 --- a/boards/opentitan-matcha/Cargo.toml +++ /dev/null
@@ -1,30 +0,0 @@ -[package] -name = "opentitan-matcha" -version = "0.1.0" -authors = ["Tock Project Developers <tock-dev@googlegroups.com>"] -build = "build.rs" -edition = "2018" - -[dependencies] -components = { path = "../../../tock/boards/components" } -rv32i = { path = "../../../tock/arch/rv32i" } -capsules = { path = "../../../tock/capsules" } -kernel = { path = "../../../tock/kernel" } -matcha = { path = "../../chips/matcha" } -lowrisc = { path = "../../../tock/chips/lowrisc" } - -[features] -# OpenTitan Matcha SoC design can be synthesized or compiled for different targets. A -# target can be a specific FPGA board, an ASIC technology, or a simulation tool. -# Please see: https://docs.opentitan.org/doc/ug/getting_started/ for further -# information. -# -# OpenTitan Matcha CPU and possibly other components must be configured appropriately -# for a specific target: -# - fpga_nexysvideo: -# OpenTitan Matcha SoC design running on Nexys Video Artix-7 FPGA. -# -# - sim_verilator: -# OpenTitan Matcha SoC design simulated in Verilator. -fpga_nexysvideo = ["matcha/config_fpga_nexysvideo"] -sim_verilator = ["matcha/config_sim_verilator"]
diff --git a/boards/opentitan-matcha/Makefile b/boards/opentitan-matcha/Makefile deleted file mode 100644 index f891877..0000000 --- a/boards/opentitan-matcha/Makefile +++ /dev/null
@@ -1,34 +0,0 @@ -# Makefile for building the tock kernel for the OpenTitan Matcha platform - -DEFAULT_BOARD_CONFIGURATION=fpga_nexysvideo -TARGET=riscv32imc-unknown-none-elf -PLATFORM=opentitan-matcha -FLASHID=--dev-id="0403:6010" -RISC_PREFIX = riscv64-elf - - -include ../../Makefile.common - -# Pass OpenTitan board configuration option in `BOARD_CONFIGURATION` through -# Cargo `--features`. Please see `Cargo.toml` for available options. -ifneq ($(BOARD_CONFIGURATION),) - CARGO_FLAGS += --features=$(BOARD_CONFIGURATION) -else - CARGO_FLAGS += --features=$(DEFAULT_BOARD_CONFIGURATION) -endif - -qemu: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).elf - $(call check_defined, OPENTITAN_BOOT_ROM) - qemu-system-riscv32 -M opentitan -kernel $^ -bios $(OPENTITAN_BOOT_ROM) -nographic -serial mon:stdio - -qemu-app: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).elf - $(call check_defined, OPENTITAN_BOOT_ROM) - qemu-system-riscv32 -M opentitan -kernel $^ -bios $(OPENTITAN_BOOT_ROM) -device loader,file=$(APP),addr=0x20030000 -nographic -serial mon:stdio - -flash: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin - $(OPENTITAN_TREE)/build-out/sw/host/spiflash/spiflash $(FLASHID) --input=$(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin - -flash-app: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).elf - $(RISC_PREFIX)-objcopy --update-section .apps=$(APP) $^ $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM)-app.elf - $(RISC_PREFIX)-objcopy --output-target=binary $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM)-app.elf $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM)-app.bin - $(OPENTITAN_TREE)/build-out/sw/host/spiflash/spiflash $(FLASHID) --input=$(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM)-app.bin
diff --git a/boards/opentitan-matcha/README.md b/boards/opentitan-matcha/README.md deleted file mode 100644 index 551991f..0000000 --- a/boards/opentitan-matcha/README.md +++ /dev/null
@@ -1,4 +0,0 @@ -OpenTitan Matcha RISC-V Board -================= - -This is provides board support for the Matcha config of OpenTitan. \ No newline at end of file
diff --git a/boards/opentitan-matcha/build.rs b/boards/opentitan-matcha/build.rs deleted file mode 100644 index ab031c3..0000000 --- a/boards/opentitan-matcha/build.rs +++ /dev/null
@@ -1,4 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=layout.ld"); - println!("cargo:rerun-if-changed=../../../tock/boards/kernel_layout.ld"); -}
diff --git a/boards/opentitan-matcha/layout.ld b/boards/opentitan-matcha/layout.ld deleted file mode 100644 index 61f2e9a..0000000 --- a/boards/opentitan-matcha/layout.ld +++ /dev/null
@@ -1,22 +0,0 @@ -MEMORY -{ - rom (rx) : ORIGIN = 0x20000000, LENGTH = 0x30000 - prog (rx) : ORIGIN = 0x20030000, LENGTH = 0x100000-0x30000 - ram (!rx) : ORIGIN = 0x10000000, LENGTH = 0x10000 -} - -MPU_MIN_ALIGN = 1K; -SECTIONS { - /* - * The flash header needs to match what the boot ROM for OpenTitan is - * expecting. At the moment, it contains only the entry point, but it - * will eventually contain the signature -- and (hopefully?!) some - * versioning information to make it slightly easier to debug when the - * boot ROM and Tock are out of sync with respect to the definition... - */ - .flash_header : { - LONG(_stext) - } > rom -} - -INCLUDE ../../../tock/boards/kernel_layout.ld
diff --git a/boards/opentitan-matcha/src/io.rs b/boards/opentitan-matcha/src/io.rs deleted file mode 100644 index 2439aec..0000000 --- a/boards/opentitan-matcha/src/io.rs +++ /dev/null
@@ -1,50 +0,0 @@ -use core::fmt::Write; -use core::panic::PanicInfo; -use core::str; -use kernel::debug; -use kernel::debug::IoWrite; -use kernel::hil::gpio; -use kernel::hil::led; - -use crate::CHIP; -use crate::PROCESSES; - -struct Writer {} - -static mut WRITER: Writer = Writer {}; - -impl Write for Writer { - fn write_str(&mut self, s: &str) -> ::core::fmt::Result { - self.write(s.as_bytes()); - Ok(()) - } -} - -impl IoWrite for Writer { - fn write(&mut self, buf: &[u8]) { - unsafe { - matcha::uart::UART0.transmit_sync(buf); - } - } -} - -/// Panic handler. -#[cfg(not(test))] -#[no_mangle] -#[panic_handler] -pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! { - // turn off the non panic leds, just in case - let first_led = &mut led::LedLow::new(&mut matcha::gpio::PORT[7]); - gpio::Pin::make_output(&matcha::gpio::PORT[7]); - - let writer = &mut WRITER; - - debug::panic( - &mut [first_led], - writer, - pi, - &rv32i::support::nop, - &PROCESSES, - &CHIP, - ) -}
diff --git a/boards/opentitan-matcha/src/main.rs b/boards/opentitan-matcha/src/main.rs deleted file mode 100644 index 9dcc2ab..0000000 --- a/boards/opentitan-matcha/src/main.rs +++ /dev/null
@@ -1,309 +0,0 @@ -//! Board file for LowRISC OpenTitan Matcha RISC-V development platform. -//! -//! - <https://opentitan.org/> - -#![no_std] -// Disable this attribute when documenting, as a workaround for -// https://github.com/rust-lang/rust/issues/62184. -#![cfg_attr(not(doc), no_main)] -#![feature(const_in_array_repeat_expressions)] - -use capsules::virtual_alarm::{MuxAlarm, VirtualMuxAlarm}; -use capsules::virtual_hmac::VirtualMuxHmac; -use kernel::capabilities; -use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState}; -use kernel::component::Component; -use kernel::hil; -use kernel::hil::i2c::I2CMaster; -use kernel::hil::time::Alarm; -use kernel::Chip; -use kernel::Platform; -use kernel::{create_capability, debug, static_init}; -use rv32i::csr; - -pub mod io; - -// -// Actual memory for holding the active process structures. Need an empty list -// at least. -static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; 4] = - [None, None, None, None]; - -static mut CHIP: Option< - &'static matcha::chip::Matcha<VirtualMuxAlarm<'static, matcha::timer::RvTimer>>, -> = None; - -// How should the kernel respond when a process faults. -const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic; - -/// Dummy buffer that causes the linker to reserve enough space for the stack. -#[no_mangle] -#[link_section = ".stack_buffer"] -pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000]; - -/// A structure representing this platform that holds references to all -/// capsules for this platform. We've included an alarm and console. -struct OpenTitan { - led: &'static capsules::led::LED<'static, matcha::gpio::GpioPin<'static>>, - gpio: &'static capsules::gpio::GPIO<'static, matcha::gpio::GpioPin<'static>>, - console: &'static capsules::console::Console<'static>, - alarm: &'static capsules::alarm::AlarmDriver< - 'static, - VirtualMuxAlarm<'static, matcha::timer::RvTimer<'static>>, - >, - hmac: &'static capsules::hmac::HmacDriver< - 'static, - VirtualMuxHmac<'static, lowrisc::hmac::Hmac<'static>, [u8; 32]>, - [u8; 32], - >, - lldb: &'static capsules::low_level_debug::LowLevelDebug< - 'static, - capsules::virtual_uart::UartDevice<'static>, - >, - i2c_master: &'static capsules::i2c_master::I2CMasterDriver<lowrisc::i2c::I2c<'static>>, -} - -/// Mapping of integer syscalls to objects that implement syscalls. -impl Platform for OpenTitan { - fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R - where - F: FnOnce(Option<&dyn kernel::Driver>) -> R, - { - match driver_num { - capsules::led::DRIVER_NUM => f(Some(self.led)), - capsules::hmac::DRIVER_NUM => f(Some(self.hmac)), - capsules::gpio::DRIVER_NUM => f(Some(self.gpio)), - capsules::console::DRIVER_NUM => f(Some(self.console)), - capsules::alarm::DRIVER_NUM => f(Some(self.alarm)), - capsules::low_level_debug::DRIVER_NUM => f(Some(self.lldb)), - capsules::i2c_master::DRIVER_NUM => f(Some(self.i2c_master)), - _ => f(None), - } - } -} - -/// Reset Handler. -/// -/// This function is called from the arch crate after some very basic RISC-V -/// setup. -#[no_mangle] -pub unsafe fn reset_handler() { - // Basic setup of the platform. - rv32i::init_memory(); - // Ibex-specific handler - matcha::chip::configure_trap_handler(); - - // initialize capabilities - let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability); - let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability); - - let main_loop_cap = create_capability!(capabilities::MainLoopCapability); - - let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES)); - - let dynamic_deferred_call_clients = - static_init!([DynamicDeferredCallClientState; 1], Default::default()); - let dynamic_deferred_caller = static_init!( - DynamicDeferredCall, - DynamicDeferredCall::new(dynamic_deferred_call_clients) - ); - DynamicDeferredCall::set_global_instance(dynamic_deferred_caller); - - // Configure kernel debug gpios as early as possible - kernel::debug::assign_gpios( - Some(&matcha::gpio::PORT[7]), // First LED - None, - None, - ); - - // Create a shared UART channel for the console and for kernel debug. - let uart_mux = components::console::UartMuxComponent::new( - &matcha::uart::UART0, - matcha::uart::UART0_BAUDRATE, - dynamic_deferred_caller, - ) - .finalize(()); - - // LEDs - // Start with half on and half off - let led = components::led::LedsComponent::new(components::led_component_helper!( - matcha::gpio::GpioPin, - ( - &matcha::gpio::PORT[8], - kernel::hil::gpio::ActivationMode::ActiveHigh - ), - ( - &matcha::gpio::PORT[9], - kernel::hil::gpio::ActivationMode::ActiveHigh - ), - ( - &matcha::gpio::PORT[10], - kernel::hil::gpio::ActivationMode::ActiveHigh - ), - ( - &matcha::gpio::PORT[11], - kernel::hil::gpio::ActivationMode::ActiveHigh - ), - ( - &matcha::gpio::PORT[12], - kernel::hil::gpio::ActivationMode::ActiveHigh - ), - ( - &matcha::gpio::PORT[13], - kernel::hil::gpio::ActivationMode::ActiveHigh - ), - ( - &matcha::gpio::PORT[14], - kernel::hil::gpio::ActivationMode::ActiveHigh - ), - ( - &matcha::gpio::PORT[15], - kernel::hil::gpio::ActivationMode::ActiveHigh - ) - )) - .finalize(components::led_component_buf!(matcha::gpio::GpioPin)); - - let gpio = components::gpio::GpioComponent::new( - board_kernel, - components::gpio_component_helper!( - matcha::gpio::GpioPin, - 0 => &matcha::gpio::PORT[0], - 1 => &matcha::gpio::PORT[1], - 2 => &matcha::gpio::PORT[2], - 3 => &matcha::gpio::PORT[3], - 4 => &matcha::gpio::PORT[4], - 5 => &matcha::gpio::PORT[5], - 6 => &matcha::gpio::PORT[6], - 7 => &matcha::gpio::PORT[15] - ), - ) - .finalize(components::gpio_component_buf!(matcha::gpio::GpioPin)); - - let alarm = &matcha::timer::TIMER; - alarm.setup(); - - // Create a shared virtualization mux layer on top of a single hardware - // alarm. - let mux_alarm = static_init!( - MuxAlarm<'static, matcha::timer::RvTimer>, - MuxAlarm::new(alarm) - ); - hil::time::Alarm::set_alarm_client(&matcha::timer::TIMER, mux_alarm); - - // Alarm - let virtual_alarm_user = static_init!( - VirtualMuxAlarm<'static, matcha::timer::RvTimer>, - VirtualMuxAlarm::new(mux_alarm) - ); - let scheduler_timer_virtual_alarm = static_init!( - VirtualMuxAlarm<'static, matcha::timer::RvTimer>, - VirtualMuxAlarm::new(mux_alarm) - ); - let alarm = static_init!( - capsules::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, matcha::timer::RvTimer>>, - capsules::alarm::AlarmDriver::new( - virtual_alarm_user, - board_kernel.create_grant(&memory_allocation_cap) - ) - ); - hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm); - - let chip = static_init!( - matcha::chip::Matcha<VirtualMuxAlarm<'static, matcha::timer::RvTimer>>, - matcha::chip::Matcha::new(scheduler_timer_virtual_alarm) - ); - scheduler_timer_virtual_alarm.set_alarm_client(chip.scheduler_timer()); - CHIP = Some(chip); - - // Need to enable all interrupts for Tock Kernel - chip.enable_plic_interrupts(); - // enable interrupts globally - csr::CSR - .mie - .modify(csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET + csr::mie::mie::mext::SET); - csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET); - - // Setup the console. - let console = components::console::ConsoleComponent::new(board_kernel, uart_mux).finalize(()); - // Create the debugger object that handles calls to `debug!()`. - components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(()); - - let lldb = components::lldb::LowLevelDebugComponent::new(board_kernel, uart_mux).finalize(()); - - let hmac_data_buffer = static_init!([u8; 64], [0; 64]); - let hmac_dest_buffer = static_init!([u8; 32], [0; 32]); - - let mux_hmac = components::hmac::HmacMuxComponent::new(&matcha::hmac::HMAC).finalize( - components::hmac_mux_component_helper!(lowrisc::hmac::Hmac, [u8; 32]), - ); - - let hmac = components::hmac::HmacComponent::new( - board_kernel, - &mux_hmac, - hmac_data_buffer, - hmac_dest_buffer, - ) - .finalize(components::hmac_component_helper!( - lowrisc::hmac::Hmac, - [u8; 32] - )); - - let i2c_master = static_init!( - capsules::i2c_master::I2CMasterDriver<lowrisc::i2c::I2c<'static>>, - capsules::i2c_master::I2CMasterDriver::new( - &matcha::i2c::I2C, - &mut capsules::i2c_master::BUF, - board_kernel.create_grant(&memory_allocation_cap) - ) - ); - - matcha::i2c::I2C.set_master_client(i2c_master); - - /// These symbols are defined in the linker script. - extern "C" { - /// Beginning of the ROM region containing app images. - static _sapps: u8; - /// End of the ROM region containing app images. - static _eapps: u8; - /// Beginning of the RAM region for app memory. - static mut _sappmem: u8; - /// End of the RAM region for app memory. - static _eappmem: u8; - } - - let opentitan = OpenTitan { - gpio: gpio, - led: led, - console: console, - alarm: alarm, - hmac, - lldb: lldb, - i2c_master, - }; - - kernel::procs::load_processes( - board_kernel, - chip, - core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, - ), - core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, - ), - &mut PROCESSES, - FAULT_RESPONSE, - &process_mgmt_cap, - ) - .unwrap_or_else(|err| { - debug!("Error loading processes!"); - debug!("{:?}", err); - }); - debug!("OpenTitan initialisation complete. Entering main loop"); - debug!("Woo Tock!"); - - - let scheduler = components::sched::priority::PriorityComponent::new(board_kernel).finalize(()); - board_kernel.kernel_loop(&opentitan, chip, None, scheduler, &main_loop_cap); -}
diff --git a/chips/matcha/Cargo.toml b/chips/matcha/Cargo.toml deleted file mode 100644 index 1c39868..0000000 --- a/chips/matcha/Cargo.toml +++ /dev/null
@@ -1,18 +0,0 @@ -[package] -name = "matcha" -version = "0.1.0" -authors = ["Tock Project Developers <tock-dev@googlegroups.com>"] -edition = "2018" - -[features] -# Compiling this crate requires enabling one of these features, otherwise -# the default will be chosen. -config_fpga_nexysvideo = ["config_disable_default"] -config_sim_verilator = ["config_disable_default"] -config_disable_default = [] - -[dependencies] -lowrisc = { path = "../../../tock/chips/lowrisc" } -rv32i = { path = "../../../tock/arch/rv32i" } -kernel = { path = "../../../tock/kernel" } -
diff --git a/chips/matcha/README.md b/chips/matcha/README.md deleted file mode 100644 index b5b6a4c..0000000 --- a/chips/matcha/README.md +++ /dev/null
@@ -1,4 +0,0 @@ -OpenTitan Matcha SoC -======================= -Matcha is the dual-hart OpenTitan system. At the center of the Matcha are two -Ibex RISC-V compliant processors. \ No newline at end of file
diff --git a/chips/matcha/src/aes.rs b/chips/matcha/src/aes.rs deleted file mode 100644 index 7ab4bf9..0000000 --- a/chips/matcha/src/aes.rs +++ /dev/null
@@ -1,350 +0,0 @@ -//! Support for the AES hardware block on OpenTitan -//! -//! https://docs.opentitan.org/hw/ip/aes/doc/ - -use kernel::common::cells::{OptionalCell, TakeCell}; -use kernel::common::registers::{ - register_bitfields, register_structs, ReadOnly, ReadWrite, WriteOnly, -}; -use kernel::common::StaticRef; -use kernel::debug; -use kernel::hil; -use kernel::hil::symmetric_encryption; -use kernel::hil::symmetric_encryption::{AES128_BLOCK_SIZE, AES128_KEY_SIZE}; -use kernel::ReturnCode; - -const MAX_LENGTH: usize = 128; - -register_structs! { - pub AesRegisters { - (0x00 => key0: WriteOnly<u32>), - (0x04 => key1: WriteOnly<u32>), - (0x08 => key2: WriteOnly<u32>), - (0x0c => key3: WriteOnly<u32>), - (0x10 => key4: WriteOnly<u32>), - (0x14 => key5: WriteOnly<u32>), - (0x18 => key6: WriteOnly<u32>), - (0x1c => key7: WriteOnly<u32>), - (0x20 => data_in0: WriteOnly<u32>), - (0x24 => data_in1: WriteOnly<u32>), - (0x28 => data_in2: WriteOnly<u32>), - (0x2c => data_in3: WriteOnly<u32>), - (0x30 => data_out0: ReadOnly<u32>), - (0x34 => data_out1: ReadOnly<u32>), - (0x38 => data_out2: ReadOnly<u32>), - (0x3c => data_out3: ReadOnly<u32>), - (0x40 => ctrl: ReadWrite<u32, CTRL::Register>), - (0x44 => trigger: WriteOnly<u32, TRIGGER::Register>), - (0x48 => status: ReadOnly<u32, STATUS::Register>), - (0x4c => @END), - } -} - -register_bitfields![u32, - CTRL [ - OPERATION OFFSET(0) NUMBITS(1) [ - Encrypting = 0, - Decrypting = 1 - ], - KEY_LEN OFFSET(1) NUMBITS(3) [ - Key128 = 1, - Key192 = 2, - Key256 = 4 - ], - MANUAL_OPERATION OFFSET(4) NUMBITS(1) [] - ], - TRIGGER [ - START OFFSET(0) NUMBITS(1) [], - KEY_CLEAR OFFSET(1) NUMBITS(1) [], - DATA_IN_CLEAR OFFSET(2) NUMBITS(1) [], - DATA_OUT_CLEAR OFFSET(3) NUMBITS(1) [] - ], - STATUS [ - IDLE 0, - STALL 1, - OUTPUT_VALID 2, - INPUT_READY 3 - ] -]; - -// https://docs.opentitan.org/hw/top_earlgrey/doc/ -const AES_BASE: StaticRef<AesRegisters> = - unsafe { StaticRef::new(0x41100000 as *const AesRegisters) }; - -pub struct Aes<'a> { - registers: StaticRef<AesRegisters>, - - client: OptionalCell<&'a dyn hil::symmetric_encryption::Client<'a>>, - source: TakeCell<'a, [u8]>, - dest: TakeCell<'a, [u8]>, -} - -impl<'a> Aes<'a> { - const fn new() -> Aes<'a> { - Aes { - registers: AES_BASE, - client: OptionalCell::empty(), - source: TakeCell::empty(), - dest: TakeCell::empty(), - } - } - - fn clear(&self) { - let regs = self.registers; - regs.trigger.write( - TRIGGER::KEY_CLEAR::SET + TRIGGER::DATA_IN_CLEAR::SET + TRIGGER::DATA_OUT_CLEAR::SET, - ); - } - - fn configure(&self, encrypting: bool) { - let regs = self.registers; - let e = if encrypting { - CTRL::OPERATION::Encrypting - } else { - CTRL::OPERATION::Decrypting - }; - // Set this in manual mode for the moment since automatic block mode - // does not appear to be working - - regs.ctrl - .write(e + CTRL::KEY_LEN::Key128 + CTRL::MANUAL_OPERATION::SET); - } - - fn idle(&self) -> bool { - let regs = self.registers; - regs.status.is_set(STATUS::IDLE) - } - - fn input_ready(&self) -> bool { - let regs = self.registers; - regs.status.is_set(STATUS::INPUT_READY) - } - - fn output_valid(&self) -> bool { - let regs = self.registers; - regs.status.is_set(STATUS::OUTPUT_VALID) - } - - fn trigger(&self) { - let regs = self.registers; - regs.trigger.write(TRIGGER::START::SET); - } - - fn read_block(&self, blocknum: usize) { - let regs = self.registers; - let blocknum = blocknum * AES128_BLOCK_SIZE; - - loop { - if self.output_valid() { - break; - } - } - - self.dest.map_or_else( - || { - debug!("Called read_block() with no data"); - }, - |dest| { - for i in 0..4 { - // we work off an array of u8 so we need to assemble those - // back into a u32 - let mut v = 0; - match i { - 0 => v = regs.data_out0.get(), - 1 => v = regs.data_out1.get(), - 2 => v = regs.data_out2.get(), - 3 => v = regs.data_out3.get(), - _ => {} - } - dest[blocknum + (i * 4) + 0] = (v >> 0) as u8; - dest[blocknum + (i * 4) + 1] = (v >> 8) as u8; - dest[blocknum + (i * 4) + 2] = (v >> 16) as u8; - dest[blocknum + (i * 4) + 3] = (v >> 24) as u8; - } - }, - ); - } - - fn write_block(&self, blocknum: usize) { - let regs = self.registers; - let blocknum = blocknum * AES128_BLOCK_SIZE; - - loop { - if self.input_ready() { - break; - } - } - - self.source.map_or_else( - || { - // This is the case that dest = source - self.dest.map_or_else( - || { - debug!("Called write_block() with no data"); - }, - |dest| { - for i in 0..4 { - // we work off an array of u8 so we need to - // assemble those back into a u32 - let mut v = dest[blocknum + (i * 4) + 0] as usize; - v |= (dest[blocknum + (i * 4) + 1] as usize) << 8; - v |= (dest[blocknum + (i * 4) + 2] as usize) << 16; - v |= (dest[blocknum + (i * 4) + 3] as usize) << 24; - match i { - 0 => regs.data_in0.set(v as u32), - 1 => regs.data_in1.set(v as u32), - 2 => regs.data_in2.set(v as u32), - 3 => regs.data_in3.set(v as u32), - _ => {} - } - } - }, - ) - }, - |source| { - for i in 0..4 { - // we work off an array of u8 so we need to assemble - // those back into a u32 - let mut v = source[blocknum + (i * 4) + 0] as usize; - v |= (source[blocknum + (i * 4) + 1] as usize) << 8; - v |= (source[blocknum + (i * 4) + 2] as usize) << 16; - v |= (source[blocknum + (i * 4) + 3] as usize) << 24; - match i { - 0 => regs.data_in0.set(v as u32), - 1 => regs.data_in1.set(v as u32), - 2 => regs.data_in2.set(v as u32), - 3 => regs.data_in3.set(v as u32), - _ => {} - } - } - }, - ); - } - - fn set_key(&self, key: &[u8]) -> ReturnCode { - let regs = self.registers; - - loop { - if self.idle() { - break; - } - } - - if key.len() != AES128_KEY_SIZE { - return ReturnCode::EINVAL; - } - - for i in 0..4 { - let mut k = key[i * 4 + 0] as usize; - k |= (key[i * 4 + 1] as usize) << 8; - k |= (key[i * 4 + 2] as usize) << 16; - k |= (key[i * 4 + 3] as usize) << 24; - match i { - 0 => regs.key0.set(k as u32), - 1 => regs.key1.set(k as u32), - 2 => regs.key2.set(k as u32), - 3 => regs.key3.set(k as u32), - _ => {} - } - } - - // We must write the rest of the registers as well - regs.key4.set(0); - regs.key5.set(0); - regs.key6.set(0); - regs.key7.set(0); - ReturnCode::SUCCESS - } - - fn do_crypt(&self, start_index: usize, stop_index: usize, wr_start_index: usize) { - // convert our indicies into the array into block numbers - // start and end are pointer for reading - // write is the pointer for writing - // Note that depending on whether or not we have separate source - // and dest buffers the write and read pointers may index into - // different arrays. - let start_block = start_index / AES128_BLOCK_SIZE; - let end_block = stop_index / AES128_BLOCK_SIZE; - let mut write_block = wr_start_index / AES128_BLOCK_SIZE; - for i in start_block..end_block { - self.write_block(write_block); - self.trigger(); - self.read_block(i); - write_block = write_block + 1; - } - } -} - -impl<'a> hil::symmetric_encryption::AES128<'a> for Aes<'a> { - fn enable(&self) { - self.configure(true); - } - - fn disable(&self) { - self.clear(); - } - - fn set_client(&'a self, client: &'a dyn symmetric_encryption::Client<'a>) { - self.client.set(client); - } - - fn set_iv(&self, _iv: &[u8]) -> ReturnCode { - // nothing because this is ECB - ReturnCode::SUCCESS - } - - fn start_message(&self) {} - - fn set_key(&self, key: &[u8]) -> ReturnCode { - self.set_key(key) - } - - fn crypt( - &'a self, - source: Option<&'a mut [u8]>, - dest: &'a mut [u8], - start_index: usize, - stop_index: usize, - ) -> Option<(ReturnCode, Option<&'a mut [u8]>, &'a mut [u8])> { - match stop_index.checked_sub(start_index) { - None => return Some((ReturnCode::EINVAL, source, dest)), - Some(s) => { - if s > MAX_LENGTH { - return Some((ReturnCode::EINVAL, source, dest)); - } - if s % AES128_BLOCK_SIZE != 0 { - return Some((ReturnCode::EINVAL, source, dest)); - } - } - } - self.dest.replace(dest); - // The crypt API has two cases: separate source and destination - // buffers and a single source buffer. - // If we don't have a separate source buffer, we overwrite the - // destination with the data. This means that read index and write - // index match - // If we do have a separate source buffer, we start writing from - // 0 and the read index is separate. - match source { - None => { - self.do_crypt(start_index, stop_index, start_index); - } - Some(src) => { - self.source.replace(src); - self.do_crypt(start_index, stop_index, 0); - } - } - self.client.map(|client| { - client.crypt_done(self.source.take(), self.dest.take().unwrap()); - }); - None - } -} - -pub static mut AES: Aes<'static> = Aes::new(); - -impl kernel::hil::symmetric_encryption::AES128ECB for Aes<'_> { - fn set_mode_aes128ecb(&self, encrypting: bool) { - self.configure(encrypting); - } -}
diff --git a/chips/matcha/src/chip.rs b/chips/matcha/src/chip.rs deleted file mode 100644 index 58a95b9..0000000 --- a/chips/matcha/src/chip.rs +++ /dev/null
@@ -1,338 +0,0 @@ -//! High-level setup and interrupt mapping for the chip. - -use core::fmt::Write; -use core::hint::unreachable_unchecked; -use kernel; -use kernel::debug; -use kernel::hil::time::Alarm; -use kernel::Chip; -use rv32i::csr::{mcause, mie::mie, mip::mip, mtvec::mtvec, CSR}; -use rv32i::syscall::SysCall; -use rv32i::PMPConfigMacro; - -use crate::chip_config::CONFIG; -use crate::gpio; -use crate::hmac; -use crate::interrupts; -use crate::plic; -use crate::pwrmgr; -use crate::timer; -use crate::uart; -use crate::usbdev; - -PMPConfigMacro!(4); - -pub struct Matcha<A: 'static + Alarm<'static>> { - userspace_kernel_boundary: SysCall, - pmp: PMP, - scheduler_timer: kernel::VirtualSchedulerTimer<A>, -} - -impl<A: 'static + Alarm<'static>> Matcha<A> { - pub unsafe fn new(alarm: &'static A) -> Self { - Self { - userspace_kernel_boundary: SysCall::new(), - pmp: PMP::new(), - scheduler_timer: kernel::VirtualSchedulerTimer::new(alarm), - } - } - - pub unsafe fn enable_plic_interrupts(&self) { - plic::disable_all(); - plic::clear_all_pending(); - plic::enable_all(); - } - - unsafe fn handle_plic_interrupts(&self) { - while let Some(interrupt) = plic::next_pending() { - match interrupt { - interrupts::UART0_TX_WATERMARK..=interrupts::UART0_RX_PARITY_ERR => { - uart::UART0.handle_interrupt() - } - int_pin @ interrupts::GPIO_PIN0..=interrupts::GPIO_PIN31 => { - let pin = &gpio::PORT[(int_pin - interrupts::GPIO_PIN0) as usize]; - pin.handle_interrupt(); - } - interrupts::HMAC_HMAC_DONE..=interrupts::HMAC_HMAC_ERR => { - hmac::HMAC.handle_interrupt() - } - interrupts::USBDEV_PKT_RECEIVED..=interrupts::USBDEV_CONNECTED => { - usbdev::USB.handle_interrupt() - } - interrupts::PWRMGRWAKEUP => { - pwrmgr::PWRMGR.handle_interrupt(); - self.check_until_true_or_interrupt( - || pwrmgr::PWRMGR.check_clock_propagation(), - None, - ); - } - _ => debug!("Pidx {}", interrupt), - } - plic::complete(interrupt); - } - } - - /// Run a function in an interruptable loop. - /// - /// The function will run until it returns true, an interrupt occurs or if - /// `max_tries` is not `None` and that limit is reached. - /// If the function returns true this call will also return true. If an - /// interrupt occurs or `max_tries` is reached this call will return false. - fn check_until_true_or_interrupt<F>(&self, f: F, max_tries: Option<usize>) -> bool - where - F: Fn() -> bool, - { - match max_tries { - Some(t) => { - for _i in 0..t { - if self.has_pending_interrupts() { - return false; - } - if f() { - return true; - } - } - } - None => { - while !self.has_pending_interrupts() { - if f() { - return true; - } - } - } - } - - false - } -} - -impl<A: 'static + Alarm<'static>> kernel::Chip for Matcha<A> { - type MPU = PMP; - type UserspaceKernelBoundary = SysCall; - type SchedulerTimer = kernel::VirtualSchedulerTimer<A>; - type WatchDog = (); - - fn mpu(&self) -> &Self::MPU { - &self.pmp - } - - fn scheduler_timer(&self) -> &Self::SchedulerTimer { - &self.scheduler_timer - } - - fn watchdog(&self) -> &Self::WatchDog { - &() - } - - fn userspace_kernel_boundary(&self) -> &SysCall { - &self.userspace_kernel_boundary - } - - fn service_pending_interrupts(&self) { - loop { - let mip = CSR.mip.extract(); - - if mip.is_set(mip::mtimer) { - unsafe { - timer::TIMER.service_interrupt(); - } - } - if mip.is_set(mip::mext) { - unsafe { - self.handle_plic_interrupts(); - } - } - - if !mip.matches_any(mip::mext::SET + mip::mtimer::SET) { - break; - } - } - - // Re-enable all MIE interrupts that we care about. Since we looped - // until we handled them all, we can re-enable all of them. - CSR.mie.modify(mie::mext::SET + mie::mtimer::SET); - } - - fn has_pending_interrupts(&self) -> bool { - let mip = CSR.mip.extract(); - mip.matches_any(mip::mext::SET + mip::mtimer::SET) - } - - fn sleep(&self) { - unsafe { - pwrmgr::PWRMGR.enable_low_power(); - self.check_until_true_or_interrupt(|| pwrmgr::PWRMGR.check_clock_propagation(), None); - rv32i::support::wfi(); - } - } - - unsafe fn atomic<F, R>(&self, f: F) -> R - where - F: FnOnce() -> R, - { - rv32i::support::atomic(f) - } - - unsafe fn print_state(&self, writer: &mut dyn Write) { - let _ = writer.write_fmt(format_args!( - "\r\n---| Matcha configuration for {} |---", - CONFIG.name - )); - rv32i::print_riscv_state(writer); - } -} - -fn handle_exception(exception: mcause::Exception) { - match exception { - mcause::Exception::UserEnvCall | mcause::Exception::SupervisorEnvCall => (), - - mcause::Exception::InstructionMisaligned - | mcause::Exception::InstructionFault - | mcause::Exception::IllegalInstruction - | mcause::Exception::Breakpoint - | mcause::Exception::LoadMisaligned - | mcause::Exception::LoadFault - | mcause::Exception::StoreMisaligned - | mcause::Exception::StoreFault - | mcause::Exception::MachineEnvCall - | mcause::Exception::InstructionPageFault - | mcause::Exception::LoadPageFault - | mcause::Exception::StorePageFault - | mcause::Exception::Unknown => { - panic!("fatal exception"); - } - } -} - -unsafe fn handle_interrupt(intr: mcause::Interrupt) { - match intr { - mcause::Interrupt::UserSoft - | mcause::Interrupt::UserTimer - | mcause::Interrupt::UserExternal => { - panic!("unexpected user-mode interrupt"); - } - mcause::Interrupt::SupervisorExternal - | mcause::Interrupt::SupervisorTimer - | mcause::Interrupt::SupervisorSoft => { - panic!("unexpected supervisor-mode interrupt"); - } - - mcause::Interrupt::MachineSoft => { - CSR.mie.modify(mie::msoft::CLEAR); - } - mcause::Interrupt::MachineTimer => { - CSR.mie.modify(mie::mtimer::CLEAR); - } - mcause::Interrupt::MachineExternal => { - CSR.mie.modify(mie::mext::CLEAR); - } - - mcause::Interrupt::Unknown => { - panic!("interrupt of unknown cause"); - } - } -} - -/// Trap handler for board/chip specific code. -/// -/// For the Ibex this gets called when an interrupt occurs while the chip is -/// in kernel mode. All we need to do is check which interrupt occurred and -/// disable it. -#[export_name = "_start_trap_rust"] -pub unsafe extern "C" fn start_trap_rust() { - match mcause::Trap::from(CSR.mcause.extract()) { - mcause::Trap::Interrupt(interrupt) => { - handle_interrupt(interrupt); - } - mcause::Trap::Exception(exception) => { - handle_exception(exception); - } - } -} - -/// Function that gets called if an interrupt occurs while an app was running. -/// mcause is passed in, and this function should correctly handle disabling the -/// interrupt that fired so that it does not trigger again. -#[export_name = "_disable_interrupt_trap_handler"] -pub unsafe extern "C" fn disable_interrupt_trap_handler(mcause_val: u32) { - match mcause::Trap::from(mcause_val) { - mcause::Trap::Interrupt(interrupt) => { - handle_interrupt(interrupt); - } - _ => { - panic!("unexpected non-interrupt\n"); - } - } -} - -pub unsafe fn configure_trap_handler() { - // The Ibex CPU does not support non-vectored trap entries. - CSR.mtvec - .write(mtvec::trap_addr.val(_start_trap_vectored as u32 >> 2) + mtvec::mode::Vectored) -} - -// Mock implementation for crate tests that does not include the section -// specifier, as the test will not use our linker script, and the host -// compilation environment may not allow the section name. -#[cfg(not(any(target_arch = "riscv32", target_os = "none")))] -pub extern "C" fn _start_trap_vectored() { - unsafe { - unreachable_unchecked(); - } -} - -#[cfg(all(target_arch = "riscv32", target_os = "none"))] -#[link_section = ".riscv.trap_vectored"] -#[export_name = "_start_trap_vectored"] -#[naked] -pub extern "C" fn _start_trap_vectored() -> ! { - unsafe { - // According to the Ibex user manual: - // [NMI] has interrupt ID 31, i.e., it has the highest priority of all - // interrupts and the core jumps to the trap-handler base address (in - // mtvec) plus 0x7C to handle the NMI. - // - // Below are 32 (non-compressed) jumps to cover the entire possible - // range of vectored traps. - #[cfg(all(target_arch = "riscv32", target_os = "none"))] - llvm_asm!(" - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - j _start_trap - " - : - : - : - : "volatile"); - unreachable_unchecked() - } -}
diff --git a/chips/matcha/src/chip_config.rs b/chips/matcha/src/chip_config.rs deleted file mode 100644 index 9a26ff9..0000000 --- a/chips/matcha/src/chip_config.rs +++ /dev/null
@@ -1,46 +0,0 @@ -//! Chip specific configuration. -//! -//! This file includes configuration values for different implementations and -//! uses of the same matcha chip. For example, running the chip on an FPGA -//! requires different parameters from running it in a verilog simulator. -//! Additionally, chips on different platforms can be used differently, so this -//! also permits changing values like the UART baud rate to enable better -//! debugging on platforms that can support it. -//! -//! The configuration used is selected via Cargo features specified when the -//! board is compiled. - -/// Matcha configuration based on the target device. -pub struct Config<'a> { - /// Identifier for the platform. This is useful for debugging to confirm the - /// correct configuration of the chip is being used. - pub name: &'a str, - /// The clock speed of the CPU in Hz. - pub cpu_freq: u32, - /// The clock speed of the peripherals in Hz. - pub peripheral_freq: u32, - /// The baud rate for UART. This allows for a version of the chip that can - /// support a faster baud rate to use it to help with debugging. - pub uart_baudrate: u32, -} - -/// Config for running Matcha on an FPGA. Also the default configuration. -#[cfg(any( - feature = "config_fpga_nexysvideo", - not(feature = "config_disable_default") -))] -pub const CONFIG: Config = Config { - name: "fpga_nexysvideo", - cpu_freq: 10_000_000, - peripheral_freq: 2_500_000, - uart_baudrate: 115200, -}; - -/// Config for running Matcha in a verilog simulator. -#[cfg(feature = "config_sim_verilator")] -pub const CONFIG: Config = Config { - name: "sim_verilator", - cpu_freq: 500_000, - peripheral_freq: 125_000, - uart_baudrate: 9600, -};
diff --git a/chips/matcha/src/gpio.rs b/chips/matcha/src/gpio.rs deleted file mode 100644 index 03adf98..0000000 --- a/chips/matcha/src/gpio.rs +++ /dev/null
@@ -1,69 +0,0 @@ -//! GPIO instantiation. - -use core::ops::{Index, IndexMut}; - -use kernel::common::StaticRef; -pub use lowrisc::gpio::GpioPin; -use lowrisc::gpio::{pins, GpioRegisters}; -use lowrisc::padctrl::PadCtrlRegisters; - -const PADCTRL_BASE: StaticRef<PadCtrlRegisters> = - unsafe { StaticRef::new(0x4046_0000 as *const PadCtrlRegisters) }; - -const GPIO0_BASE: StaticRef<GpioRegisters> = - unsafe { StaticRef::new(0x4004_0000 as *const GpioRegisters) }; - -pub struct Port<'a> { - pins: [GpioPin<'a>; 32], -} - -impl<'a> Index<usize> for Port<'a> { - type Output = GpioPin<'a>; - - fn index(&self, index: usize) -> &GpioPin<'a> { - &self.pins[index] - } -} - -impl<'a> IndexMut<usize> for Port<'a> { - fn index_mut(&mut self, index: usize) -> &mut GpioPin<'a> { - &mut self.pins[index] - } -} - -pub static mut PORT: Port = Port { - pins: [ - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin0), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin1), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin2), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin3), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin4), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin5), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin6), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin7), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin8), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin9), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin10), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin11), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin12), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin13), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin14), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin15), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin16), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin17), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin18), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin19), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin20), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin21), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin22), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin23), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin24), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin25), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin26), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin27), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin28), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin29), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin30), - GpioPin::new(GPIO0_BASE, PADCTRL_BASE, pins::pin31), - ], -};
diff --git a/chips/matcha/src/hmac.rs b/chips/matcha/src/hmac.rs deleted file mode 100644 index 182ed53..0000000 --- a/chips/matcha/src/hmac.rs +++ /dev/null
@@ -1,7 +0,0 @@ -use kernel::common::StaticRef; -use lowrisc::hmac::{Hmac, HmacRegisters}; - -pub static mut HMAC: Hmac = Hmac::new(HMAC0_BASE); - -const HMAC0_BASE: StaticRef<HmacRegisters> = - unsafe { StaticRef::new(0x4111_0000 as *const HmacRegisters) };
diff --git a/chips/matcha/src/i2c.rs b/chips/matcha/src/i2c.rs deleted file mode 100644 index 4cc7332..0000000 --- a/chips/matcha/src/i2c.rs +++ /dev/null
@@ -1,9 +0,0 @@ -use crate::chip_config::CONFIG; -use kernel::common::StaticRef; -use lowrisc::i2c::{I2c, I2cRegisters}; - -pub static mut I2C: I2c = I2c::new(I2C_BASE, (1 / CONFIG.cpu_freq) * 1000 * 1000); - -// This is a placeholder address as the I2C MMIO interface isn't avaliable yet -const I2C_BASE: StaticRef<I2cRegisters> = - unsafe { StaticRef::new(0x4008_0000 as *const I2cRegisters) };
diff --git a/chips/matcha/src/interrupts.rs b/chips/matcha/src/interrupts.rs deleted file mode 100644 index d503127..0000000 --- a/chips/matcha/src/interrupts.rs +++ /dev/null
@@ -1,210 +0,0 @@ -//! Named interrupts for the Matcha chip. - -#![allow(dead_code)] - -pub const PWRMGRWAKEUP: u32 = 0x50; - -pub const NO_INTERRUPT: u32 = 0; - -pub const UART0_TX_WATERMARK: u32 = 1; -pub const UART0_RX_WATERMARK: u32 = 2; -pub const UART0_TX_EMPTY: u32 = 3; -pub const UART0_RX_OVERFLOW: u32 = 4; -pub const UART0_RX_FRAME_ERR: u32 = 5; -pub const UART0_RX_BREAK_ERR: u32 = 6; -pub const UART0_RX_TIMEOUT: u32 = 7; -pub const UART0_RX_PARITY_ERR: u32 = 8; - -pub const UART1_TX_WATERMARK: u32 = 9; -pub const UART1_RX_WATERMARK: u32 = 10; -pub const UART1_TX_EMPTY: u32 = 11; -pub const UART1_RX_OVERFLOW: u32 = 12; -pub const UART1_RX_FRAME_ERR: u32 = 13; -pub const UART1_RX_BREAK_ERR: u32 = 14; -pub const UART1_RX_TIMEOUT: u32 = 15; -pub const UART1_RX_PARITY_ERR: u32 = 16; - -pub const UART2_TX_WATERMARK: u32 = 17; -pub const UART2_RX_WATERMARK: u32 = 18; -pub const UART2_TX_EMPTY: u32 = 19; -pub const UART2_RX_OVERFLOW: u32 = 20; -pub const UART2_RX_FRAME_ERR: u32 = 21; -pub const UART2_RX_BREAK_ERR: u32 = 22; -pub const UART2_RX_TIMEOUT: u32 = 23; -pub const UART2_RX_PARITY_ERR: u32 = 24; - -pub const UART3_TX_WATERMARK: u32 = 25; -pub const UART3_RX_WATERMARK: u32 = 26; -pub const UART3_TX_EMPTY: u32 = 27; -pub const UART3_RX_OVERFLOW: u32 = 28; -pub const UART3_RX_FRAME_ERR: u32 = 29; -pub const UART3_RX_BREAK_ERR: u32 = 30; -pub const UART3_RX_TIMEOUT: u32 = 31; -pub const UART3_RX_PARITY_ERR: u32 = 32; - -pub const GPIO_PIN0: u32 = 33; -pub const GPIO_PIN1: u32 = 34; -pub const GPIO_PIN2: u32 = 35; -pub const GPIO_PIN3: u32 = 36; -pub const GPIO_PIN4: u32 = 37; -pub const GPIO_PIN5: u32 = 38; -pub const GPIO_PIN6: u32 = 39; -pub const GPIO_PIN7: u32 = 40; -pub const GPIO_PIN8: u32 = 41; -pub const GPIO_PIN9: u32 = 42; -pub const GPIO_PIN10: u32 = 43; -pub const GPIO_PIN11: u32 = 44; -pub const GPIO_PIN12: u32 = 45; -pub const GPIO_PIN13: u32 = 46; -pub const GPIO_PIN14: u32 = 47; -pub const GPIO_PIN15: u32 = 48; -pub const GPIO_PIN16: u32 = 49; -pub const GPIO_PIN17: u32 = 50; -pub const GPIO_PIN18: u32 = 51; -pub const GPIO_PIN19: u32 = 52; -pub const GPIO_PIN20: u32 = 53; -pub const GPIO_PIN21: u32 = 54; -pub const GPIO_PIN22: u32 = 55; -pub const GPIO_PIN23: u32 = 56; -pub const GPIO_PIN24: u32 = 57; -pub const GPIO_PIN25: u32 = 58; -pub const GPIO_PIN26: u32 = 59; -pub const GPIO_PIN27: u32 = 60; -pub const GPIO_PIN28: u32 = 61; -pub const GPIO_PIN29: u32 = 62; -pub const GPIO_PIN30: u32 = 63; -pub const GPIO_PIN31: u32 = 64; - -pub const SPI_DEVICE_RXF: u32 = 65; -pub const SPI_DEVICE_RXLVL: u32 = 66; -pub const SPI_DEVICE_TXLVL: u32 = 67; -pub const SPI_DEVICE_RXERR: u32 = 68; -pub const SPI_DEVICE_RXOVERFLOW: u32 = 69; -pub const SPI_DEVICE_TXUNDERFLOW: u32 = 70; - - -pub const SPI_HOST0_ERROR: u32 = 71; -pub const SPI_HOST0_SPIEVENT: u32 = 72; -pub const SPI_HOST1_ERROR: u32 = 73; -pub const SPI_HOST1_SPIEVENT: u32 = 74; - -pub const I2C0_FMT_WATERMARK: u32 = 75; -pub const I2C0_RX_WATERMARK: u32 = 76; -pub const I2C0_FMT_OVERFLOW: u32 = 77; -pub const I2C0_RX_OVERFLOW: u32 = 78; -pub const I2C0_NAK: u32 = 79; -pub const I2C0_SCL_INTERFERENCE: u32 = 80; -pub const I2C0_SDA_INTERFERENCE: u32 = 81; -pub const I2C0_STRETCH_TIMEOUT: u32 = 82; -pub const I2C0_SDA_UNSTABLE: u32 = 83; -pub const I2C0_TRANS_COMPLETE: u32 = 84; -pub const I2C0_TX_EMPTY: u32 = 85; -pub const I2C0_TX_NONEMPTY: u32 = 86; -pub const I2C0_TX_OVERFLOW: u32 = 87; -pub const I2C0_ACQ_OVERFLOW: u32 = 88; -pub const I2C0_ACK_STOP: u32 = 89; -pub const I2C0_HOST_TIMEOUT: u32 = 90; - -pub const I2C1_FMT_WATERMARK: u32 = 91; -pub const I2C1_RX_WATERMARK: u32 = 92; -pub const I2C1_FMT_OVERFLOW: u32 = 93; -pub const I2C1_RX_OVERFLOW: u32 = 94; -pub const I2C1_NAK: u32 = 95; -pub const I2C1_SCL_INTERFERENCE: u32 = 96; -pub const I2C1_SDA_INTERFERENCE: u32 = 97; -pub const I2C1_STRETCH_TIMEOUT: u32 = 98; -pub const I2C1_SDA_UNSTABLE: u32 = 99; -pub const I2C1_TRANS_COMPLETE: u32 = 100; -pub const I2C1_TX_EMPTY: u32 = 101; -pub const I2C1_TX_NONEMPTY: u32 = 102; -pub const I2C1_TX_OVERFLOW: u32 = 103; -pub const I2C1_ACQ_OVERFLOW: u32 = 104; -pub const I2C1_ACK_STOP: u32 = 105; -pub const I2C1_HOST_TIMEOUT: u32 = 106; - -pub const I2C2_FMT_WATERMARK: u32 = 107; -pub const I2C2_RX_WATERMARK: u32 = 108; -pub const I2C2_FMT_OVERFLOW: u32 = 109; -pub const I2C2_RX_OVERFLOW: u32 = 110; -pub const I2C2_NAK: u32 = 111; -pub const I2C2_SCL_INTERFERENCE: u32 = 112; -pub const I2C2_SDA_INTERFERENCE: u32 = 113; -pub const I2C2_STRETCH_TIMEOUT: u32 = 114; -pub const I2C2_SDA_UNSTABLE: u32 = 115; -pub const I2C2_TRANS_COMPLETE: u32 = 116; -pub const I2C2_TX_EMPTY: u32 = 117; -pub const I2C2_TX_NONEMPTY: u32 = 118; -pub const I2C2_TX_OVERFLOW: u32 = 119; -pub const I2C2_ACQ_OVERFLOW: u32 = 120; -pub const I2C2_ACK_STOP: u32 = 121; -pub const I2C2_HOST_TIMEOUT: u32 = 122; - -pub const PATTGEN_DONE_CH0: u32 = 123; -pub const PATTGEN_DONE_CH1: u32 = 124; - -pub const RV_TIMER_EXPIRED0_0: u32 = 125; - -pub const USBDEV_PKT_RECEIVED: u32 = 126; -pub const USBDEV_PKT_SENT: u32 = 127; -pub const USBDEV_DISCONNECTED: u32 = 128; -pub const USBDEV_HOST_LOST: u32 = 129; -pub const USBDEV_LINK_RESET: u32 = 130; -pub const USBDEV_LINK_SUSPEND: u32 = 131; -pub const USBDEV_LINK_RESUME: u32 = 132; -pub const USBDEV_AV_EMPTY: u32 = 133; -pub const USBDEV_RX_FULL: u32 = 134; -pub const USBDEV_AV_OVERFLOW: u32 = 135; -pub const USBDEV_LINK_IN_ERR: u32 = 136; -pub const USBDEV_RX_CRC_ERR: u32 = 137; -pub const USBDEV_RX_PID_ERR: u32 = 138; -pub const USBDEV_RX_BITSTUFF_ERR: u32 = 139; -pub const USBDEV_FRAME: u32 = 140; -pub const USBDEV_CONNECTED: u32 = 141; -pub const USBDEV_LINK_OUT_ERR: u32 = 142; - -pub const OTP_CTRL_OTP_OPERATION_DONE: u32 = 143; -pub const OTP_CTRL_OTP_ERR: u32 = 144; - -pub const ALERT_CLASSA: u32 = 145; -pub const ALERT_CLASSB: u32 = 146; -pub const ALERT_CLASSC: u32 = 147; -pub const ALERT_CLASSD: u32 = 148; - -pub const PWRMGR_AON_WAKEUP: u32 = 149; - -pub const ADC_CTRL_AON_DEBUG_CABLE: u32 = 150; - -pub const AON_TIMER_AON_WAKEUP_TIMER_EXPIRED: u32 = 151; -pub const AON_TIMER_AON_WATCHDOG_EXPIRED: u32 = 152; - -pub const FLASH_PROG_EMPTY: u32 = 153; -pub const FLASH_PROG_LVL: u32 = 154; -pub const FLASH_RD_FULL: u32 = 155; -pub const FLASH_RD_LVL: u32 = 156; -pub const FLASH_OP_DONE: u32 = 157; - -pub const HMAC_HMAC_DONE: u32 = 158; -pub const HMAC_FIFO_EMPTY: u32 = 159; -pub const HMAC_HMAC_ERR: u32 = 160; - -pub const KMAC_KMAC_DONE: u32 = 161; -pub const KMAC_FIFO_EMPTY: u32 = 162; -pub const KMAC_KMAC_ERR: u32 = 163; - -pub const KEYMGR_OP_DONE: u32 = 164; - -pub const CSRNG_CS_CMD_REQ_DONE: u32 = 165; -pub const CSRNG_CS_ENTROPY_REQ: u32 = 166; -pub const CSRNG_CS_HW_INST_EXC: u32 = 167; -pub const CSRNG_CS_FATAL_ERR: u32 = 168; -pub const ENTROPY_SRC_ES_ENTROPY_VALID: u32 = 169; -pub const ENTROPY_SRC_ES_HEALTH_TEST_FAILED: u32 = 170; -pub const ENTROPY_SRC_ES_FATAL_ERR: u32 = 171; - -pub const EDN0_EDN_CMD_REQ_DONE: u32 = 172; -pub const EDN0_EDN_FATAL_ERR: u32 = 173; - -pub const EDN1_EDN_CMD_REQ_DONE: u32 = 174; -pub const EDN1_EDN_FATAL_ERR: u32 = 175; - -pub const OTBN_DONE: u32 = 176; \ No newline at end of file
diff --git a/chips/matcha/src/lib.rs b/chips/matcha/src/lib.rs deleted file mode 100644 index 234c235..0000000 --- a/chips/matcha/src/lib.rs +++ /dev/null
@@ -1,20 +0,0 @@ -//! Drivers and chip support for Matcha. - -#![feature(llvm_asm, const_fn, naked_functions)] -#![no_std] -#![crate_name = "matcha"] -#![crate_type = "rlib"] - -mod chip_config; -mod interrupts; - -pub mod aes; -pub mod chip; -pub mod gpio; -pub mod hmac; -pub mod i2c; -pub mod plic; -pub mod pwrmgr; -pub mod timer; -pub mod uart; -pub mod usbdev;
diff --git a/chips/matcha/src/plic.rs b/chips/matcha/src/plic.rs deleted file mode 100644 index be80568..0000000 --- a/chips/matcha/src/plic.rs +++ /dev/null
@@ -1,103 +0,0 @@ -//! Platform Level Interrupt Control peripheral driver. - -use kernel::common::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite}; -use kernel::common::StaticRef; -//use kernel::debug; - -register_structs! { - pub PlicRegisters { - /// Interrupt Pending Register - (0x000 => pending: [ReadOnly<u32>; 3]), - /// Interrupt Source Register - (0x00C => source: [ReadWrite<u32>; 3]), - /// Interrupt Priority Registers - (0x018 => priority: [ReadWrite<u32, priority::Register>; 79]), - (0x154 => _reserved0: [ReadWrite<u32>; 43]), - /// Interrupt Enable Register - (0x200 => enable: [ReadWrite<u32>; 3]), - /// Priority Threshold Register - (0x20C => threshold: ReadWrite<u32, priority::Register>), - /// Claim/Complete Register - (0x210 => claim: ReadWrite<u32>), - /// MSIP Register - (0x214 => msip: ReadWrite<u32>), - (0x218 => @END), - } -} - -register_bitfields![u32, - priority [ - Priority OFFSET(0) NUMBITS(3) [] - ] -]; - -const PLIC_BASE: StaticRef<PlicRegisters> = - unsafe { StaticRef::new(0x4101_0000 as *const PlicRegisters) }; - -/// Clear all pending interrupts. -pub unsafe fn clear_all_pending() { - let _plic: &PlicRegisters = &*PLIC_BASE; -} - -/// Enable all interrupts. -pub unsafe fn enable_all() { - let plic: &PlicRegisters = &*PLIC_BASE; - - // USB hardware on current OT master branch seems to have - // interrupt bugs: running Alarms causes persistent USB - // CONNECTED interrupts that can't be masked from USBDEV and - // cause the system to hang. So enable all interrupts except - // for the USB ones. Some open PRs on OT fix this, we'll re-enable - // USB interrurupts. - // - // https://github.com/lowRISC/opentitan/issues/3388 - plic.enable[0].set(0xFFFF_FFFF); - plic.enable[1].set(0xFFFF_FFFF); - plic.enable[2].set(0xFFFF_0000); // USB are 64-79 - - // Set the max priority for each interrupt. This is not really used - // at this point. - for priority in plic.priority.iter() { - priority.write(priority::Priority.val(3)); - } - - // Accept all interrupts. - plic.threshold.write(priority::Priority.val(1)); -} - -/// Disable all interrupts. -pub unsafe fn disable_all() { - let plic: &PlicRegisters = &*PLIC_BASE; - for enable in plic.enable.iter() { - enable.set(0); - } -} - -/// Get the index (0-256) of the lowest number pending interrupt, or `None` if -/// none is pending. RISC-V PLIC has a "claim" register which makes it easy -/// to grab the highest priority pending interrupt. -pub unsafe fn next_pending() -> Option<u32> { - let plic: &PlicRegisters = &*PLIC_BASE; - - let claim = plic.claim.get(); - if claim == 0 { - None - } else { - Some(claim) - } -} - -/// Signal that an interrupt is finished being handled. In Tock, this should be -/// called from the normal main loop (not the interrupt handler). -pub unsafe fn complete(index: u32) { - let plic: &PlicRegisters = &*PLIC_BASE; - plic.claim.set(index); -} - -/// Return `true` if there are any pending interrupts in the PLIC, `false` -/// otherwise. -pub unsafe fn has_pending() -> bool { - let plic: &PlicRegisters = &*PLIC_BASE; - - plic.pending.iter().fold(0, |i, pending| pending.get() | i) != 0 -}
diff --git a/chips/matcha/src/pwrmgr.rs b/chips/matcha/src/pwrmgr.rs deleted file mode 100644 index 23db221..0000000 --- a/chips/matcha/src/pwrmgr.rs +++ /dev/null
@@ -1,7 +0,0 @@ -use kernel::common::StaticRef; -use lowrisc::pwrmgr::{PwrMgr, PwrMgrRegisters}; - -pub static mut PWRMGR: PwrMgr = PwrMgr::new(PWRMGR_BASE); - -const PWRMGR_BASE: StaticRef<PwrMgrRegisters> = - unsafe { StaticRef::new(0x4040_0000 as *const PwrMgrRegisters) };
diff --git a/chips/matcha/src/timer.rs b/chips/matcha/src/timer.rs deleted file mode 100644 index 3c2e09e..0000000 --- a/chips/matcha/src/timer.rs +++ /dev/null
@@ -1,198 +0,0 @@ -//! Timer driver. - -use crate::chip_config::CONFIG; -use kernel::common::cells::OptionalCell; -use kernel::common::registers::{register_bitfields, register_structs, ReadWrite, WriteOnly}; -use kernel::common::StaticRef; -use kernel::hil::time; -use kernel::hil::time::{Ticks, Ticks64, Time}; -use kernel::ReturnCode; - -const PRESCALE: u16 = ((CONFIG.cpu_freq / 10_000) - 1) as u16; // 10Khz - -/// 10KHz `Frequency` -#[derive(Debug)] -pub struct Freq10KHz; -impl time::Frequency for Freq10KHz { - fn frequency() -> u32 { - 10_000 - } -} - -register_structs! { - pub TimerRegisters { - (0x000 => ctrl: ReadWrite<u32, ctrl::Register>), - - (0x004 => _reserved), - - (0x100 => config: ReadWrite<u32, config::Register>), - - (0x104 => value_low: ReadWrite<u32>), - (0x108 => value_high: ReadWrite<u32>), - - (0x10c => compare_low: ReadWrite<u32>), - (0x110 => compare_high: ReadWrite<u32>), - - (0x114 => intr_enable: ReadWrite<u32, intr::Register>), - (0x118 => intr_state: ReadWrite<u32, intr::Register>), - (0x11c => intr_test: WriteOnly<u32, intr::Register>), - (0x120 => @END), - } -} - -register_bitfields![u32, - ctrl [ - enable OFFSET(0) NUMBITS(1) [] - ], - config [ - prescale OFFSET(0) NUMBITS(12) [], - step OFFSET(16) NUMBITS(8) [] - ], - intr [ - timer0 OFFSET(0) NUMBITS(1) [] - ] -]; - -pub struct RvTimer<'a> { - registers: StaticRef<TimerRegisters>, - alarm_client: OptionalCell<&'a dyn time::AlarmClient>, - overflow_client: OptionalCell<&'a dyn time::OverflowClient>, -} - -impl<'a> RvTimer<'a> { - const fn new(base: StaticRef<TimerRegisters>) -> RvTimer<'a> { - RvTimer { - registers: base, - alarm_client: OptionalCell::empty(), - overflow_client: OptionalCell::empty(), - } - } - - pub fn setup(&self) { - let regs = self.registers; - // Set proper prescaler and the like - regs.config - .write(config::prescale.val(PRESCALE as u32) + config::step.val(1u32)); - regs.compare_high.set(0); - regs.value_low.set(0xFFFF_0000); - regs.intr_enable.write(intr::timer0::CLEAR); - regs.ctrl.write(ctrl::enable::SET); - } - - pub fn service_interrupt(&self) { - let regs = self.registers; - regs.intr_enable.write(intr::timer0::CLEAR); - regs.intr_state.write(intr::timer0::SET); - self.alarm_client.map(|client| { - client.alarm(); - }); - } -} - -impl time::Time for RvTimer<'_> { - type Frequency = Freq10KHz; - type Ticks = Ticks64; - - fn now(&self) -> Ticks64 { - // RISC-V has a 64-bit counter but you can only read 32 bits - // at once, which creates a race condition if the lower register - // wraps between the reads. So the recommended approach is to read - // low, read high, read low, and if the second low is lower, re-read - // high. -pal 8/6/20 - let first_low: u32 = self.registers.value_low.get(); - let mut high: u32 = self.registers.value_high.get(); - let second_low: u32 = self.registers.value_low.get(); - if second_low < first_low { - // Wraparound - high = self.registers.value_high.get(); - } - Ticks64::from(((high as u64) << 32) | second_low as u64) - } -} - -impl<'a> time::Counter<'a> for RvTimer<'a> { - fn set_overflow_client(&'a self, client: &'a dyn time::OverflowClient) { - self.overflow_client.set(client); - } - - fn start(&self) -> ReturnCode { - ReturnCode::SUCCESS - } - - fn stop(&self) -> ReturnCode { - // RISCV counter can't be stopped... - ReturnCode::EBUSY - } - - fn reset(&self) -> ReturnCode { - // RISCV counter can't be reset - ReturnCode::FAIL - } - - fn is_running(&self) -> bool { - true - } -} - -impl<'a> time::Alarm<'a> for RvTimer<'a> { - fn set_alarm_client(&self, client: &'a dyn time::AlarmClient) { - self.alarm_client.set(client); - } - - fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) { - // This does not handle the 64-bit wraparound case. - // Because mtimer fires if the counter is >= the compare, - // handling wraparound requires setting compare to the - // maximum value, issuing a callback on the overflow client - // if there is one, spinning until it wraps around to 0, then - // setting the compare to the correct value. - let regs = self.registers; - let now = self.now(); - let mut expire = reference.wrapping_add(dt); - - if !now.within_range(reference, expire) { - expire = now; - } - - let val = expire.into_u64(); - let high = (val >> 32) as u32; - let low = (val & 0xffffffff) as u32; - - // Recommended approach for setting the two compare registers - // (RISC-V Privileged Architectures 3.1.15) -pal 8/6/20 - regs.compare_low.set(0xffffffff); - regs.compare_high.set(high); - regs.compare_low.set(low); - //debug!("TIMER: set to {}", expire.into_u64()); - self.registers.intr_enable.write(intr::timer0::SET); - } - - fn get_alarm(&self) -> Self::Ticks { - let mut val: u64 = (self.registers.compare_high.get() as u64) << 32; - val |= self.registers.compare_low.get() as u64; - Ticks64::from(val) - } - - fn disarm(&self) -> ReturnCode { - // You clear the RISCV mtime interrupt by writing to the compare - // registers. Since the only way to do so is to set a new alarm, - // and this is also the only way to re-enable the interrupt, disabling - // the interrupt is sufficient. Calling set_alarm will clear the - // pending interrupt before re-enabling. -pal 8/6/20 - self.registers.intr_enable.write(intr::timer0::CLEAR); - ReturnCode::SUCCESS - } - - fn is_armed(&self) -> bool { - self.registers.intr_enable.is_set(intr::timer0) - } - - fn minimum_dt(&self) -> Self::Ticks { - Self::Ticks::from(1 as u64) - } -} - -const TIMER_BASE: StaticRef<TimerRegisters> = - unsafe { StaticRef::new(0x4010_0000 as *const TimerRegisters) }; - -pub static mut TIMER: RvTimer = RvTimer::new(TIMER_BASE);
diff --git a/chips/matcha/src/uart.rs b/chips/matcha/src/uart.rs deleted file mode 100644 index 63d9b72..0000000 --- a/chips/matcha/src/uart.rs +++ /dev/null
@@ -1,10 +0,0 @@ -use crate::chip_config::CONFIG; -use kernel::common::StaticRef; -use lowrisc::uart::{Uart, UartRegisters}; - -pub const UART0_BAUDRATE: u32 = CONFIG.uart_baudrate; - -pub static mut UART0: Uart = Uart::new(UART0_BASE, CONFIG.peripheral_freq); - -const UART0_BASE: StaticRef<UartRegisters> = - unsafe { StaticRef::new(0x4000_0000 as *const UartRegisters) };
diff --git a/chips/matcha/src/usbdev.rs b/chips/matcha/src/usbdev.rs deleted file mode 100644 index aa70c29..0000000 --- a/chips/matcha/src/usbdev.rs +++ /dev/null
@@ -1,7 +0,0 @@ -use kernel::common::StaticRef; -use lowrisc::usbdev::{Usb, UsbRegisters}; - -pub static mut USB: Usb = Usb::new(USB0_BASE); - -const USB0_BASE: StaticRef<UsbRegisters> = - unsafe { StaticRef::new(0x4011_0000 as *const UsbRegisters) };
diff --git a/layout_generic.ld b/layout_generic.ld new file mode 100644 index 0000000..3a77ad7 --- /dev/null +++ b/layout_generic.ld
@@ -0,0 +1,158 @@ +/* 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. + */ + /* 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`: + * + * 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); + + *(.start) + } > FLASH =0xFF + + /* Text section, Code! */ + .text : + { + . = ALIGN(4); + _text = .; + *(.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 + + /* Sections we do not need. */ + /DISCARD/ : + { + *(.ARM.exidx .eh_frame) + } +} + +ASSERT((_stack_top_aligned - _stack_top_unaligned) == 0, " +STACK_SIZE must be 8 byte multiple")
diff --git a/layout_matcha.ld b/layout_matcha.ld new file mode 100644 index 0000000..096b5a4 --- /dev/null +++ b/layout_matcha.ld
@@ -0,0 +1,18 @@ +/* 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 + * the kernel binary, check for the actual address of APP_MEMORY! + */ + FLASH (rx) : ORIGIN = 0x20800040, LENGTH = 0x800000 - 0x40 + SRAM (rwx) : ORIGIN = 0x10800000, LENGTH = 0x800000 +} + +MPU_MIN_ALIGN = 1K; + +INCLUDE layout_generic.ld
diff --git a/rust-toolchain b/rust-toolchain index b18a3f3..a563102 100644 --- a/rust-toolchain +++ b/rust-toolchain
@@ -1 +1,6 @@ -nightly-2020-06-03 +[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-2021-03-25" +components = ["clippy", "miri", "rustfmt"] +targets = ["riscv32imc-unknown-none-elf"]
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..75c75d9 --- /dev/null +++ b/src/main.rs
@@ -0,0 +1,14 @@ +#![no_std] + +use libtock::println; +use libtock::result::TockResult; + +libtock_core::stack_size! {0x1000} + +#[libtock::main] +async fn main() -> TockResult<()> { + let drivers = libtock::retrieve_drivers()?; + drivers.console.create_console(); + println!("Hello Tock World from shodan/sw/matcha/src/main.rs!"); + Ok(()) +} \ No newline at end of file