diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..0a6e1fa --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,13 @@ +[build] +# https://internals.rust-lang.org/t/evaluating-pipelined-rustc-compilation/10199/12 +pipelining = true + +[target.aarch64-vesper-metta] +rustflags = [ + "-C", "target-feature=-fp-armv8", + "-C", "target-cpu=cortex-a53", + "-C", "embed-bitcode=yes", +] + +[unstable] +build-std = ["core", "compiler_builtins", "alloc"] diff --git a/.gitignore b/.gitignore index 4bfa550..7c0ef8c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .idea/ *.iml target/ +kernel8* +.gdb_history diff --git a/Cargo.lock b/Cargo.lock index af43cfc..e89c0f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,23 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "r0" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vesper" version = "0.0.1" +dependencies = [ + "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] +[metadata] +"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" +"checksum rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" diff --git a/Justfile b/Justfile index a560f8b..06476c6 100644 --- a/Justfile +++ b/Justfile @@ -2,4 +2,4 @@ qemu: @echo No QEMU support device: - cargo build + cargo make sdcard diff --git a/Makefile.toml b/Makefile.toml new file mode 100644 index 0000000..b881152 --- /dev/null +++ b/Makefile.toml @@ -0,0 +1,52 @@ +# +# SPDX-License-Identifier: BlueOak-1.0.0 +# +# Copyright (c) Berkus Decker +# +[config] +min_version = "0.24.0" +default_to_workspace = true + +[env] +CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = "false" + +DEFAULT_TARGET = "aarch64-vesper-metta" + +DEVICE_FEATURES = "noserial" + +OBJCOPY = "cargo objcopy" +OBJCOPY_PARAMS = "-- --strip-all -O binary" + +UTILS_CONTAINER = "andrerichter/raspi3-utils" +DOCKER_CMD = "docker run -it --rm -v ${PWD}:/work -w /work -p 5900:5900" + +TARGET_JSON = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/${DEFAULT_TARGET}.json" + +KERNEL_ELF = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/kernel8" +KERNEL_BIN = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/kernel8.img" + +[tasks.default] +alias = "all" + +[tasks.modules] +command = "cargo" +args = ["modules", "tree"] + +[tasks.all] +dependencies = ["kernel-binary"] + +[tasks.kernel-binary] # Forward build to vesper/Makefile.toml +env = { "CARGO_MAKE_MEMBER_TASK" = "kernel-binary" } +run_task = "do-on-members" + +[tasks.build] # Forward build to vesper/Makefile.toml +env = { "CARGO_MAKE_MEMBER_TASK" = "build" } +run_task = "do-on-members" + +[tasks.sdcard] +env = { "CARGO_MAKE_MEMBER_TASK" = "sdcard" } +run_task = "do-on-members" + +[tasks.sdeject] +env = { "CARGO_MAKE_MEMBER_TASK" = "sdeject" } +run_task = "do-on-members" diff --git a/linker/aarch64.ld b/linker/aarch64.ld new file mode 100644 index 0000000..923ee1b --- /dev/null +++ b/linker/aarch64.ld @@ -0,0 +1,80 @@ +/* + * SPDX-License-Identifier: MIT OR BlueOak-1.0.0 + * Copyright (c) 2018 Andre Richter + * Original code distributed under MIT, additional changes are under BlueOak-1.0.0 + */ + +ENTRY(_boot_cores); + +/* Symbols between __boot_start and __boot_end should be dropped after init is complete. + Symbols between __ro_start and __ro_end are the kernel code. + Symbols between __bss_start and __bss_end must be initialized to zero by r0 code in kernel. +*/ +SECTIONS +{ + . = 0x80000; /* AArch64 boot address is 0x80000, 4K-aligned */ + __boot_start = .; + .text : + { + KEEP(*(.text.boot)) + . = ALIGN(4096); + KEEP(*(.data.boot)) + . = ALIGN(4096); /* Here boot code ends */ + __boot_end = .; // __boot_end must be 4KiB aligned + __ro_start = .; + *(.text .text.*) + } + + .vectors ALIGN(2048): + { + *(.vectors) + } + + .rodata ALIGN(4): + { + *(.rodata .rodata.*) + FILL(0x00) + } + . = ALIGN(4096); /* Fill up to 4KiB */ + __ro_end = .; /* __ro_end must be 4KiB aligned */ + __data_start = .; /* __data_start must be 4KiB aligned */ + + .data : /* @todo align data to 4K -- it's already aligned up to __ro_end marker now */ + { + *(.data .data.*) + FILL(0x00) + } + + /* @todo could insert .data.boot here with proper alignment */ + + .bss ALIGN(8): + { + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4096); /* Align up to 4KiB */ + __bss_end = .; + } + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} + +PROVIDE(current_el0_synchronous = default_exception_handler); +PROVIDE(current_el0_irq = default_exception_handler); +PROVIDE(current_el0_fiq = default_exception_handler); +PROVIDE(current_el0_serror = default_exception_handler); + +PROVIDE(current_elx_synchronous = default_exception_handler); +PROVIDE(current_elx_irq = default_exception_handler); +PROVIDE(current_elx_fiq = default_exception_handler); +PROVIDE(current_elx_serror = default_exception_handler); + +PROVIDE(lower_aarch64_synchronous = default_exception_handler); +PROVIDE(lower_aarch64_irq = default_exception_handler); +PROVIDE(lower_aarch64_fiq = default_exception_handler); +PROVIDE(lower_aarch64_serror = default_exception_handler); + +PROVIDE(lower_aarch32_synchronous = default_exception_handler); +PROVIDE(lower_aarch32_irq = default_exception_handler); +PROVIDE(lower_aarch32_fiq = default_exception_handler); +PROVIDE(lower_aarch32_serror = default_exception_handler); diff --git a/nucleus/Cargo.toml b/nucleus/Cargo.toml index e048a41..9caf908 100644 --- a/nucleus/Cargo.toml +++ b/nucleus/Cargo.toml @@ -16,3 +16,5 @@ edition = "2018" maintenance = { status = "experimental" } [dependencies] +r0 = "0.2" +rlibc = "1.0" diff --git a/nucleus/Makefile.toml b/nucleus/Makefile.toml new file mode 100644 index 0000000..e59109e --- /dev/null +++ b/nucleus/Makefile.toml @@ -0,0 +1,24 @@ +# +# SPDX-License-Identifier: BlueOak-1.0.0 +# +# Copyright (c) Berkus Decker +# +[tasks.kernel-binary] +script = [ + "cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${DEFAULT_TARGET}/release/vesper ${KERNEL_ELF}", + "${OBJCOPY} ${OBJCOPY_PARAMS} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${DEFAULT_TARGET}/release/vesper ${KERNEL_BIN}" +] + +[tasks.build] +env = { "TARGET_FEATURES" = "" } +args = ["build", "-Zbuild-std=core,compiler_builtins,alloc", "--target=${TARGET_JSON}", "--release", "--features=${TARGET_FEATURES}"] + +[tasks.sdcard] +dependencies = ["build", "kernel-binary"] +command = "cp" +args = ["${KERNEL_BIN}", "/Volumes/BOOT/"] + +[tasks.sdeject] +dependencies = ["sdcard"] +command = "diskutil" +args = ["unmount", "/Volumes/BOOT/"] diff --git a/nucleus/src/main.rs b/nucleus/src/main.rs index e7a11a9..f964b35 100644 --- a/nucleus/src/main.rs +++ b/nucleus/src/main.rs @@ -1,3 +1,12 @@ -fn main() { - println!("Hello, world!"); +#![no_std] +#![no_main] + +#[no_mangle] +pub extern "C" fn _boot_cores() -> ! { + loop {} +} + +#[panic_handler] +fn panicked(_info: &core::panic::PanicInfo) -> ! { + loop {} } diff --git a/targets/README.md b/targets/README.md new file mode 100644 index 0000000..0c97e63 --- /dev/null +++ b/targets/README.md @@ -0,0 +1,25 @@ +# vesper-targets + +These are [target +specifications](https://github.com/rust-lang/rfcs/blob/master/text/0131-target-specification.md) +suitable for cross-compiling Rust crates for Vesper. + +They are very much based on Robigalia's [sel4-targets](https://gitlab.com/robigalia/sel4-targets). + +## Status + +Complete for aarch64. Untested for anything else. + +## Generating target specifications: + +See [description in rust docs](https://doc.rust-lang.org/rustc/targets/custom.html). + +To generate a target specification json template, run + +``` +rustc +nightly -Z unstable-options --target= --print target-spec-json +``` + +### To do + +"panic-strategy": "abort" is ok for baremetal targets, but not for -metta, right? Will rework for userspace targets when we have unwinding. diff --git a/targets/aarch64-vesper-metta.json b/targets/aarch64-vesper-metta.json new file mode 100644 index 0000000..363679e --- /dev/null +++ b/targets/aarch64-vesper-metta.json @@ -0,0 +1,22 @@ +{ + "llvm-target": "aarch64-unknown-none", + "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + "arch": "aarch64", + "os": "vesper", + "vendor": "metta", + "env": "", + "executables": true, + "panic-strategy": "abort", + "linker-flavor": "ld.lld", + "linker": "rust-lld", + "pre-link-args": { + "ld.lld": [ + "--script=linker/aarch64.ld", + "--print-gc-sections" + ] + }, + "disable-redzone": true, + "target-endian": "little", + "target-c-int-width": "32", + "target-pointer-width": "64" +} diff --git a/targets/bcm2710-rpi-3-b-plus.dtb b/targets/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000..bdc7e43 Binary files /dev/null and b/targets/bcm2710-rpi-3-b-plus.dtb differ