refactor: 📦 Split kernel into machine and nucleus

Move openocd task to upper level and remove kernel
build dependency - the qemu runner doesn't really
depend on it.
This commit is contained in:
Berkus Decker 2022-01-22 23:15:50 +02:00
parent b26d61cb67
commit 4cdeeb8556
44 changed files with 270 additions and 204 deletions

View File

@ -1,16 +1,12 @@
[unstable]
build-std = ["core", "compiler_builtins", "alloc"]
build-std-features = ["compiler-builtins-mem"]
[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",
"-Z", "macro-backtrace",
"-C", "target-feature=-fp-armv8",
"-C", "target-cpu=cortex-a53",
"-C", "embed-bitcode=yes",
"-Z", "macro-backtrace",
]
runner = "cargo make test-runner"

56
Cargo.lock generated
View File

@ -44,6 +44,38 @@ dependencies = [
"unicode-segmentation",
]
[[package]]
name = "machine"
version = "0.0.1"
dependencies = [
"bit_field",
"bitflags",
"cfg-if",
"cortex-a",
"qemu-exit",
"r0",
"snafu",
"tock-registers",
"usize_conversions",
"ux",
]
[[package]]
name = "nucleus"
version = "0.0.1"
dependencies = [
"bit_field",
"bitflags",
"cfg-if",
"cortex-a",
"machine",
"r0",
"snafu",
"tock-registers",
"usize_conversions",
"ux",
]
[[package]]
name = "proc-macro2"
version = "1.0.27"
@ -76,9 +108,9 @@ checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
[[package]]
name = "snafu"
version = "0.7.0-beta.2"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c25527526a3f0e26586508fc008e03929bc74c64fb00f34c6b22922bf39eaca"
checksum = "2eba135d2c579aa65364522eb78590cdf703176ef71ad4c32b00f58f7afb2df5"
dependencies = [
"doc-comment",
"snafu-derive",
@ -86,9 +118,9 @@ dependencies = [
[[package]]
name = "snafu-derive"
version = "0.7.0-beta.2"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6cdd4a5d0765ccc385665731d230efeb3b7e43df0770b625161da46bd5c9247"
checksum = "7a7fe9b0669ef117c5cabc5549638528f36771f058ff977d7689deb517833a75"
dependencies = [
"heck",
"proc-macro2",
@ -136,19 +168,3 @@ name = "ux"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f"
[[package]]
name = "vesper"
version = "0.0.1"
dependencies = [
"bit_field",
"bitflags",
"cfg-if",
"cortex-a",
"qemu-exit",
"r0",
"snafu",
"tock-registers",
"usize_conversions",
"ux",
]

View File

@ -3,7 +3,7 @@ _default:
# Build and run kernel in QEMU with serial port emulation
zellij:
cargo make zellij-config
cargo make zellij-nucleus
zellij --layout-path emulation/layout.zellij
# Build and run kernel in QEMU

View File

@ -38,7 +38,9 @@ VOLUME = { value = "/Volumes/BOOT", condition = { env_not_set = ["VOLUME"] } }
#
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
RUST_LIBS = "-Z build-std=compiler_builtins,core,alloc -Z build-std-features=compiler-builtins-mem"
TARGET_JSON = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/${TARGET}.json"
PLATFORM_TARGET="--target=${TARGET_JSON} --features=${TARGET_FEATURES} ${RUST_LIBS}"
DEVICE_FEATURES = "noserial"
QEMU_FEATURES = "qemu"
@ -65,8 +67,8 @@ QEMU_GDB_OPTS = "-gdb tcp::5555 -S"
GDB_CONNECT_FILE = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${TARGET}/gdb-connect"
KERNEL_ELF = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/kernel8"
KERNEL_BIN = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/kernel8.img"
KERNEL_ELF = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${TARGET}/release/nucleus"
KERNEL_BIN = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/nucleus.bin"
[tasks.default]
alias = "all"
@ -78,6 +80,83 @@ dependencies = ["kernel-binary"]
command = "cargo"
args = ["modules", "tree"]
[tasks.build]
env = { "TARGET_FEATURES" = "" }
command = "cargo"
args = ["build", "@@split(PLATFORM_TARGET, )", "--release"]
[tasks.build-qemu]
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
command = "cargo"
args = ["build", "@@split(PLATFORM_TARGET, )", "--release"]
[tasks.expand]
env = { "TARGET_FEATURES" = "" }
command = "cargo"
args = ["expand", "@@split(PLATFORM_TARGET, )", "--release"]
[tasks.test]
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
command = "cargo"
args = ["test", "@@split(PLATFORM_TARGET, )"]
[tasks.docs]
env = { "TARGET_FEATURES" = "" }
command = "cargo"
args = ["doc", "--open", "--no-deps", "@@split(PLATFORM_TARGET, )"]
[tasks.clippy]
env = { "TARGET_FEATURES" = "", "CLIPPY_FEATURES" = { value = "--features=${CLIPPY_FEATURES}", condition = { env_set = ["CLIPPY_FEATURES"] } } }
command = "cargo"
args = ["clippy", "@@split(PLATFORM_TARGET, )", "@@remove-empty(CLIPPY_FEATURES)", "--", "-D", "warnings"]
# These tasks are written in cargo-make's own script to make it portable across platforms (no `basename` on Windows)
[tasks.custom-binary]
env = { "BINARY_FILE" = "${BINARY_FILE}" }
script_runner = "@duckscript"
script = [
'''
binaryFile = basename ${BINARY_FILE}
cp ${BINARY_FILE} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.elf
exec --fail-on-error ${OBJCOPY} %{OBJCOPY_PARAMS} ${BINARY_FILE} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.bin
'''
]
install_crate = { crate_name = "cargo-binutils", binary = "rust-objcopy", test_arg = ["--help"] }
[tasks.test-binary]
env = { "BINARY_FILE" = "${CARGO_MAKE_TASK_ARGS}" }
run_task = "custom-binary"
[tasks.test-runner]
dependencies = ["test-binary"]
script_runner = "@duckscript"
script = [
'''
binaryFile = basename ${CARGO_MAKE_TASK_ARGS}
exec --fail-on-error ${QEMU} %{QEMU_OPTS} %{QEMU_TESTS_OPTS} -dtb ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/bcm2710-rpi-3-b-plus.dtb -kernel ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.bin
'''
]
[tasks.zellij-config]
dependencies = ["build-qemu", "kernel-binary"]
script_runner = "@duckscript"
env = { "ZELLIJ_CONFIG_FILE" = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/emulation/zellij-config.sh" }
script = [
'''
writefile ${ZELLIJ_CONFIG_FILE} "QEMU=${QEMU}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "QEMU_OPTS=\"${QEMU_OPTS}\"\n"
appendfile ${ZELLIJ_CONFIG_FILE} "QEMU_RUNNER_OPTS=${QEMU_RUNNER_OPTS}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "KERNEL_BIN=${KERNEL_BIN}\n"
'''
]
install_crate = { crate_name = "zellij", binary = "zellij", test_arg = ["--help"] }
[tasks.openocd]
script = [
"${OPENOCD} -f interface/jlink.cfg -f ../ocd/${TARGET_BOARD}_target.cfg"
]
[tasks.sdeject]
dependencies = ["sdcard"]
script = [

36
machine/Cargo.toml Normal file
View File

@ -0,0 +1,36 @@
[package]
name = "machine"
version = "0.0.1"
authors = ["Berkus Decker <berkus+vesper@metta.systems>"]
description = "Vesper nanokernel shared code library."
documentation = "https://docs.metta.systems/vesper"
homepage = "https://github.com/metta-systems/vesper"
repository = "https://github.com/metta-systems/vesper"
readme = "README.md"
license = "BlueOak-1.0.0"
categories = ["no-std", "embedded", "os"]
publish = false
edition = "2021"
[badges]
maintenance = { status = "experimental" }
[features]
noserial = []
# Enable JTAG debugging of kernel - enable jtag helpers and
# block waiting for JTAG probe attach at the start of kernel main.
jtag = []
# Build for running under QEMU with semihosting, so various halt/reboot options would for example quit QEMU instead.
qemu = []
[dependencies]
r0 = "1.0"
qemu-exit = "3.0"
cortex-a = "7.0"
tock-registers = "0.7"
ux = { version = "0.1", default-features = false }
usize_conversions = "0.2"
bit_field = "0.10"
bitflags = "1.3"
cfg-if = "1.0"
snafu = { version = "0.7", default-features = false }

View File

@ -7,6 +7,4 @@ mod asid;
mod phys_addr;
mod virt_addr;
pub use asid::*;
pub use phys_addr::*;
pub use virt_addr::*;
pub use {asid::*, phys_addr::*, virt_addr::*};

View File

@ -13,18 +13,12 @@
use {
crate::{
arch::aarch64::memory::{
get_virt_addr_properties, AttributeFields, /*FrameAllocator, PhysAddr, VirtAddr,*/
},
arch::aarch64::memory::{get_virt_addr_properties, AttributeFields},
println,
},
// bitflags::bitflags,
core::{
// convert::TryInto,
// fmt,
marker::PhantomData,
ops::{Index, IndexMut},
// ptr::Unique,
},
cortex_a::{
asm::barrier,
@ -35,12 +29,10 @@ use {
interfaces::{ReadWriteable, Readable, Writeable},
register_bitfields,
},
// ux::*,
};
mod mair {
use cortex_a::registers::MAIR_EL1;
use tock_registers::interfaces::Writeable;
use {cortex_a::registers::MAIR_EL1, tock_registers::interfaces::Writeable};
/// Setup function for the MAIR_EL1 register.
pub fn set_up() {

View File

@ -13,8 +13,7 @@ use {
mod addr;
pub mod mmu;
pub use addr::PhysAddr;
pub use addr::VirtAddr;
pub use addr::{PhysAddr, VirtAddr};
// aarch64 granules and page sizes howto:
// https://stackoverflow.com/questions/34269185/simultaneous-existence-of-different-sized-pages-on-aarch64

View File

@ -4,8 +4,7 @@
#![allow(dead_code)]
use crate::platform;
use core::fmt;
use {crate::platform, core::fmt};
/// A trait that must be implemented by devices that are candidates for the
/// global console.

55
machine/src/lib.rs Normal file
View File

@ -0,0 +1,55 @@
#![no_std]
#![no_main]
#![feature(decl_macro)]
#![feature(allocator_api)]
#![feature(format_args_nl)]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(custom_test_frameworks)]
#![test_runner(crate::tests::test_runner)]
#![reexport_test_harness_main = "test_main"]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::enum_variant_names)]
#![allow(clippy::nonstandard_macro_braces)] // https://github.com/shepmaster/snafu/issues/296
#![allow(missing_docs)] // Temp: switch to deny
#![deny(warnings)]
#[cfg(not(target_arch = "aarch64"))]
use architecture_not_supported_sorry;
/// Architecture-specific code.
#[macro_use]
pub mod arch;
pub use arch::*;
pub mod devices;
pub mod macros;
mod mm;
pub mod panic;
pub mod platform;
pub mod qemu;
mod sync;
pub mod tests;
pub mod write_to;
/// The global console. Output of the kernel print! and println! macros goes here.
pub static CONSOLE: sync::NullLock<devices::Console> = sync::NullLock::new(devices::Console::new());
/// The global allocator for DMA-able memory. That is, memory which is tagged
/// non-cacheable in the page tables.
static DMA_ALLOCATOR: sync::NullLock<mm::BumpAllocator> =
sync::NullLock::new(mm::BumpAllocator::new(
// @todo Init this after we loaded boot memory map
memory::map::virt::DMA_HEAP_START as usize,
memory::map::virt::DMA_HEAP_END as usize,
"Global DMA Allocator",
// Try the following arguments instead to see all mailbox operations
// fail. It will cause the allocator to use memory that are marked
// cacheable and therefore not DMA-safe. The answer from the VideoCore
// won't be received by the CPU because it reads an old cached value
// that resembles an error case instead.
// 0x00600000 as usize,
// 0x007FFFFF as usize,
// "Global Non-DMA Allocator",
));

View File

@ -1,14 +1,10 @@
#[cfg(not(test))]
#[panic_handler]
fn panicked(info: &core::panic::PanicInfo) -> ! {
pub fn handler(info: &core::panic::PanicInfo) -> ! {
// @todo This may fail to print if the panic message is too long for local print buffer.
crate::println!("{}", info);
crate::endless_sleep()
}
#[cfg(test)]
#[panic_handler]
fn panicked(info: &core::panic::PanicInfo) -> ! {
pub fn handler_for_tests(info: &core::panic::PanicInfo) -> ! {
crate::println!("\n[failed]\n");
// @todo This may fail to print if the panic message is too long for local print buffer.
crate::println!("\nError: {}\n", info);

View File

@ -361,6 +361,7 @@ impl PreparedMailbox {
impl Mailbox {
/// Create a new mailbox in the DMA-able memory area.
#[allow(clippy::result_unit_err)]
pub fn new(base_addr: usize) -> ::core::result::Result<Mailbox, ()> {
use core::alloc::Allocator;
crate::DMA_ALLOCATOR

View File

@ -64,6 +64,7 @@ impl ops::Deref for Power {
}
impl Power {
#[allow(clippy::new_without_default)]
pub fn new() -> Power {
Power
}

View File

@ -12,7 +12,6 @@ pub mod semihosting {
qemu_exit_handle.exit_success()
}
#[cfg(test)]
pub fn exit_failure() -> ! {
use qemu_exit::QEMUExit;
@ -22,7 +21,6 @@ pub mod semihosting {
qemu_exit_handle.exit_failure()
}
#[cfg(test)]
pub fn sys_write0_call(text: &str) {
// SAFETY: text must be \0-terminated!
let cmd = 0x04;

View File

@ -8,7 +8,7 @@
use crate::{print, println, qemu};
pub trait TestFn {
fn run(&self) -> ();
fn run(&self);
}
impl<T> TestFn for T
@ -22,7 +22,6 @@ where
}
}
#[cfg(test)]
pub fn test_runner(tests: &[&dyn TestFn]) {
println!("Running {} tests", tests.len());
for test in tests {

View File

@ -1,8 +1,8 @@
[package]
name = "vesper"
name = "nucleus"
version = "0.0.1"
authors = ["Berkus Decker <berkus+vesper@metta.systems>"]
description = "Vesper exokernel"
description = "Vesper nanokernel binary"
documentation = "https://docs.metta.systems/vesper"
homepage = "https://github.com/metta-systems/vesper"
repository = "https://github.com/metta-systems/vesper"
@ -16,21 +16,21 @@ edition = "2021"
maintenance = { status = "experimental" }
[features]
noserial = []
noserial = ["machine/noserial"]
# Enable JTAG debugging of kernel - enable jtag helpers and
# block waiting for JTAG probe attach at the start of kernel main.
jtag = []
jtag = ["machine/jtag"]
# Build for running under QEMU with semihosting, so various halt/reboot options would for example quit QEMU instead.
qemu = ["qemu-exit"]
qemu = ["machine/qemu"]
[dependencies]
machine = { path = "../machine" }
r0 = "1.0"
qemu-exit = { version = "3.0", optional = true }
cortex-a = "7.0"
tock-registers = "0.7"
ux = { version = "0.1.3", default-features = false }
usize_conversions = "0.2.0"
bit_field = "0.10.1"
ux = { version = "0.1", default-features = false }
usize_conversions = "0.2"
bit_field = "0.10"
bitflags = "1.3"
cfg-if = "1.0"
snafu = { version = "0.7.0-beta.2", default-features = false }
snafu = { version = "0.7", default-features = false }

View File

@ -3,92 +3,28 @@
#
# Copyright (c) Berkus Decker <berkus+vesper@metta.systems>
#
[tasks.build]
env = { "TARGET_FEATURES" = "" }
args = ["build", "--target=${TARGET_JSON}", "--release", "--features=${TARGET_FEATURES}"]
[tasks.expand]
env = { "TARGET_FEATURES" = "" }
args = ["expand", "--target=${TARGET_JSON}", "--release", "--features=${TARGET_FEATURES}"]
[tasks.test]
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
args = ["test", "--target=${TARGET_JSON}", "--features=${TARGET_FEATURES}"]
[tasks.docs]
env = { "TARGET_FEATURES" = "" }
args = ["doc", "--open", "--no-deps", "--target=${TARGET_JSON}", "--features=${TARGET_FEATURES}"]
# These tasks are written in cargo-make's own script to make it portable across platforms (no `basename` on Windows)
[tasks.kernel-binary]
script_runner = "@duckscript"
script = [
'''
cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${TARGET}/release/vesper ${KERNEL_ELF}
exec --fail-on-error ${OBJCOPY} %{OBJCOPY_PARAMS} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${TARGET}/release/vesper ${KERNEL_BIN}
'''
]
[tasks.custom-binary]
script_runner = "@duckscript"
script = [
'''
binaryFile = basename ${CARGO_MAKE_TASK_ARGS}
cp ${CARGO_MAKE_TASK_ARGS} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.elf
exec --fail-on-error ${OBJCOPY} %{OBJCOPY_PARAMS} ${CARGO_MAKE_TASK_ARGS} ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.bin
'''
]
[tasks.test-runner]
dependencies = ["custom-binary"]
script_runner = "@duckscript"
script = [
'''
binaryFile = basename ${CARGO_MAKE_TASK_ARGS}
exec --fail-on-error ${QEMU} %{QEMU_OPTS} %{QEMU_TESTS_OPTS} -dtb ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/bcm2710-rpi-3-b-plus.dtb -kernel ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${binaryFile}.bin
'''
]
[tasks.build-qemu]
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
command = "cargo"
args = ["build", "--target=${TARGET_JSON}", "--release", "--features=${TARGET_FEATURES}"]
env = { "BINARY_FILE" = "${KERNEL_ELF}" }
run_task = "custom-binary"
[tasks.qemu-runner]
dependencies = ["build-qemu", "kernel-binary"]
env = { "TARGET_FEATURES" = "${QEMU_FEATURES}" }
script = [
"${QEMU} ${QEMU_OPTS} ${QEMU_RUNNER_OPTS} -dtb ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/targets/bcm2710-rpi-3-b-plus.dtb -kernel ${KERNEL_BIN}"
]
dependencies = ["build-qemu", "kernel-binary"]
[tasks.qemu]
extend = "qemu-runner"
env = { "QEMU_RUNNER_OPTS" = "${QEMU_SERIAL_OPTS}" }
[tasks.zellij-config]
extend = "qemu-runner"
script_runner = "@duckscript"
env = { "ZELLIJ_CONFIG_FILE" = "../emulation/zellij-config.sh" }
script = [
'''
writefile ${ZELLIJ_CONFIG_FILE} "QEMU=${QEMU}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "QEMU_OPTS=\"${QEMU_OPTS}\"\n"
appendfile ${ZELLIJ_CONFIG_FILE} "QEMU_RUNNER_OPTS=${QEMU_RUNNER_OPTS}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY=${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}\n"
appendfile ${ZELLIJ_CONFIG_FILE} "KERNEL_BIN=${KERNEL_BIN}\n"
'''
]
install_crate = { crate_name = "zellij", binary = "zellij", test_arg = ["--help"] }
[tasks.qemu-gdb]
extend = "qemu-runner"
env = { "QEMU_RUNNER_OPTS" = "${QEMU_SERIAL_OPTS} ${QEMU_GDB_OPTS}" }
[tasks.openocd]
dependencies = ["build", "kernel-binary"]
script = [
"${OPENOCD} -f interface/jlink.cfg -f ../ocd/${TARGET_BOARD}_target.cfg"
]
[tasks.zellij-nucleus]
env = { "KERNEL_BIN" = "${KERNEL_BIN}" }
run_task = "zellij-config"
[tasks.gdb-config]
script_runner = "@duckscript"
@ -110,7 +46,7 @@ dependencies = ["build", "kernel-binary"]
script = [
"${NM} -- ${KERNEL_ELF} | sort"
]
#install_crate = "cargo-binutils"
install_crate = { crate_name = "cargo-binutils", binary = "rust-nm", test_arg = ["--help"] }
[tasks.sdcard]
dependencies = ["build", "kernel-binary"]
@ -122,11 +58,6 @@ script = [
'''
]
[tasks.clippy]
env = { "TARGET_FEATURES" = { value = "--features=${CLIPPY_FEATURES}", condition = { env_set = ["CLIPPY_FEATURES"] } } }
command = "cargo"
args = ["clippy", "--target=${TARGET_JSON}", "@@remove-empty(TARGET_FEATURES)", "--", "-D", "warnings"]
[tasks.hopper]
dependencies = ["build", "kernel-binary"]
# The cmd line below causes a bug in hopper, see https://www.dropbox.com/s/zyw5mfx0bepcjb1/hopperv4-RAW-bug.mov?dl=0

View File

@ -9,71 +9,36 @@
#![no_std]
#![no_main]
#![feature(decl_macro)]
#![feature(allocator_api)]
#![feature(ptr_internals)]
#![feature(format_args_nl)]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(custom_test_frameworks)]
#![test_runner(crate::tests::test_runner)]
#![test_runner(machine::tests::test_runner)]
#![reexport_test_harness_main = "test_main"]
#![deny(missing_docs)]
#![deny(warnings)]
#![allow(clippy::nonstandard_macro_braces)] // https://github.com/shepmaster/snafu/issues/296
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::enum_variant_names)]
#[cfg(not(target_arch = "aarch64"))]
use architecture_not_supported_sorry;
/// Architecture-specific code.
#[macro_use]
pub mod arch;
pub use arch::*;
mod devices;
mod macros;
mod mm;
mod panic;
mod platform;
#[cfg(feature = "qemu")]
mod qemu;
mod sync;
#[cfg(test)]
mod tests;
mod write_to;
#[cfg(not(test))]
use core::panic::PanicInfo;
use {
crate::platform::rpi3::{
display::{Color, DrawError},
mailbox::{channel, Mailbox, MailboxOps},
vc::VC,
},
cfg_if::cfg_if,
machine::{
arch, entry, memory,
platform::rpi3::{
display::{Color, DrawError},
mailbox::{channel, Mailbox, MailboxOps},
vc::VC,
},
println, CONSOLE,
},
};
entry!(kmain);
/// The global console. Output of the kernel print! and println! macros goes here.
static CONSOLE: sync::NullLock<devices::Console> = sync::NullLock::new(devices::Console::new());
/// The global allocator for DMA-able memory. That is, memory which is tagged
/// non-cacheable in the page tables.
static DMA_ALLOCATOR: sync::NullLock<mm::BumpAllocator> =
sync::NullLock::new(mm::BumpAllocator::new(
// @todo Init this after we loaded boot memory map
memory::map::virt::DMA_HEAP_START as usize,
memory::map::virt::DMA_HEAP_END as usize,
"Global DMA Allocator",
// Try the following arguments instead to see all mailbox operations
// fail. It will cause the allocator to use memory that are marked
// cacheable and therefore not DMA-safe. The answer from the VideoCore
// won't be received by the CPU because it reads an old cached value
// that resembles an error case instead.
// 0x00600000 as usize,
// 0x007FFFFF as usize,
// "Global Non-DMA Allocator",
));
#[cfg(not(test))]
#[panic_handler]
fn panicked(info: &PanicInfo) -> ! {
machine::panic::handler(info)
}
fn print_mmu_state_and_features() {
memory::mmu::print_features();
@ -103,7 +68,7 @@ fn init_exception_traps() {
#[cfg(not(feature = "noserial"))]
fn init_uart_serial() {
use crate::platform::rpi3::{gpio::GPIO, mini_uart::MiniUart, pl011_uart::PL011Uart};
use machine::platform::rpi3::{gpio::GPIO, mini_uart::MiniUart, pl011_uart::PL011Uart};
let gpio = GPIO::default();
let uart = MiniUart::default();
@ -131,7 +96,7 @@ fn init_uart_serial() {
// physical wires (e.g. the Framebuffer), you don't need to do this,
// because flush() is anyways called implicitly by replace_with(). This
// is just a special case.
use crate::devices::console::ConsoleOps;
use machine::devices::console::ConsoleOps;
CONSOLE.lock(|c| c.flush());
match uart.prepare(mbox, &gpio) {
@ -151,7 +116,7 @@ fn init_uart_serial() {
#[inline]
pub fn kmain() -> ! {
#[cfg(feature = "jtag")]
jtag::wait_debugger();
machine::arch::jtag::wait_debugger();
init_mmu();
init_exception_traps();
@ -181,7 +146,7 @@ fn command_prompt() {
b"uart" => init_uart_serial(),
b"disp" => check_display_init(),
b"trap" => check_data_abort_trap(),
b"map" => arch::memory::print_layout(),
b"map" => machine::arch::memory::print_layout(),
b"led on" => set_led(true),
b"led off" => set_led(false),
b"help" => print_help(),
@ -222,9 +187,9 @@ fn reboot() -> ! {
cfg_if! {
if #[cfg(feature = "qemu")] {
println!("Bye, shutting down QEMU");
qemu::semihosting::exit_success()
machine::qemu::semihosting::exit_success()
} else {
use crate::platform::rpi3::power::Power;
use machine::platform::rpi3::power::Power;
println!("Bye, going to reset now");
Power::new().reset()
@ -251,7 +216,7 @@ fn display_graphics() -> Result<(), DrawError> {
display.draw_text(50, 50, "Hello there!", Color::rgb(128, 192, 255))?;
let mut buf = [0u8; 64];
let s = write_to::show(&mut buf, format_args!("Display width {}", display.width));
let s = machine::write_to::show(&mut buf, format_args!("Display width {}", display.width));
if s.is_err() {
display.draw_text(50, 150, "Error displaying", Color::red())?
@ -280,7 +245,12 @@ fn check_data_abort_trap() {
#[cfg(test)]
mod main_tests {
use super::*;
use {super::*, core::panic::PanicInfo};
#[panic_handler]
fn panicked(info: &PanicInfo) -> ! {
machine::panic::handler_for_tests(info)
}
#[test_case]
fn test_data_abort_trap() {