From b2f5da7184de638d557b3d5cc0ada164247ff6a8 Mon Sep 17 00:00:00 2001 From: Andre Richter Date: Tue, 3 Apr 2018 22:45:21 +0200 Subject: [PATCH] Add tutorial 02_multicore_rust --- .02_multicorec/Makefile | 43 --- .02_multicorec/OLVASSEL.md | 36 --- .02_multicorec/README.md | 34 --- .02_multicorec/kernel8.img | Bin 84 -> 0 bytes .02_multicorec/main.c | 29 --- 02_multicore_rust/Cargo.lock | 11 + 02_multicore_rust/Cargo.toml | 7 + 02_multicore_rust/Makefile | 61 +++++ 02_multicore_rust/README.md | 75 ++++++ .../aarch64-raspi3-none-elf.json | 24 ++ 02_multicore_rust/dockcross-linux-aarch64 | 246 ++++++++++++++++++ 02_multicore_rust/kernel8.img | Bin 0 -> 152 bytes {.02_multicorec => 02_multicore_rust}/link.ld | 0 02_multicore_rust/raspi3_glue/Cargo.toml | 6 + .../raspi3_glue/src/boot_cores.S | 19 +- 02_multicore_rust/raspi3_glue/src/lib.rs | 88 +++++++ 02_multicore_rust/src/main.rs | 31 +++ 17 files changed, 555 insertions(+), 155 deletions(-) delete mode 100644 .02_multicorec/Makefile delete mode 100644 .02_multicorec/OLVASSEL.md delete mode 100644 .02_multicorec/README.md delete mode 100755 .02_multicorec/kernel8.img delete mode 100644 .02_multicorec/main.c create mode 100644 02_multicore_rust/Cargo.lock create mode 100644 02_multicore_rust/Cargo.toml create mode 100644 02_multicore_rust/Makefile create mode 100644 02_multicore_rust/README.md create mode 100644 02_multicore_rust/aarch64-raspi3-none-elf.json create mode 100755 02_multicore_rust/dockcross-linux-aarch64 create mode 100755 02_multicore_rust/kernel8.img rename {.02_multicorec => 02_multicore_rust}/link.ld (100%) create mode 100644 02_multicore_rust/raspi3_glue/Cargo.toml rename .02_multicorec/start.S => 02_multicore_rust/raspi3_glue/src/boot_cores.S (84%) create mode 100644 02_multicore_rust/raspi3_glue/src/lib.rs create mode 100644 02_multicore_rust/src/main.rs diff --git a/.02_multicorec/Makefile b/.02_multicorec/Makefile deleted file mode 100644 index f6ba7559..00000000 --- a/.02_multicorec/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright (C) 2018 bzt (bztsrc@github) -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, copy, -# modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. -# -# - -SRCS = $(wildcard *.c) -OBJS = $(SRCS:.c=.o) -CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles - -all: clean kernel8.img - -start.o: start.S - aarch64-elf-gcc $(CFLAGS) -c start.S -o start.o - -%.o: %.c - aarch64-elf-gcc $(CFLAGS) -c $< -o $@ - -kernel8.img: start.o $(OBJS) - aarch64-elf-ld -nostdlib -nostartfiles start.o $(OBJS) -T link.ld -o kernel8.elf - aarch64-elf-objcopy -O binary kernel8.elf kernel8.img - -clean: - rm kernel8.elf *.o >/dev/null 2>/dev/null || true diff --git a/.02_multicorec/OLVASSEL.md b/.02_multicorec/OLVASSEL.md deleted file mode 100644 index 19ba0113..00000000 --- a/.02_multicorec/OLVASSEL.md +++ /dev/null @@ -1,36 +0,0 @@ -Oktatóanyag 02 - Többmagos C -============================ - -Próbáljunk valami összetettebbet, mit szóltok? Összetettebb alatt azt értem, hogy most is megállítjuk a CPU magokat, -akárcsak az első oktatóanyagban, de most az egyik magot C-ből! - -Start ------ - -Most már meg kell különböztetnünk a magokat. Ehhez kiolvassuk a *mpidr_el1* rendszer regisztert. Ha nem nulla, akkor -a korábbi végtelen ciklus következik. Ha nulla, akkor meg fogunk hívni egy C eljárást. De ehhez előbb be állítanunk -egy megfelelő vermet, ki kell nulláznunk a bss szegmenst mielőtt kiadhatnánk az ugrás parancsot. Hozzáadtam néhány -Assembly sort, amik mindezt elvégzik. Arra az esetre, ha a C eljárás visszatérne (nem szabadna), ugyanarra a -végtelen ciklusra ugrunk, mint amit a többi CPU mag is épp végrehajt. - -Makefile --------- - -Egy kisit trükkösebb lett. Hozzáadtam parancsokat a C fordításhoz, de akkor már általánosan. Mostantól ugyanazt -a Makefile-t használhatjuk minden oktatóanyaghoz, függetlenül attól, hány C forrásfájlunk van, és a továbbiakban -nem is szerepeltetem. - -Linker script -------------- - -Hasonlóan, a linker szkript is bonyolultabbá vált, mivel a C-hez adat és bss szekciókra is szükség van. Hozzáadtam -továbbá egy számolást a bss szegmens méretének megállapítására, így egyszerűen hivatkozhatunk rá Assembly-ben, és -nem kell ott molyolni vele. - -Fontos, hogy a text szegmens az Assembly kóddal kezdődjön, mivel ez elé raktuk a vermet, ezért kell a KEEP(). -Íly módon mind a betöltési címünk 0x80000, akárcsak a `_start` cimke címe és a verem teteje. - -Main ----- - -Végezetül, az első C kódunk. Csak egy végtelen ciklus, de akkor is! :-) diff --git a/.02_multicorec/README.md b/.02_multicorec/README.md deleted file mode 100644 index 67315da0..00000000 --- a/.02_multicorec/README.md +++ /dev/null @@ -1,34 +0,0 @@ -Tutorial 02 - Multicore C -========================= - -Now let's try something more complex, shall we? By complex I mean stop the CPU cores just like in the first tutorial, -but this time stop one of them from C! - -Start ------ - -Now we have to distinguish the cores. For that, we read the *mpidr_el1* system register. If it's not zero, we'll -do the former infinite loop. If it's zero, then we'll call a C function. But for that, we need a proper stack, and a -zerod out bss segment in memory before the call instruction. I've added some more code to the Assembly to do all of -that. In case the C code returns (shouldn't), we also jump to the same infinite loop the other CPU cores running. - -Makefile --------- - -It became a bit trickier. I've added commands for compiling C sources, but in a comform way. From now on, we -can use the same Makefile for every tutorial, regardless of the number of C sources, and I won't discuss it any -further. - -Linker script -------------- - -Likewise, the linker script became more complex too, as C needs data and bss sections. I've also added a calculation -for the bss size, so that we can refer to it from the Assembly without any further hassle. - -It is important to start the text segment with the Assembly code, because we set the stack right before it, hence -the KEEP(). This way our load address is 0x80000, the same as `_start` label and stack top. - -Main ----- - -Finaly, our first C code. Just an empty loop, but still! :-) diff --git a/.02_multicorec/kernel8.img b/.02_multicorec/kernel8.img deleted file mode 100755 index 93185e1f73068e3547fe434844bf6a70dbdd0ad3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84 zcmZ3;U~yHE#bHt+1H+bh1?H>&|Nj?HWMqi2XJD8Jq8~9ZNHj4pnAo>4{BUAn2we34 ZzbQKd!<4T;bqrv@0VWd|AT*F80svHg6>0zg diff --git a/.02_multicorec/main.c b/.02_multicorec/main.c deleted file mode 100644 index e7d114bd..00000000 --- a/.02_multicorec/main.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2018 bzt (bztsrc@github) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -void main() -{ - while(1); -} diff --git a/02_multicore_rust/Cargo.lock b/02_multicore_rust/Cargo.lock new file mode 100644 index 00000000..32f2dd58 --- /dev/null +++ b/02_multicore_rust/Cargo.lock @@ -0,0 +1,11 @@ +[[package]] +name = "kernel8" +version = "0.1.0" +dependencies = [ + "raspi3_glue 0.1.0", +] + +[[package]] +name = "raspi3_glue" +version = "0.1.0" + diff --git a/02_multicore_rust/Cargo.toml b/02_multicore_rust/Cargo.toml new file mode 100644 index 00000000..92adb6df --- /dev/null +++ b/02_multicore_rust/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "kernel8" +version = "0.1.0" +authors = ["Andre Richter "] + +[dependencies] +raspi3_glue = { path = "raspi3_glue" } diff --git a/02_multicore_rust/Makefile b/02_multicore_rust/Makefile new file mode 100644 index 00000000..dc5a6d56 --- /dev/null +++ b/02_multicore_rust/Makefile @@ -0,0 +1,61 @@ +# +# MIT License +# +# Copyright (c) 2018 Andre Richter +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +TARGET = aarch64-raspi3-none-elf + +CROSS_CONTAINER = ./dockcross-linux-aarch64 +CROSS_CONTAINER_OBJCOPY = aarch64-linux-gnu-objcopy + +QEMU_CONTAINER = andrerichter/raspi3-qemu +DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work +QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img + +all: clean kernel8.img + +target/$(TARGET)/debug/kernel8: src/main.rs + RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) + cp $@ . + +target/$(TARGET)/release/kernel8: src/main.rs + RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release + cp $@ . + +ifeq ($(DEBUG),1) +kernel8: target/$(TARGET)/debug/kernel8 +else +kernel8: target/$(TARGET)/release/kernel8 +endif + +kernel8.img: kernel8 + $(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img + +qemu: + $(DOCKER_CMD) $(QEMU_CONTAINER) $(QEMU_CMD) -d in_asm + +clippy: + RUSTFLAGS="-C panic=abort" xargo clippy --target=$(TARGET) + +clean: + cargo clean + rm -f kernel8 diff --git a/02_multicore_rust/README.md b/02_multicore_rust/README.md new file mode 100644 index 00000000..696614db --- /dev/null +++ b/02_multicore_rust/README.md @@ -0,0 +1,75 @@ +# Tutorial 02 - Multicore Rust + +Now let's try something more complex, shall we? By complex I mean stopping the +CPU cores just like in the first tutorial, but this time stop one of them from +**Rust**! + +## Glue code + +In order to incorporate Rust code, we are setting up a binary crate and add +`#![no_std]` to `main.rs`, since we are writing our own bare metal code and do +not want to rely on the standard library. + +However, a lot of steps are needed to make a `no_std` crate build. All of this +and even more is explained in detail in [The Embedonomicon][nom], so please take +your time and read up on it. Afterwards, you can compare to the files in this +crate and see what we actually kept to get our Raspberry Pi 3 tutorial +going. Here's a short summary of the crate's structure: + + - `raspi3_glue/`: The extern crate containing glue code as presented in the + Embedonomicon. + - In a small deviation to the Embedonomicon, `lib.rs` also includes + `_boot_cores.S` from the previous tutorial via the [global_asm!][gasm] + macro. + - Therefore, `_boot_cores.S` has been moved into `raspi3_glue/src/`. + - `src`: Source code of our actual crate, currently only containing `main.rs` + executing an endless loop. + +[nom]: https://japaric.github.io/embedonomicon/ +[gasm]: https://doc.rust-lang.org/unstable-book/language-features/global-asm.html + +### Changes to `_boot_cores.S` + +In contrast to the previous tutorial, we now we have to [distinguish the + cores][dist]. To do so, we read the [mpidr_el1][mpdir] system register. If it + is not zero, we'll do the former infinite loop. If it is zero, aka we are + executing on core0, then we'll call the Rust `reset()` function. For that, we + also need a proper stack, and have space reserved in memory for the [bss + segment][bss]. + +We added the `bss` segment to the linker script and export its properties via +`__bss_start` and `__bss_size`, which will be picked up and zeroed out by the +glue code in `raspi3_glue/src/lib.rs`. Additionally, we set the stack in the +Assembly in `_boot_cores.S`, and then finally call the `reset()` function of the +glue code, which in turn calls `main()` after zeroing `bss`. In case the Rust +code returns (which it never should not), we also jump to the same infinite loop +the other CPU cores running. + +[dist]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/CFHCIDCH.html +[mpdir]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500g/BABHBJCI.html +[bss]: https://en.wikipedia.org/wiki/.bss + +## Changes to `Makefile` + +It became a bit trickier. We've added more targets: +- `kernel8.img` now depends on `kernel8`, which compiles the crate either in + release or debug mode. For the latter, add `DEBUG=1` before invoking make, + e.g. `DEBUG=1 make` +- [clippy] is Rust's linter, and can give you useful advise to improve your + code. Invoke with `make clippy`. + +[clippy]: https://github.com/rust-lang-nursery/rust-clippy + +From now on, we can use the same Makefile for every tutorial, regardless of the +number of Rust sources, and we won't discuss it any further. + +## Changes to `link.ld` + +Apart from the added bss section, it is important to start the text segment with +the Assembly code and not the Rust code, because we set the stack right before +it, hence the `KEEP()`. This way, the assembly stays at 0x80000, the same as +`_boot_cores` label and stack top. + +## main.rs + +Finally, our first Rust code. Just an empty loop, but still! :-) diff --git a/02_multicore_rust/aarch64-raspi3-none-elf.json b/02_multicore_rust/aarch64-raspi3-none-elf.json new file mode 100644 index 00000000..407f21b8 --- /dev/null +++ b/02_multicore_rust/aarch64-raspi3-none-elf.json @@ -0,0 +1,24 @@ +{ + "arch": "aarch64", + "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + "executables": true, + "linker-flavor": "ld.lld", + "linker-is-gnu": true, + "pre-link-args": { + "ld.lld": [ + "--script=link.ld" + ] + }, + "llvm-target": "aarch64-unknown-none", + "no-compiler-rt": true, + "features": "+a53,+strict-align", + "max-atomic-width": 128, + "os": "none", + "panic": "abort", + "panic-strategy": "abort", + "relocation-model": "pic", + "target-c-int-width": "32", + "target-endian": "little", + "target-pointer-width": "64", + "disable-redzone": true +} diff --git a/02_multicore_rust/dockcross-linux-aarch64 b/02_multicore_rust/dockcross-linux-aarch64 new file mode 100755 index 00000000..3c7481d2 --- /dev/null +++ b/02_multicore_rust/dockcross-linux-aarch64 @@ -0,0 +1,246 @@ +#!/bin/bash + +DEFAULT_DOCKCROSS_IMAGE=dockcross/linux-arm64 + +#------------------------------------------------------------------------------ +# Helpers +# +err() { + echo -e >&2 ERROR: $@\\n +} + +die() { + err $@ + exit 1 +} + +has() { + # eg. has command update + local kind=$1 + local name=$2 + + type -t $kind:$name | grep -q function +} + +#------------------------------------------------------------------------------ +# Command handlers +# +command:update-image() { + docker pull $FINAL_IMAGE +} + +help:update-image() { + echo Pull the latest $FINAL_IMAGE . +} + +command:update-script() { + if cmp -s <( docker run --rm $FINAL_IMAGE ) $0; then + echo $0 is up to date + else + echo -n Updating $0 '... ' + docker run --rm $FINAL_IMAGE > $0 && echo ok + fi +} + +help:update-image() { + echo Update $0 from $FINAL_IMAGE . +} + +command:update() { + command:update-image + command:update-script +} + +help:update() { + echo Pull the latest $FINAL_IMAGE, and then update $0 from that. +} + +command:help() { + if [[ $# != 0 ]]; then + if ! has command $1; then + err \"$1\" is not an dockcross command + command:help + elif ! has help $1; then + err No help found for \"$1\" + else + help:$1 + fi + else + cat >&2 < +ENDHELP + exit 1 + fi +} + +#------------------------------------------------------------------------------ +# Option processing +# +special_update_command='' +while [[ $# != 0 ]]; do + case $1 in + + --) + shift + break + ;; + + --args|-a) + ARG_ARGS="$2" + shift 2 + ;; + + --config|-c) + ARG_CONFIG="$2" + shift 2 + ;; + + --image|-i) + ARG_IMAGE="$2" + shift 2 + ;; + update|update-image|update-script) + special_update_command=$1 + break + ;; + -*) + err Unknown option \"$1\" + command:help + exit + ;; + + *) + break + ;; + + esac +done + +# The precedence for options is: +# 1. command-line arguments +# 2. environment variables +# 3. defaults + +# Source the config file if it exists +DEFAULT_DOCKCROSS_CONFIG=~/.dockcross +FINAL_CONFIG=${ARG_CONFIG-${DOCKCROSS_CONFIG-$DEFAULT_DOCKCROSS_CONFIG}} + +[[ -f "$FINAL_CONFIG" ]] && source "$FINAL_CONFIG" + +# Set the docker image +FINAL_IMAGE=${ARG_IMAGE-${DOCKCROSS_IMAGE-$DEFAULT_DOCKCROSS_IMAGE}} + +# Handle special update command +if [ "$special_update_command" != "" ]; then + case $special_update_command in + + update) + command:update + exit $? + ;; + + update-image) + command:update-image + exit $? + ;; + + update-script) + command:update-script + exit $? + ;; + + esac +fi + +# Set the docker run extra args (if any) +FINAL_ARGS=${ARG_ARGS-${DOCKCROSS_ARGS}} + +# Bash on Ubuntu on Windows +UBUNTU_ON_WINDOWS=$([ -e /proc/version ] && grep -l Microsoft /proc/version || echo "") +# MSYS, Git Bash, etc. +MSYS=$([ -e /proc/version ] && grep -l MINGW /proc/version || echo "") + +if [ -z "$UBUNTU_ON_WINDOWS" -a -z "$MSYS" ]; then + USER_IDS="-e BUILDER_UID=$( id -u ) -e BUILDER_GID=$( id -g ) -e BUILDER_USER=$( id -un ) -e BUILDER_GROUP=$( id -gn )" +fi + +# Change the PWD when working in Docker on Windows +if [ -n "$UBUNTU_ON_WINDOWS" ]; then + HOST_PWD=$PWD + HOST_PWD=${HOST_PWD/\/mnt\//} + HOST_PWD=${HOST_PWD/\//:\/} +elif [ -n "$MSYS" ]; then + HOST_PWD=$PWD + HOST_PWD=${HOST_PWD/\//} + HOST_PWD=${HOST_PWD/\//:\/} +else + HOST_PWD=$PWD +fi + +# Mount Additional Volumes +if [ -z "$SSH_DIR" ]; then + SSH_DIR="$HOME/.ssh" +fi + +HOST_VOLUMES= +if [ -e "$SSH_DIR" ]; then + HOST_VOLUMES+="-v $SSH_DIR:/home/$(id -un)/.ssh" +fi + +#------------------------------------------------------------------------------ +# Now, finally, run the command in a container +# +tty -s && TTY_ARGS=-ti || TTY_ARGS= +CONTAINER_NAME=dockcross_$RANDOM +docker run $TTY_ARGS --name $CONTAINER_NAME \ + -v "$HOST_PWD":/work \ + $HOST_VOLUMES \ + $USER_IDS \ + $FINAL_ARGS \ + $FINAL_IMAGE "$@" +run_exit_code=$? + +# Attempt to delete container +rm_output=$(docker rm -f $CONTAINER_NAME 2>&1) +rm_exit_code=$? +if [[ $rm_exit_code != 0 ]]; then + if [[ "$CIRCLECI" == "true" ]] && [[ $rm_output == *"Driver btrfs failed to remove"* ]]; then + : # Ignore error because of https://circleci.com/docs/docker-btrfs-error/ + else + echo "$rm_output" + exit $rm_exit_code + fi +fi + +exit $run_exit_code + +################################################################################ +# +# This image is not intended to be run manually. +# +# To create a dockcross helper script for the +# dockcross/linux-armv7 image, run: +# +# docker run --rm dockcross/linux-armv7 > dockcross-linux-armv7 +# chmod +x dockcross-linux-armv7 +# +# You may then wish to move the dockcross script to your PATH. +# +################################################################################ diff --git a/02_multicore_rust/kernel8.img b/02_multicore_rust/kernel8.img new file mode 100755 index 0000000000000000000000000000000000000000..dd969f56608c966647de8b2dd8ac5ce592719d5c GIT binary patch literal 152 zcmZ3;U~yHE#bHt+1H+bh1?H>&|Nj?X$iNU`&%iK|lYwE%Zy;YDD9*sZ!2kkG3=AS5 z`T?`N)&b`DYe3NnKy?#1TpfODdOG~HXXJQ&h=CylBnIZYGVB0}9sd76AEeZet literal 0 HcmV?d00001 diff --git a/.02_multicorec/link.ld b/02_multicore_rust/link.ld similarity index 100% rename from .02_multicorec/link.ld rename to 02_multicore_rust/link.ld diff --git a/02_multicore_rust/raspi3_glue/Cargo.toml b/02_multicore_rust/raspi3_glue/Cargo.toml new file mode 100644 index 00000000..99c8e683 --- /dev/null +++ b/02_multicore_rust/raspi3_glue/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "raspi3_glue" +version = "0.1.0" +authors = ["Andre Richter "] + +[dependencies] diff --git a/.02_multicorec/start.S b/02_multicore_rust/raspi3_glue/src/boot_cores.S similarity index 84% rename from .02_multicorec/start.S rename to 02_multicore_rust/raspi3_glue/src/boot_cores.S index 27d0c503..f6f28af6 100644 --- a/.02_multicorec/start.S +++ b/02_multicore_rust/raspi3_glue/src/boot_cores.S @@ -1,5 +1,6 @@ /* * Copyright (C) 2018 bzt (bztsrc@github) + * Copyright (c) 2018 Andre Richter * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -25,9 +26,9 @@ .section ".text.boot" -.global _start +.global _boot_cores -_start: +_boot_cores: // read cpu id, stop slave cores mrs x1, mpidr_el1 and x1, x1, #3 @@ -38,18 +39,10 @@ _start: 2: // cpu id == 0 // set stack before our code - ldr x1, =_start + ldr x1, =_boot_cores mov sp, x1 - // clear bss - ldr x1, =__bss_start - ldr w2, =__bss_size -3: cbz w2, 4f - str xzr, [x1], #8 - sub w2, w2, #1 - cbnz w2, 3b - - // jump to C code, should not return -4: bl main + // jump to Rust code, should not return + bl reset // for failsafe, halt this core too b 1b diff --git a/02_multicore_rust/raspi3_glue/src/lib.rs b/02_multicore_rust/raspi3_glue/src/lib.rs new file mode 100644 index 00000000..e1d22891 --- /dev/null +++ b/02_multicore_rust/raspi3_glue/src/lib.rs @@ -0,0 +1,88 @@ +/* + * MIT License + * + * Copyright (c) 2018 Jorge Aparicio + * Copyright (c) 2018 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#![feature(lang_items)] +#![no_std] +#![feature(global_asm)] + +use core::ptr; + +#[lang = "panic_fmt"] +unsafe extern "C" fn panic_fmt( + _args: core::fmt::Arguments, + _file: &'static str, + _line: u32, + _col: u32, +) -> ! { + loop {} +} + +#[lang = "start"] +extern "C" fn start(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize +where + T: Termination, +{ + user_main().report() as isize +} + +#[lang = "termination"] +trait Termination { + fn report(self) -> i32; +} + +impl Termination for () { + fn report(self) -> i32 { + 0 + } +} + +#[no_mangle] +pub unsafe extern "C" fn reset() -> ! { + extern "C" { + fn main(argc: isize, argv: *const *const u8) -> isize; + + static mut __bss_start: u32; + static mut __bss_end: u32; + } + + zero_bss(&mut __bss_start, &mut __bss_end); + + main(0, ptr::null()); + + loop {} +} + +unsafe fn zero_bss(bss_start: *mut u32, bss_end: *mut u32) { + let mut bss = bss_start; + while bss < bss_end { + // NOTE(ptr::write*) to force aligned stores + // NOTE(volatile) to prevent the compiler from optimizing this into `memclr` + ptr::write_volatile(bss, 0); + bss = bss.offset(1); + } +} + +// Disable all cores except core 0, and then jump to reset() +global_asm!(include_str!("boot_cores.S")); diff --git a/02_multicore_rust/src/main.rs b/02_multicore_rust/src/main.rs new file mode 100644 index 00000000..4e44126e --- /dev/null +++ b/02_multicore_rust/src/main.rs @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (c) 2018 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#![no_std] + +extern crate raspi3_glue; + +fn main() { + loop {} +}