Various finetunings

pull/84/head
Andre Richter 4 years ago
parent e7df5b2982
commit 22faff5229
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -197,7 +197,7 @@ diff -uNr 02_runtime_init/src/panic_wait.rs 03_hacky_hello_world/src/panic_wait.
diff -uNr 02_runtime_init/src/print.rs 03_hacky_hello_world/src/print.rs
--- 02_runtime_init/src/print.rs
+++ 03_hacky_hello_world/src/print.rs
@@ -0,0 +1,42 @@
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
@ -208,7 +208,7 @@ diff -uNr 02_runtime_init/src/print.rs 03_hacky_hello_world/src/print.rs
+use core::fmt;
+
+//--------------------------------------------------------------------------------------------------
+// Private Code
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+#[doc(hidden)]
@ -218,10 +218,6 @@ diff -uNr 02_runtime_init/src/print.rs 03_hacky_hello_world/src/print.rs
+ bsp::console::console().write_fmt(args).unwrap();
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Prints without a newline.
+///
+/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -84,7 +84,7 @@ diff -uNr 03_hacky_hello_world/src/_arch/aarch64/cpu.rs 04_zero_overhead_abstrac
+
+ // Expect the boot core to start in EL2.
+ if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
+ SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
+ SP.set(bsp::memory::boot_core_stack_end() as u64);
+ runtime_init::runtime_init()
+ } else {
+ // If not core0, infinitely wait for events.
@ -157,20 +157,32 @@ diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/cpu.rs 04_zero_overhead_abstr
diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/memory.rs 04_zero_overhead_abstraction/src/bsp/raspberrypi/memory.rs
--- 03_hacky_hello_world/src/bsp/raspberrypi/memory.rs
+++ 04_zero_overhead_abstraction/src/bsp/raspberrypi/memory.rs
@@ -17,6 +17,13 @@
@@ -17,9 +17,25 @@
}
//--------------------------------------------------------------------------------------------------
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// The early boot core's stack address.
+pub const BOOT_CORE_STACK_START: usize = 0x80_000;
+/// The board's memory map.
+#[rustfmt::skip]
+pub(super) mod map {
+ pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+}
+
+//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
+/// Exclusive end address of the boot core's stack.
+#[inline(always)]
+pub fn boot_core_stack_end() -> usize {
+ map::BOOT_CORE_STACK_END
+}
+
/// Return the range spanning the .bss section.
///
/// # Safety
diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi.rs 04_zero_overhead_abstraction/src/bsp/raspberrypi.rs
--- 03_hacky_hello_world/src/bsp/raspberrypi.rs

@ -25,7 +25,7 @@ pub unsafe extern "C" fn _start() -> ! {
// Expect the boot core to start in EL2.
if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP.set(bsp::memory::boot_core_stack_end() as u64);
runtime_init::runtime_init()
} else {
// If not core0, infinitely wait for events.

@ -20,13 +20,22 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -25,7 +25,7 @@ pub unsafe extern "C" fn _start() -> ! {
// Expect the boot core to start in EL2.
if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP.set(bsp::memory::boot_core_stack_end() as u64);
runtime_init::runtime_init()
} else {
// If not core0, infinitely wait for events.

@ -20,13 +20,22 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -268,7 +268,7 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_g
+use synchronization::interface::Mutex;
+
+impl driver::interface::DeviceDriver for GPIO {
+ fn compatible(&self) -> &str {
+ fn compatible(&self) -> &'static str {
+ "BCM GPIO"
+ }
+}
@ -524,11 +524,11 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 06_dri
+use synchronization::interface::Mutex;
+
+impl driver::interface::DeviceDriver for PL011Uart {
+ fn compatible(&self) -> &str {
+ fn compatible(&self) -> &'static str {
+ "BCM PL011 UART"
+ }
+
+ fn init(&self) -> Result<(), ()> {
+ unsafe fn init(&self) -> Result<(), &'static str> {
+ let mut r = &self.inner;
+ r.lock(|inner| inner.init());
+
@ -608,7 +608,7 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm.rs 06_drivers_gpio_uart/src/
diff -uNr 05_safe_globals/src/bsp/device_driver/common.rs 06_drivers_gpio_uart/src/bsp/device_driver/common.rs
--- 05_safe_globals/src/bsp/device_driver/common.rs
+++ 06_drivers_gpio_uart/src/bsp/device_driver/common.rs
@@ -0,0 +1,35 @@
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2020 Andre Richter <andre.o.richter@gmail.com>
@ -617,31 +617,34 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/common.rs 06_drivers_gpio_uart/s
+
+use core::{marker::PhantomData, ops};
+
+//--------------------------------------------------------------------------------------------------
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+pub struct MMIODerefWrapper<T> {
+ base_addr: usize,
+ start_addr: usize,
+ phantom: PhantomData<T>,
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+impl<T> MMIODerefWrapper<T> {
+ /// Create an instance.
+ pub const unsafe fn new(base_addr: usize) -> Self {
+ pub const unsafe fn new(start_addr: usize) -> Self {
+ Self {
+ base_addr,
+ start_addr,
+ phantom: PhantomData,
+ }
+ }
+
+ /// Return a pointer to the associated MMIO register block.
+ fn ptr(&self) -> *const T {
+ self.base_addr as *const _
+ }
+}
+
+impl<T> ops::Deref for MMIODerefWrapper<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe { &*self.ptr() }
+ unsafe { &*(self.start_addr as *const _) }
+ }
+}
@ -807,11 +810,11 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/driver.rs 06_drivers_gpio_uart/src
+use crate::driver;
+
+//--------------------------------------------------------------------------------------------------
+// Public Definitions
+// Private Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// Device Driver Manager type.
+pub struct BSPDriverManager {
+struct BSPDriverManager {
+ device_drivers: [&'static (dyn DeviceDriver + Sync); 2],
+}
+
@ -851,13 +854,13 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/driver.rs 06_drivers_gpio_uart/src
diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
--- 05_safe_globals/src/bsp/raspberrypi/memory.rs
+++ 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
@@ -23,6 +23,33 @@
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
+/// The board's memory map.
+#[rustfmt::skip]
+pub(super) mod map {
@@ -23,7 +23,30 @@
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
- pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+ pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000;
+
@ -880,10 +883,8 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ }
+}
+
//--------------------------------------------------------------------------------------------------
// Public Code
}
//--------------------------------------------------------------------------------------------------
diff -uNr 05_safe_globals/src/bsp/raspberrypi.rs 06_drivers_gpio_uart/src/bsp/raspberrypi.rs
@ -980,7 +981,7 @@ diff -uNr 05_safe_globals/src/console.rs 06_drivers_gpio_uart/src/console.rs
diff -uNr 05_safe_globals/src/driver.rs 06_drivers_gpio_uart/src/driver.rs
--- 05_safe_globals/src/driver.rs
+++ 06_drivers_gpio_uart/src/driver.rs
@@ -0,0 +1,41 @@
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
@ -993,14 +994,17 @@ diff -uNr 05_safe_globals/src/driver.rs 06_drivers_gpio_uart/src/driver.rs
+
+/// Driver interfaces.
+pub mod interface {
+
+ /// Device Driver functions.
+ pub trait DeviceDriver {
+ /// Return a compatibility string for identifying the driver.
+ fn compatible(&self) -> &str;
+ fn compatible(&self) -> &'static str;
+
+ /// Called by the kernel to bring up the device.
+ fn init(&self) -> Result<(), ()> {
+ ///
+ /// # Safety
+ ///
+ /// - During init, drivers might do stuff with system-wide impact.
+ unsafe fn init(&self) -> Result<(), &'static str> {
+ Ok(())
+ }
+ }
@ -1059,8 +1063,8 @@ diff -uNr 05_safe_globals/src/main.rs 06_drivers_gpio_uart/src/main.rs
+ use driver::interface::DriverManager;
+
+ for i in bsp::driver::driver_manager().all_device_drivers().iter() {
+ if i.init().is_err() {
+ panic!("Error loading driver: {}", i.compatible())
+ if let Err(x) = i.init() {
+ panic!("Error loading driver: {}: {}", i.compatible(), x);
+ }
+ }
+ bsp::driver::driver_manager().post_device_driver_init();

@ -25,7 +25,7 @@ pub unsafe extern "C" fn _start() -> ! {
// Expect the boot core to start in EL2.
if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP.set(bsp::memory::boot_core_stack_end() as u64);
runtime_init::runtime_init()
} else {
// If not core0, infinitely wait for events.

@ -132,7 +132,7 @@ impl GPIO {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM GPIO"
}
}

@ -245,11 +245,11 @@ impl PL011Uart {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM PL011 UART"
}
fn init(&self) -> Result<(), ()> {
unsafe fn init(&self) -> Result<(), &'static str> {
let mut r = &self.inner;
r.lock(|inner| inner.init());

@ -6,30 +6,33 @@
use core::{marker::PhantomData, ops};
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct MMIODerefWrapper<T> {
base_addr: usize,
start_addr: usize,
phantom: PhantomData<T>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl<T> MMIODerefWrapper<T> {
/// Create an instance.
pub const unsafe fn new(base_addr: usize) -> Self {
pub const unsafe fn new(start_addr: usize) -> Self {
Self {
base_addr,
start_addr,
phantom: PhantomData,
}
}
/// Return a pointer to the associated MMIO register block.
fn ptr(&self) -> *const T {
self.base_addr as *const _
}
}
impl<T> ops::Deref for MMIODerefWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
unsafe { &*(self.start_addr as *const _) }
}
}

@ -7,11 +7,11 @@
use crate::driver;
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Definitions
//--------------------------------------------------------------------------------------------------
/// Device Driver Manager type.
pub struct BSPDriverManager {
struct BSPDriverManager {
device_drivers: [&'static (dyn DeviceDriver + Sync); 2],
}

@ -20,12 +20,11 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -54,6 +53,12 @@ pub(super) mod map {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -10,14 +10,17 @@
/// Driver interfaces.
pub mod interface {
/// Device Driver functions.
pub trait DeviceDriver {
/// Return a compatibility string for identifying the driver.
fn compatible(&self) -> &str;
fn compatible(&self) -> &'static str;
/// Called by the kernel to bring up the device.
fn init(&self) -> Result<(), ()> {
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
unsafe fn init(&self) -> Result<(), &'static str> {
Ok(())
}
}

@ -130,8 +130,8 @@ unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
for i in bsp::driver::driver_manager().all_device_drivers().iter() {
if i.init().is_err() {
panic!("Error loading driver: {}", i.compatible())
if let Err(x) = i.init() {
panic!("Error loading driver: {}: {}", i.compatible(), x);
}
}
bsp::driver::driver_manager().post_device_driver_init();

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -187,7 +187,7 @@ diff -uNr 06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs 07_uart_chainloader/src/
// Expect the boot core to start in EL2.
if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP.set(bsp::memory::boot_core_stack_end() as u64);
- runtime_init::runtime_init()
+ relocate::relocate_self::<u64>()
} else {
@ -281,16 +281,60 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/link.ld 07_uart_chainloader/s
diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 07_uart_chainloader/src/bsp/raspberrypi/memory.rs
--- 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
+++ 07_uart_chainloader/src/bsp/raspberrypi/memory.rs
@@ -23,6 +23,9 @@
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
+/// The address on which the Raspberry firmware loads every binary by default.
+pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x80_000;
+
@@ -23,19 +23,21 @@
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
- pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+ pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
- pub const GPIO_OFFSET: usize = 0x0020_0000;
- pub const UART_OFFSET: usize = 0x0020_1000;
+ pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
+
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000;
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
pub mod mmio {
use super::*;
- pub const BASE: usize = 0x3F00_0000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const BASE: usize = 0x3F00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
/// Physical devices.
@@ -43,9 +45,9 @@
pub mod mmio {
use super::*;
- pub const BASE: usize = 0xFE00_0000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const BASE: usize = 0xFE00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
@@ -59,6 +61,12 @@
map::BOOT_CORE_STACK_END
}
+/// The address on which the Raspberry firmware loads every binary by default.
+#[inline(always)]
+pub fn board_default_load_addr() -> usize {
+ map::BOARD_DEFAULT_LOAD_ADDRESS
+}
+
/// Return the range spanning the .bss section.
///
/// # Safety
diff -uNr 06_drivers_gpio_uart/src/console.rs 07_uart_chainloader/src/console.rs
--- 06_drivers_gpio_uart/src/console.rs
@ -379,7 +423,7 @@ diff -uNr 06_drivers_gpio_uart/src/main.rs 07_uart_chainloader/src/main.rs
+ console().write_char('O');
+ console().write_char('K');
+
+ let kernel_addr: *mut u8 = bsp::memory::BOARD_DEFAULT_LOAD_ADDRESS as *mut u8;
+ let kernel_addr: *mut u8 = bsp::memory::board_default_load_addr() as *mut u8;
+ unsafe {
+ // Read the kernel byte by byte.
+ for i in 0..size {
@ -453,7 +497,7 @@ diff -uNr 06_drivers_gpio_uart/src/relocate.rs 07_uart_chainloader/src/relocate.
+ let mut reloc_dst_addr: *mut T = binary_start_addr as *mut T;
+
+ // The address of where the previous firmware loaded us.
+ let mut src_addr: *const T = bsp::memory::BOARD_DEFAULT_LOAD_ADDRESS as *const _;
+ let mut src_addr: *const T = bsp::memory::board_default_load_addr() as *const _;
+
+ // Copy the whole binary.
+ //

@ -25,7 +25,7 @@ pub unsafe extern "C" fn _start() -> ! {
// Expect the boot core to start in EL2.
if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP.set(bsp::memory::boot_core_stack_end() as u64);
relocate::relocate_self::<u64>()
} else {
// If not core0, infinitely wait for events.

@ -132,7 +132,7 @@ impl GPIO {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM GPIO"
}
}

@ -245,11 +245,11 @@ impl PL011Uart {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM PL011 UART"
}
fn init(&self) -> Result<(), ()> {
unsafe fn init(&self) -> Result<(), &'static str> {
let mut r = &self.inner;
r.lock(|inner| inner.init());

@ -6,30 +6,33 @@
use core::{marker::PhantomData, ops};
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct MMIODerefWrapper<T> {
base_addr: usize,
start_addr: usize,
phantom: PhantomData<T>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl<T> MMIODerefWrapper<T> {
/// Create an instance.
pub const unsafe fn new(base_addr: usize) -> Self {
pub const unsafe fn new(start_addr: usize) -> Self {
Self {
base_addr,
start_addr,
phantom: PhantomData,
}
}
/// Return a pointer to the associated MMIO register block.
fn ptr(&self) -> *const T {
self.base_addr as *const _
}
}
impl<T> ops::Deref for MMIODerefWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
unsafe { &*(self.start_addr as *const _) }
}
}

@ -7,11 +7,11 @@
use crate::driver;
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Definitions
//--------------------------------------------------------------------------------------------------
/// Device Driver Manager type.
pub struct BSPDriverManager {
struct BSPDriverManager {
device_drivers: [&'static (dyn DeviceDriver + Sync); 2],
}

@ -20,26 +20,24 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The address on which the Raspberry firmware loads every binary by default.
pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
pub mod mmio {
use super::*;
pub const BASE: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
pub const BASE: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
/// Physical devices.
@ -47,9 +45,9 @@ pub(super) mod map {
pub mod mmio {
use super::*;
pub const BASE: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
pub const BASE: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
@ -57,6 +55,18 @@ pub(super) mod map {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// The address on which the Raspberry firmware loads every binary by default.
#[inline(always)]
pub fn board_default_load_addr() -> usize {
map::BOARD_DEFAULT_LOAD_ADDRESS
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -10,14 +10,17 @@
/// Driver interfaces.
pub mod interface {
/// Device Driver functions.
pub trait DeviceDriver {
/// Return a compatibility string for identifying the driver.
fn compatible(&self) -> &str;
fn compatible(&self) -> &'static str;
/// Called by the kernel to bring up the device.
fn init(&self) -> Result<(), ()> {
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
unsafe fn init(&self) -> Result<(), &'static str> {
Ok(())
}
}

@ -132,8 +132,8 @@ unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
for i in bsp::driver::driver_manager().all_device_drivers().iter() {
if i.init().is_err() {
panic!("Error loading driver: {}", i.compatible())
if let Err(x) = i.init() {
panic!("Error loading driver: {}: {}", i.compatible(), x);
}
}
bsp::driver::driver_manager().post_device_driver_init();
@ -177,7 +177,7 @@ fn kernel_main() -> ! {
console().write_char('O');
console().write_char('K');
let kernel_addr: *mut u8 = bsp::memory::BOARD_DEFAULT_LOAD_ADDRESS as *mut u8;
let kernel_addr: *mut u8 = bsp::memory::board_default_load_addr() as *mut u8;
unsafe {
// Read the kernel byte by byte.
for i in 0..size {

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -31,7 +31,7 @@ pub unsafe fn relocate_self<T>() -> ! {
let mut reloc_dst_addr: *mut T = binary_start_addr as *mut T;
// The address of where the previous firmware loaded us.
let mut src_addr: *const T = bsp::memory::BOARD_DEFAULT_LOAD_ADDRESS as *const _;
let mut src_addr: *const T = bsp::memory::board_default_load_addr() as *const _;
// Copy the whole binary.
//

@ -111,7 +111,7 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/cpu.rs 08_timestamps/src/_arch/a
// Expect the boot core to start in EL2.
if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP.set(bsp::memory::boot_core_stack_end() as u64);
- relocate::relocate_self::<u64>()
+ runtime_init::runtime_init()
} else {
@ -121,7 +121,7 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/cpu.rs 08_timestamps/src/_arch/a
diff -uNr 07_uart_chainloader/src/_arch/aarch64/time.rs 08_timestamps/src/_arch/aarch64/time.rs
--- 07_uart_chainloader/src/_arch/aarch64/time.rs
+++ 08_timestamps/src/_arch/aarch64/time.rs
@@ -0,0 +1,101 @@
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
@ -138,12 +138,8 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/time.rs 08_timestamps/src/_arch/
+
+const NS_PER_S: u64 = 1_000_000_000;
+
+//--------------------------------------------------------------------------------------------------
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// ARMv8 Generic Timer.
+pub struct GenericTimer;
+struct GenericTimer;
+
+//--------------------------------------------------------------------------------------------------
+// Global instances
@ -284,16 +280,60 @@ diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/link.ld 08_timestamps/src/bsp/
diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/memory.rs 08_timestamps/src/bsp/raspberrypi/memory.rs
--- 07_uart_chainloader/src/bsp/raspberrypi/memory.rs
+++ 08_timestamps/src/bsp/raspberrypi/memory.rs
@@ -23,9 +23,6 @@
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
-/// The address on which the Raspberry firmware loads every binary by default.
-pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x80_000;
-
@@ -23,21 +23,19 @@
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
- pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+ pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
- pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
-
- pub const GPIO_OFFSET: usize = 0x0020_0000;
- pub const UART_OFFSET: usize = 0x0020_1000;
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000;
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
pub mod mmio {
use super::*;
- pub const BASE: usize = 0x3F00_0000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const BASE: usize = 0x3F00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
/// Physical devices.
@@ -45,9 +43,9 @@
pub mod mmio {
use super::*;
- pub const BASE: usize = 0xFE00_0000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const BASE: usize = 0xFE00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
@@ -61,12 +59,6 @@
map::BOOT_CORE_STACK_END
}
-/// The address on which the Raspberry firmware loads every binary by default.
-#[inline(always)]
-pub fn board_default_load_addr() -> usize {
- map::BOARD_DEFAULT_LOAD_ADDRESS
-}
-
/// Return the range spanning the .bss section.
///
/// # Safety
diff -uNr 07_uart_chainloader/src/main.rs 08_timestamps/src/main.rs
--- 07_uart_chainloader/src/main.rs
@ -371,7 +411,7 @@ diff -uNr 07_uart_chainloader/src/main.rs 08_timestamps/src/main.rs
- console().write_char('O');
- console().write_char('K');
-
- let kernel_addr: *mut u8 = bsp::memory::BOARD_DEFAULT_LOAD_ADDRESS as *mut u8;
- let kernel_addr: *mut u8 = bsp::memory::board_default_load_addr() as *mut u8;
- unsafe {
- // Read the kernel byte by byte.
- for i in 0..size {
@ -410,7 +450,7 @@ diff -uNr 07_uart_chainloader/src/main.rs 08_timestamps/src/main.rs
diff -uNr 07_uart_chainloader/src/print.rs 08_timestamps/src/print.rs
--- 07_uart_chainloader/src/print.rs
+++ 08_timestamps/src/print.rs
@@ -40,3 +40,71 @@
@@ -36,3 +36,71 @@
$crate::print::_print(format_args_nl!($($arg)*));
})
}
@ -520,7 +560,7 @@ diff -uNr 07_uart_chainloader/src/relocate.rs 08_timestamps/src/relocate.rs
- let mut reloc_dst_addr: *mut T = binary_start_addr as *mut T;
-
- // The address of where the previous firmware loaded us.
- let mut src_addr: *const T = bsp::memory::BOARD_DEFAULT_LOAD_ADDRESS as *const _;
- let mut src_addr: *const T = bsp::memory::board_default_load_addr() as *const _;
-
- // Copy the whole binary.
- //

@ -25,7 +25,7 @@ pub unsafe extern "C" fn _start() -> ! {
// Expect the boot core to start in EL2.
if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP.set(bsp::memory::boot_core_stack_end() as u64);
runtime_init::runtime_init()
} else {
// If not core0, infinitely wait for events.

@ -14,12 +14,8 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// ARMv8 Generic Timer.
pub struct GenericTimer;
struct GenericTimer;
//--------------------------------------------------------------------------------------------------
// Global instances

@ -132,7 +132,7 @@ impl GPIO {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM GPIO"
}
}

@ -245,11 +245,11 @@ impl PL011Uart {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM PL011 UART"
}
fn init(&self) -> Result<(), ()> {
unsafe fn init(&self) -> Result<(), &'static str> {
let mut r = &self.inner;
r.lock(|inner| inner.init());

@ -6,30 +6,33 @@
use core::{marker::PhantomData, ops};
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct MMIODerefWrapper<T> {
base_addr: usize,
start_addr: usize,
phantom: PhantomData<T>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl<T> MMIODerefWrapper<T> {
/// Create an instance.
pub const unsafe fn new(base_addr: usize) -> Self {
pub const unsafe fn new(start_addr: usize) -> Self {
Self {
base_addr,
start_addr,
phantom: PhantomData,
}
}
/// Return a pointer to the associated MMIO register block.
fn ptr(&self) -> *const T {
self.base_addr as *const _
}
}
impl<T> ops::Deref for MMIODerefWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
unsafe { &*(self.start_addr as *const _) }
}
}

@ -7,11 +7,11 @@
use crate::driver;
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Definitions
//--------------------------------------------------------------------------------------------------
/// Device Driver Manager type.
pub struct BSPDriverManager {
struct BSPDriverManager {
device_drivers: [&'static (dyn DeviceDriver + Sync); 2],
}

@ -20,12 +20,11 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -54,6 +53,12 @@ pub(super) mod map {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -10,14 +10,17 @@
/// Driver interfaces.
pub mod interface {
/// Device Driver functions.
pub trait DeviceDriver {
/// Return a compatibility string for identifying the driver.
fn compatible(&self) -> &str;
fn compatible(&self) -> &'static str;
/// Called by the kernel to bring up the device.
fn init(&self) -> Result<(), ()> {
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
unsafe fn init(&self) -> Result<(), &'static str> {
Ok(())
}
}

@ -133,8 +133,8 @@ unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
for i in bsp::driver::driver_manager().all_device_drivers().iter() {
if i.init().is_err() {
panic!("Error loading driver: {}", i.compatible())
if let Err(x) = i.init() {
panic!("Error loading driver: {}: {}", i.compatible(), x);
}
}
bsp::driver::driver_manager().post_device_driver_init();

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -25,7 +25,7 @@ pub unsafe extern "C" fn _start() -> ! {
// Expect the boot core to start in EL2.
if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP.set(bsp::memory::boot_core_stack_end() as u64);
runtime_init::runtime_init()
} else {
// If not core0, infinitely wait for events.

@ -14,12 +14,8 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// ARMv8 Generic Timer.
pub struct GenericTimer;
struct GenericTimer;
//--------------------------------------------------------------------------------------------------
// Global instances

@ -132,7 +132,7 @@ impl GPIO {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM GPIO"
}
}

@ -245,11 +245,11 @@ impl PL011Uart {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM PL011 UART"
}
fn init(&self) -> Result<(), ()> {
unsafe fn init(&self) -> Result<(), &'static str> {
let mut r = &self.inner;
r.lock(|inner| inner.init());

@ -6,30 +6,33 @@
use core::{marker::PhantomData, ops};
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct MMIODerefWrapper<T> {
base_addr: usize,
start_addr: usize,
phantom: PhantomData<T>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl<T> MMIODerefWrapper<T> {
/// Create an instance.
pub const unsafe fn new(base_addr: usize) -> Self {
pub const unsafe fn new(start_addr: usize) -> Self {
Self {
base_addr,
start_addr,
phantom: PhantomData,
}
}
/// Return a pointer to the associated MMIO register block.
fn ptr(&self) -> *const T {
self.base_addr as *const _
}
}
impl<T> ops::Deref for MMIODerefWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
unsafe { &*(self.start_addr as *const _) }
}
}

@ -7,11 +7,11 @@
use crate::driver;
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Definitions
//--------------------------------------------------------------------------------------------------
/// Device Driver Manager type.
pub struct BSPDriverManager {
struct BSPDriverManager {
device_drivers: [&'static (dyn DeviceDriver + Sync); 2],
}

@ -20,12 +20,11 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -54,6 +53,12 @@ pub(super) mod map {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -10,14 +10,17 @@
/// Driver interfaces.
pub mod interface {
/// Device Driver functions.
pub trait DeviceDriver {
/// Return a compatibility string for identifying the driver.
fn compatible(&self) -> &str;
fn compatible(&self) -> &'static str;
/// Called by the kernel to bring up the device.
fn init(&self) -> Result<(), ()> {
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
unsafe fn init(&self) -> Result<(), &'static str> {
Ok(())
}
}

@ -133,8 +133,8 @@ unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
for i in bsp::driver::driver_manager().all_device_drivers().iter() {
if i.init().is_err() {
panic!("Error loading driver: {}", i.compatible())
if let Err(x) = i.init() {
panic!("Error loading driver: {}: {}", i.compatible(), x);
}
}
bsp::driver::driver_manager().post_device_driver_init();

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -233,7 +233,7 @@ diff -uNr 09_hw_debug_JTAG/src/_arch/aarch64/cpu.rs 10_privilege_level/src/_arch
-
// Expect the boot core to start in EL2.
- if bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id() {
- SP.set(bsp::memory::BOOT_CORE_STACK_START as u64);
- SP.set(bsp::memory::boot_core_stack_end() as u64);
- runtime_init::runtime_init()
+ if (bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id())
+ && (CurrentEL.get() == CurrentEL::EL::EL2.value)
@ -281,7 +281,7 @@ diff -uNr 09_hw_debug_JTAG/src/_arch/aarch64/cpu.rs 10_privilege_level/src/_arch
+ ELR_EL2.set(runtime_init::runtime_init as *const () as u64);
+
+ // Set up SP_EL1 (stack pointer), which will be used by EL1 once we "return" to it.
+ SP_EL1.set(bsp::memory::BOOT_CORE_STACK_START as u64);
+ SP_EL1.set(bsp::memory::boot_core_stack_end() as u64);
+
+ // Use `eret` to "return" to EL1. This results in execution of runtime_init() in EL1.
+ asm::eret()

@ -68,7 +68,7 @@ unsafe fn el2_to_el1_transition() -> ! {
ELR_EL2.set(runtime_init::runtime_init as *const () as u64);
// Set up SP_EL1 (stack pointer), which will be used by EL1 once we "return" to it.
SP_EL1.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP_EL1.set(bsp::memory::boot_core_stack_end() as u64);
// Use `eret` to "return" to EL1. This results in execution of runtime_init() in EL1.
asm::eret()

@ -14,12 +14,8 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// ARMv8 Generic Timer.
pub struct GenericTimer;
struct GenericTimer;
//--------------------------------------------------------------------------------------------------
// Global instances

@ -132,7 +132,7 @@ impl GPIO {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM GPIO"
}
}

@ -245,11 +245,11 @@ impl PL011Uart {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM PL011 UART"
}
fn init(&self) -> Result<(), ()> {
unsafe fn init(&self) -> Result<(), &'static str> {
let mut r = &self.inner;
r.lock(|inner| inner.init());

@ -6,30 +6,33 @@
use core::{marker::PhantomData, ops};
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct MMIODerefWrapper<T> {
base_addr: usize,
start_addr: usize,
phantom: PhantomData<T>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl<T> MMIODerefWrapper<T> {
/// Create an instance.
pub const unsafe fn new(base_addr: usize) -> Self {
pub const unsafe fn new(start_addr: usize) -> Self {
Self {
base_addr,
start_addr,
phantom: PhantomData,
}
}
/// Return a pointer to the associated MMIO register block.
fn ptr(&self) -> *const T {
self.base_addr as *const _
}
}
impl<T> ops::Deref for MMIODerefWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
unsafe { &*(self.start_addr as *const _) }
}
}

@ -7,11 +7,11 @@
use crate::driver;
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Definitions
//--------------------------------------------------------------------------------------------------
/// Device Driver Manager type.
pub struct BSPDriverManager {
struct BSPDriverManager {
device_drivers: [&'static (dyn DeviceDriver + Sync); 2],
}

@ -20,12 +20,11 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -54,6 +53,12 @@ pub(super) mod map {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -10,14 +10,17 @@
/// Driver interfaces.
pub mod interface {
/// Device Driver functions.
pub trait DeviceDriver {
/// Return a compatibility string for identifying the driver.
fn compatible(&self) -> &str;
fn compatible(&self) -> &'static str;
/// Called by the kernel to bring up the device.
fn init(&self) -> Result<(), ()> {
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
unsafe fn init(&self) -> Result<(), &'static str> {
Ok(())
}
}

@ -134,8 +134,8 @@ unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
for i in bsp::driver::driver_manager().all_device_drivers().iter() {
if i.init().is_err() {
panic!("Error loading driver: {}", i.compatible())
if let Err(x) = i.init() {
panic!("Error loading driver: {}: {}", i.compatible(), x);
}
}
bsp::driver::driver_manager().post_device_driver_init();

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -440,7 +440,7 @@ diff -uNr 10_privilege_level/src/_arch/aarch64/memory/mmu.rs 11_virtual_memory/s
+///
+/// # Safety
+///
+/// - Supposed to land in `.bss`. Therefore, ensure that they boil down to all "0" entries.
+/// - Supposed to land in `.bss`. Therefore, ensure that all initial member values boil down to "0".
+static mut TABLES: ArchTranslationTable = ArchTranslationTable::new();
+
+static MMU: MemoryManagementUnit = MemoryManagementUnit;
@ -593,7 +593,7 @@ diff -uNr 10_privilege_level/src/_arch/aarch64/memory/mmu.rs 11_virtual_memory/s
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Return a reference to the MMU.
+/// Return a reference to the MMU instance.
+pub fn mmu() -> &'static impl memory::mmu::interface::MMU {
+ &MMU
+}
@ -770,16 +770,16 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_memory/src
static __bss_start: usize;
static __bss_end: usize;
}
@@ -26,6 +30,8 @@
@@ -23,6 +27,8 @@
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
+ pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
+
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
@@ -37,6 +43,7 @@
pub const GPIO_OFFSET: usize = 0x0020_0000;
@@ -36,6 +42,7 @@
pub const BASE: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
@ -787,7 +787,7 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_memory/src
}
/// Physical devices.
@@ -47,10 +54,35 @@
@@ -46,10 +53,35 @@
pub const BASE: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
@ -882,7 +882,7 @@ diff -uNr 10_privilege_level/src/main.rs 11_virtual_memory/src/main.rs
+ }
for i in bsp::driver::driver_manager().all_device_drivers().iter() {
if i.init().is_err() {
if let Err(x) = i.init() {
@@ -154,6 +168,9 @@
info!("Booting on: {}", bsp::board_name());

@ -68,7 +68,7 @@ unsafe fn el2_to_el1_transition() -> ! {
ELR_EL2.set(runtime_init::runtime_init as *const () as u64);
// Set up SP_EL1 (stack pointer), which will be used by EL1 once we "return" to it.
SP_EL1.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP_EL1.set(bsp::memory::boot_core_stack_end() as u64);
// Use `eret` to "return" to EL1. This results in execution of runtime_init() in EL1.
asm::eret()

@ -137,7 +137,7 @@ struct MemoryManagementUnit;
///
/// # Safety
///
/// - Supposed to land in `.bss`. Therefore, ensure that they boil down to all "0" entries.
/// - Supposed to land in `.bss`. Therefore, ensure that all initial member values boil down to "0".
static mut TABLES: ArchTranslationTable = ArchTranslationTable::new();
static MMU: MemoryManagementUnit = MemoryManagementUnit;
@ -290,7 +290,7 @@ fn configure_translation_control() {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the MMU.
/// Return a reference to the MMU instance.
pub fn mmu() -> &'static impl memory::mmu::interface::MMU {
&MMU
}

@ -14,12 +14,8 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// ARMv8 Generic Timer.
pub struct GenericTimer;
struct GenericTimer;
//--------------------------------------------------------------------------------------------------
// Global instances

@ -132,7 +132,7 @@ impl GPIO {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM GPIO"
}
}

@ -245,11 +245,11 @@ impl PL011Uart {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM PL011 UART"
}
fn init(&self) -> Result<(), ()> {
unsafe fn init(&self) -> Result<(), &'static str> {
let mut r = &self.inner;
r.lock(|inner| inner.init());

@ -6,30 +6,33 @@
use core::{marker::PhantomData, ops};
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct MMIODerefWrapper<T> {
base_addr: usize,
start_addr: usize,
phantom: PhantomData<T>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl<T> MMIODerefWrapper<T> {
/// Create an instance.
pub const unsafe fn new(base_addr: usize) -> Self {
pub const unsafe fn new(start_addr: usize) -> Self {
Self {
base_addr,
start_addr,
phantom: PhantomData,
}
}
/// Return a pointer to the associated MMIO register block.
fn ptr(&self) -> *const T {
self.base_addr as *const _
}
}
impl<T> ops::Deref for MMIODerefWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
unsafe { &*(self.start_addr as *const _) }
}
}

@ -7,11 +7,11 @@
use crate::driver;
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Definitions
//--------------------------------------------------------------------------------------------------
/// Device Driver Manager type.
pub struct BSPDriverManager {
struct BSPDriverManager {
device_drivers: [&'static (dyn DeviceDriver + Sync); 2],
}

@ -24,14 +24,13 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -86,6 +85,12 @@ fn ro_end() -> usize {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -10,14 +10,17 @@
/// Driver interfaces.
pub mod interface {
/// Device Driver functions.
pub trait DeviceDriver {
/// Return a compatibility string for identifying the driver.
fn compatible(&self) -> &str;
fn compatible(&self) -> &'static str;
/// Called by the kernel to bring up the device.
fn init(&self) -> Result<(), ()> {
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
unsafe fn init(&self) -> Result<(), &'static str> {
Ok(())
}
}

@ -148,8 +148,8 @@ unsafe fn kernel_init() -> ! {
}
for i in bsp::driver::driver_manager().all_device_drivers().iter() {
if i.init().is_err() {
panic!("Error loading driver: {}", i.compatible())
if let Err(x) = i.init() {
panic!("Error loading driver: {}: {}", i.compatible(), x);
}
}
bsp::driver::driver_manager().post_device_driver_init();

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -525,7 +525,7 @@ diff -uNr 11_virtual_memory/src/_arch/aarch64/exception.rs 12_exceptions_part1_g
+// Private Code
+//--------------------------------------------------------------------------------------------------
+
+/// Print verbose information about the exception and the panic.
+/// Prints verbose information about the exception and then panics.
+fn default_exception_handler(e: &ExceptionContext) {
+ panic!(
+ "\n\nCPU Exception!\n\

@ -68,7 +68,7 @@ unsafe fn el2_to_el1_transition() -> ! {
ELR_EL2.set(runtime_init::runtime_init as *const () as u64);
// Set up SP_EL1 (stack pointer), which will be used by EL1 once we "return" to it.
SP_EL1.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP_EL1.set(bsp::memory::boot_core_stack_end() as u64);
// Use `eret` to "return" to EL1. This results in execution of runtime_init() in EL1.
asm::eret()

@ -42,7 +42,7 @@ struct EsrEL1;
// Private Code
//--------------------------------------------------------------------------------------------------
/// Print verbose information about the exception and the panic.
/// Prints verbose information about the exception and then panics.
fn default_exception_handler(e: &ExceptionContext) {
panic!(
"\n\nCPU Exception!\n\

@ -137,7 +137,7 @@ struct MemoryManagementUnit;
///
/// # Safety
///
/// - Supposed to land in `.bss`. Therefore, ensure that they boil down to all "0" entries.
/// - Supposed to land in `.bss`. Therefore, ensure that all initial member values boil down to "0".
static mut TABLES: ArchTranslationTable = ArchTranslationTable::new();
static MMU: MemoryManagementUnit = MemoryManagementUnit;
@ -290,7 +290,7 @@ fn configure_translation_control() {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the MMU.
/// Return a reference to the MMU instance.
pub fn mmu() -> &'static impl memory::mmu::interface::MMU {
&MMU
}

@ -14,12 +14,8 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// ARMv8 Generic Timer.
pub struct GenericTimer;
struct GenericTimer;
//--------------------------------------------------------------------------------------------------
// Global instances

@ -132,7 +132,7 @@ impl GPIO {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM GPIO"
}
}

@ -245,11 +245,11 @@ impl PL011Uart {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM PL011 UART"
}
fn init(&self) -> Result<(), ()> {
unsafe fn init(&self) -> Result<(), &'static str> {
let mut r = &self.inner;
r.lock(|inner| inner.init());

@ -6,30 +6,33 @@
use core::{marker::PhantomData, ops};
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct MMIODerefWrapper<T> {
base_addr: usize,
start_addr: usize,
phantom: PhantomData<T>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl<T> MMIODerefWrapper<T> {
/// Create an instance.
pub const unsafe fn new(base_addr: usize) -> Self {
pub const unsafe fn new(start_addr: usize) -> Self {
Self {
base_addr,
start_addr,
phantom: PhantomData,
}
}
/// Return a pointer to the associated MMIO register block.
fn ptr(&self) -> *const T {
self.base_addr as *const _
}
}
impl<T> ops::Deref for MMIODerefWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
unsafe { &*(self.start_addr as *const _) }
}
}

@ -7,11 +7,11 @@
use crate::driver;
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Definitions
//--------------------------------------------------------------------------------------------------
/// Device Driver Manager type.
pub struct BSPDriverManager {
struct BSPDriverManager {
device_drivers: [&'static (dyn DeviceDriver + Sync); 2],
}

@ -24,14 +24,13 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -86,6 +85,12 @@ fn ro_end() -> usize {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -10,14 +10,17 @@
/// Driver interfaces.
pub mod interface {
/// Device Driver functions.
pub trait DeviceDriver {
/// Return a compatibility string for identifying the driver.
fn compatible(&self) -> &str;
fn compatible(&self) -> &'static str;
/// Called by the kernel to bring up the device.
fn init(&self) -> Result<(), ()> {
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
unsafe fn init(&self) -> Result<(), &'static str> {
Ok(())
}
}

@ -151,8 +151,8 @@ unsafe fn kernel_init() -> ! {
}
for i in bsp::driver::driver_manager().all_device_drivers().iter() {
if i.init().is_err() {
panic!("Error loading driver: {}", i.compatible())
if let Err(x) = i.init() {
panic!("Error loading driver: {}: {}", i.compatible(), x);
}
}
bsp::driver::driver_manager().post_device_driver_init();

@ -8,7 +8,7 @@ use crate::{bsp, console};
use core::fmt;
//--------------------------------------------------------------------------------------------------
// Private Code
// Public Code
//--------------------------------------------------------------------------------------------------
#[doc(hidden)]
@ -18,10 +18,6 @@ pub fn _print(args: fmt::Arguments) {
bsp::console::console().write_fmt(args).unwrap();
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html

@ -1000,7 +1000,7 @@ diff -uNr 12_exceptions_part1_groundwork/src/bsp/raspberrypi/console.rs 13_integ
diff -uNr 12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs 13_integrated_testing/src/bsp/raspberrypi/memory/mmu.rs
--- 12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs
+++ 13_integrated_testing/src/bsp/raspberrypi/memory/mmu.rs
@@ -71,3 +71,28 @@
@@ -71,3 +71,46 @@
pub fn virt_mem_layout() -> &'static KernelVirtualLayout<{ NUM_MEM_RANGES }> {
&LAYOUT
}
@ -1014,7 +1014,7 @@ diff -uNr 12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs 13_in
+ use super::*;
+ use test_macros::kernel_test;
+
+ /// Check 64 KiB alignment of the kernel's virtual memory layout sections.
+ /// Check alignment of the kernel's virtual memory layout sections.
+ #[kernel_test]
+ fn virt_mem_layout_sections_are_64KiB_aligned() {
+ const SIXTYFOUR_KIB: usize = 65536;
@ -1028,29 +1028,11 @@ diff -uNr 12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs 13_in
+ assert!(end >= start);
+ }
+ }
+}
diff -uNr 12_exceptions_part1_groundwork/src/bsp.rs 13_integrated_testing/src/bsp.rs
--- 12_exceptions_part1_groundwork/src/bsp.rs
+++ 13_integrated_testing/src/bsp.rs
@@ -11,3 +11,31 @@
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
pub use raspberrypi::*;
+
+//--------------------------------------------------------------------------------------------------
+// Testing
+//--------------------------------------------------------------------------------------------------
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use test_macros::kernel_test;
+
+ /// Ensure the kernel's virtual memory layout is free of overlaps.
+ #[kernel_test]
+ fn virt_mem_layout_has_no_overlaps() {
+ let layout = memory::mmu::virt_mem_layout().inner();
+ let layout = virt_mem_layout().inner();
+
+ for (i, first) in layout.iter().enumerate() {
+ for second in layout.iter().skip(i + 1) {

@ -68,7 +68,7 @@ unsafe fn el2_to_el1_transition() -> ! {
ELR_EL2.set(runtime_init::runtime_init as *const () as u64);
// Set up SP_EL1 (stack pointer), which will be used by EL1 once we "return" to it.
SP_EL1.set(bsp::memory::BOOT_CORE_STACK_START as u64);
SP_EL1.set(bsp::memory::boot_core_stack_end() as u64);
// Use `eret` to "return" to EL1. This results in execution of runtime_init() in EL1.
asm::eret()

@ -42,7 +42,7 @@ struct EsrEL1;
// Private Code
//--------------------------------------------------------------------------------------------------
/// Print verbose information about the exception and the panic.
/// Prints verbose information about the exception and then panics.
fn default_exception_handler(e: &ExceptionContext) {
panic!(
"\n\nCPU Exception!\n\

@ -137,7 +137,7 @@ struct MemoryManagementUnit;
///
/// # Safety
///
/// - Supposed to land in `.bss`. Therefore, ensure that they boil down to all "0" entries.
/// - Supposed to land in `.bss`. Therefore, ensure that all initial member values boil down to "0".
static mut TABLES: ArchTranslationTable = ArchTranslationTable::new();
static MMU: MemoryManagementUnit = MemoryManagementUnit;
@ -290,7 +290,7 @@ fn configure_translation_control() {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the MMU.
/// Return a reference to the MMU instance.
pub fn mmu() -> &'static impl memory::mmu::interface::MMU {
&MMU
}

@ -14,12 +14,8 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// ARMv8 Generic Timer.
pub struct GenericTimer;
struct GenericTimer;
//--------------------------------------------------------------------------------------------------
// Global instances

@ -11,31 +11,3 @@ mod raspberrypi;
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
pub use raspberrypi::*;
//--------------------------------------------------------------------------------------------------
// Testing
//--------------------------------------------------------------------------------------------------
#[cfg(test)]
mod tests {
use super::*;
use test_macros::kernel_test;
/// Ensure the kernel's virtual memory layout is free of overlaps.
#[kernel_test]
fn virt_mem_layout_has_no_overlaps() {
let layout = memory::mmu::virt_mem_layout().inner();
for (i, first) in layout.iter().enumerate() {
for second in layout.iter().skip(i + 1) {
let first_range = first.virtual_range;
let second_range = second.virtual_range;
assert!(!first_range().contains(second_range().start()));
assert!(!first_range().contains(second_range().end()));
assert!(!second_range().contains(first_range().start()));
assert!(!second_range().contains(first_range().end()));
}
}
}
}

@ -132,7 +132,7 @@ impl GPIO {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM GPIO"
}
}

@ -245,11 +245,11 @@ impl PL011Uart {
use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &str {
fn compatible(&self) -> &'static str {
"BCM PL011 UART"
}
fn init(&self) -> Result<(), ()> {
unsafe fn init(&self) -> Result<(), &'static str> {
let mut r = &self.inner;
r.lock(|inner| inner.init());

@ -6,30 +6,33 @@
use core::{marker::PhantomData, ops};
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct MMIODerefWrapper<T> {
base_addr: usize,
start_addr: usize,
phantom: PhantomData<T>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl<T> MMIODerefWrapper<T> {
/// Create an instance.
pub const unsafe fn new(base_addr: usize) -> Self {
pub const unsafe fn new(start_addr: usize) -> Self {
Self {
base_addr,
start_addr,
phantom: PhantomData,
}
}
/// Return a pointer to the associated MMIO register block.
fn ptr(&self) -> *const T {
self.base_addr as *const _
}
}
impl<T> ops::Deref for MMIODerefWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
unsafe { &*(self.start_addr as *const _) }
}
}

@ -7,11 +7,11 @@
use crate::driver;
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Definitions
//--------------------------------------------------------------------------------------------------
/// Device Driver Manager type.
pub struct BSPDriverManager {
struct BSPDriverManager {
device_drivers: [&'static (dyn DeviceDriver + Sync); 2],
}

@ -24,14 +24,13 @@ extern "C" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -86,6 +85,12 @@ fn ro_end() -> usize {
// Public Code
//--------------------------------------------------------------------------------------------------
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
}
/// Return the range spanning the .bss section.
///
/// # Safety

@ -81,7 +81,7 @@ mod tests {
use super::*;
use test_macros::kernel_test;
/// Check 64 KiB alignment of the kernel's virtual memory layout sections.
/// Check alignment of the kernel's virtual memory layout sections.
#[kernel_test]
fn virt_mem_layout_sections_are_64KiB_aligned() {
const SIXTYFOUR_KIB: usize = 65536;
@ -95,4 +95,22 @@ mod tests {
assert!(end >= start);
}
}
/// Ensure the kernel's virtual memory layout is free of overlaps.
#[kernel_test]
fn virt_mem_layout_has_no_overlaps() {
let layout = virt_mem_layout().inner();
for (i, first) in layout.iter().enumerate() {
for second in layout.iter().skip(i + 1) {
let first_range = first.virtual_range;
let second_range = second.virtual_range;
assert!(!first_range().contains(second_range().start()));
assert!(!first_range().contains(second_range().end()));
assert!(!second_range().contains(first_range().start()));
assert!(!second_range().contains(first_range().end()));
}
}
}
}

@ -10,14 +10,17 @@
/// Driver interfaces.
pub mod interface {
/// Device Driver functions.
pub trait DeviceDriver {
/// Return a compatibility string for identifying the driver.
fn compatible(&self) -> &str;
fn compatible(&self) -> &'static str;
/// Called by the kernel to bring up the device.
fn init(&self) -> Result<(), ()> {
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
unsafe fn init(&self) -> Result<(), &'static str> {
Ok(())
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save