Move anything wrt linker symbols to bsp::memory

Also, some rewording of data types.
pull/84/head
Andre Richter 4 years ago
parent af0214f0f6
commit 37b9d1435e
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -74,6 +74,57 @@ diff -uNr 01_wait_forever/src/bsp/raspberrypi/link.ld 02_runtime_init/src/bsp/ra
/DISCARD/ : { *(.comment*) }
}
diff -uNr 01_wait_forever/src/bsp/raspberrypi/memory.rs 02_runtime_init/src/bsp/raspberrypi/memory.rs
--- 01_wait_forever/src/bsp/raspberrypi/memory.rs
+++ 02_runtime_init/src/bsp/raspberrypi/memory.rs
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
+
+//! BSP Memory Management.
+
+use core::ops::Range;
+
+//--------------------------------------------------------------------------------------------------
+// Private Definitions
+//--------------------------------------------------------------------------------------------------
+
+// Symbols from the linker script.
+extern "C" {
+ static __bss_start: usize;
+ static __bss_end: usize;
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Return the range spanning the .bss section.
+///
+/// # Safety
+///
+/// - Values are provided by the linker script and must be trusted as-is.
+/// - The linker-provided addresses must be u64 aligned.
+pub fn bss_range() -> Range<*mut u64> {
+ unsafe {
+ Range {
+ start: &__bss_start as *const _ as *mut u64,
+ end: &__bss_end as *const _ as *mut u64,
+ }
+ }
+}
diff -uNr 01_wait_forever/src/bsp/raspberrypi.rs 02_runtime_init/src/bsp/raspberrypi.rs
--- 01_wait_forever/src/bsp/raspberrypi.rs
+++ 02_runtime_init/src/bsp/raspberrypi.rs
@@ -4,4 +4,4 @@
//! Top-level BSP file for the Raspberry Pi 3 and 4.
-// Coming soon.
+pub mod memory;
diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs
--- 01_wait_forever/src/main.rs
+++ 02_runtime_init/src/main.rs
@ -117,7 +168,7 @@ diff -uNr 01_wait_forever/src/memory.rs 02_runtime_init/src/memory.rs
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Zero out a memory region.
+/// Zero out a memory range.
+///
+/// # Safety
+///
@ -138,39 +189,19 @@ diff -uNr 01_wait_forever/src/memory.rs 02_runtime_init/src/memory.rs
diff -uNr 01_wait_forever/src/runtime_init.rs 02_runtime_init/src/runtime_init.rs
--- 01_wait_forever/src/runtime_init.rs
+++ 02_runtime_init/src/runtime_init.rs
@@ -0,0 +1,58 @@
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
+
+//! Rust runtime initialization code.
+
+use crate::memory;
+use core::ops::Range;
+use crate::{bsp, memory};
+
+//--------------------------------------------------------------------------------------------------
+// Private Code
+//--------------------------------------------------------------------------------------------------
+
+/// Return the range spanning the .bss section.
+///
+/// # Safety
+///
+/// - The symbol-provided addresses must be valid.
+/// - The symbol-provided addresses must be usize aligned.
+unsafe fn bss_range() -> Range<*mut usize> {
+ extern "C" {
+ // Boundaries of the .bss section, provided by linker script symbols.
+ static mut __bss_start: usize;
+ static mut __bss_end: usize;
+ }
+
+ Range {
+ start: &mut __bss_start,
+ end: &mut __bss_end,
+ }
+}
+
+/// Zero out the .bss section.
+///
+/// # Safety
@ -178,7 +209,7 @@ diff -uNr 01_wait_forever/src/runtime_init.rs 02_runtime_init/src/runtime_init.r
+/// - Must only be called pre `kernel_init()`.
+#[inline(always)]
+unsafe fn zero_bss() {
+ memory::zero_volatile(bss_range());
+ memory::zero_volatile(bsp::memory::bss_range());
+}
+
+//--------------------------------------------------------------------------------------------------

@ -4,4 +4,4 @@
//! Top-level BSP file for the Raspberry Pi 3 and 4.
// Coming soon.
pub mod memory;

@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -105,12 +105,12 @@ diff -uNr 02_runtime_init/src/bsp/raspberrypi/console.rs 03_hacky_hello_world/sr
diff -uNr 02_runtime_init/src/bsp/raspberrypi.rs 03_hacky_hello_world/src/bsp/raspberrypi.rs
--- 02_runtime_init/src/bsp/raspberrypi.rs
+++ 03_hacky_hello_world/src/bsp/raspberrypi.rs
@@ -4,4 +4,4 @@
@@ -4,4 +4,5 @@
//! Top-level BSP file for the Raspberry Pi 3 and 4.
-// Coming soon.
+pub mod console;
pub mod memory;
diff -uNr 02_runtime_init/src/console.rs 03_hacky_hello_world/src/console.rs
--- 02_runtime_init/src/console.rs

@ -5,3 +5,4 @@
//! Top-level BSP file for the Raspberry Pi 3 and 4.
pub mod console;
pub mod memory;

@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -157,29 +157,30 @@ 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
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
+
+//! BSP Memory Management.
+
+//--------------------------------------------------------------------------------------------------
@@ -17,6 +17,13 @@
}
//--------------------------------------------------------------------------------------------------
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// The early boot core's stack address.
+pub const BOOT_CORE_STACK_START: usize = 0x80_000;
+
+//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
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
+++ 04_zero_overhead_abstraction/src/bsp/raspberrypi.rs
@@ -5,3 +5,5 @@
@@ -5,4 +5,5 @@
//! Top-level BSP file for the Raspberry Pi 3 and 4.
pub mod console;
+pub mod cpu;
+pub mod memory;
pub mod memory;
diff -uNr 03_hacky_hello_world/src/cpu/smp.rs 04_zero_overhead_abstraction/src/cpu/smp.rs
--- 03_hacky_hello_world/src/cpu/smp.rs
@ -235,7 +236,7 @@ diff -uNr 03_hacky_hello_world/src/main.rs 04_zero_overhead_abstraction/src/main
diff -uNr 03_hacky_hello_world/src/runtime_init.rs 04_zero_overhead_abstraction/src/runtime_init.rs
--- 03_hacky_hello_world/src/runtime_init.rs
+++ 04_zero_overhead_abstraction/src/runtime_init.rs
@@ -50,8 +50,7 @@
@@ -30,8 +30,7 @@
/// # Safety
///
/// - Only a single core must be active and running this function.

@ -4,9 +4,40 @@
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -4,9 +4,40 @@
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -851,11 +851,10 @@ 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
@@ -10,3 +10,30 @@
@@ -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 {
@ -882,6 +881,10 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src
+ 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
--- 05_safe_globals/src/bsp/raspberrypi.rs

@ -4,6 +4,18 @@
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -37,3 +49,22 @@ pub(super) mod map {
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -281,7 +281,7 @@ 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
@@ -11,6 +11,9 @@
@@ -23,6 +23,9 @@
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
@ -476,8 +476,8 @@ diff -uNr 06_drivers_gpio_uart/src/relocate.rs 07_uart_chainloader/src/relocate.
diff -uNr 06_drivers_gpio_uart/src/runtime_init.rs 07_uart_chainloader/src/runtime_init.rs
--- 06_drivers_gpio_uart/src/runtime_init.rs
+++ 07_uart_chainloader/src/runtime_init.rs
@@ -8,9 +8,43 @@
use core::ops::Range;
@@ -7,9 +7,43 @@
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
+// Private Definitions
@ -517,10 +517,10 @@ diff -uNr 06_drivers_gpio_uart/src/runtime_init.rs 07_uart_chainloader/src/runti
+impl RunTimeInit for Traitor {}
+
/// Return the range spanning the .bss section.
/// Zero out the .bss section.
///
/// # Safety
@@ -44,14 +78,7 @@
@@ -24,14 +58,7 @@
// Public Code
//--------------------------------------------------------------------------------------------------

@ -4,6 +4,18 @@
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -40,3 +52,22 @@ pub(super) mod map {
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,8 +4,7 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Definitions
@ -45,25 +44,6 @@ pub trait RunTimeInit {
impl RunTimeInit for Traitor {}
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -71,7 +51,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -284,7 +284,7 @@ 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
@@ -11,9 +11,6 @@
@@ -23,9 +23,6 @@
/// The early boot core's stack address.
pub const BOOT_CORE_STACK_START: usize = 0x80_000;
@ -543,8 +543,8 @@ diff -uNr 07_uart_chainloader/src/relocate.rs 08_timestamps/src/relocate.rs
diff -uNr 07_uart_chainloader/src/runtime_init.rs 08_timestamps/src/runtime_init.rs
--- 07_uart_chainloader/src/runtime_init.rs
+++ 08_timestamps/src/runtime_init.rs
@@ -8,43 +8,9 @@
use core::ops::Range;
@@ -7,43 +7,9 @@
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
-// Private Definitions
@ -584,10 +584,10 @@ diff -uNr 07_uart_chainloader/src/runtime_init.rs 08_timestamps/src/runtime_init
-impl RunTimeInit for Traitor {}
-
/// Return the range spanning the .bss section.
/// Zero out the .bss section.
///
/// # Safety
@@ -78,7 +44,14 @@
@@ -58,7 +24,14 @@
// Public Code
//--------------------------------------------------------------------------------------------------

@ -4,6 +4,18 @@
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -37,3 +49,22 @@ pub(super) mod map {
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -4,6 +4,18 @@
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -37,3 +49,22 @@ pub(super) mod map {
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -4,6 +4,18 @@
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -37,3 +49,22 @@ pub(super) mod map {
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -46,7 +46,7 @@ Back from reading `Chapter 12` already? Good job :+1:!
for composing a high-level data structure that describes the kernel's virtual memory layout:
`memory::mmu::KernelVirtualLayout`.
2. The `BSP` part: `src/bsp/raspberrypi/memory/mmu.rs` contains a static instance of
`KernelVirtualLayout` and makes it accessible throug the function
`KernelVirtualLayout` and makes it accessible through the function
`bsp::memory::mmu::virt_mem_layout()`.
3. The `aarch64` part: `src/_arch/aarch64/memory/mmu.rs` contains the actual `MMU` driver. It picks
up the `BSP`'s high-level `KernelVirtualLayout` and maps it using a `64 KiB` granule.
@ -54,7 +54,7 @@ Back from reading `Chapter 12` already? Good job :+1:!
### Generic Kernel code: `memory/mmu.rs`
The descriptor types provided in this file are building blocks which help to describe attributes of
different memory regions. For example, R/W, no-execute, cached/uncached, and so on.
different memory regions. For example, `R/W`, `no-execute`, `cached/uncached`, and so on.
The descriptors are agnostic of the hardware `MMU`'s actual descriptors. Different `BSP`s can use
these types to produce a high-level description of the kernel's virtual memory layout. The actual
@ -74,12 +74,10 @@ nothing prevents you from defining those too if you wish to. Here is an example
region:
```rust
RangeDescriptor {
TranslationDescriptor {
name: "Device MMIO",
virtual_range: || {
RangeInclusive::new(memory::map::mmio::BASE, memory::map::mmio::END_INCLUSIVE)
},
translation: Translation::Identity,
virtual_range: mmio_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::Device,
acc_perms: AccessPermissions::ReadWrite,
@ -98,10 +96,11 @@ pub fn virt_addr_properties(
```
It will be used by the `_arch/aarch64`'s `MMU` code to request attributes for a virtual address and
the translation of the address. The function scans for a descriptor that contains the queried
address, and returns the respective findings for the first entry that is a hit. If no entry is
found, it returns default attributes for normal chacheable DRAM and the input address, hence telling
the `MMU` code that the requested address should be `identity mapped`.
the translation, which delivers the physical output address (the `usize` in the return-tuple). The
function scans for a descriptor that contains the queried address, and returns the respective
findings for the first entry that is a hit. If no entry is found, it returns default attributes for
normal chacheable DRAM and the input address, hence telling the `MMU` code that the requested
address should be `identity mapped`.
Due to this default return, it is technicall not needed to define normal cacheable DRAM regions.
@ -644,7 +643,7 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/link.ld 11_virtual_memory/src/b
diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs 11_virtual_memory/src/bsp/raspberrypi/memory/mmu.rs
--- 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs
+++ 11_virtual_memory/src/bsp/raspberrypi/memory/mmu.rs
@@ -0,0 +1,97 @@
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
@ -668,58 +667,30 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs 11_virtual_memory
+pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout::new(
+ memory_map::END_INCLUSIVE,
+ [
+ RangeDescriptor {
+ TranslationDescriptor {
+ name: "Kernel code and RO data",
+ virtual_range: || {
+ // Using the linker script, we ensure that the RO area is consecutive and 64 KiB
+ // aligned, and we export the boundaries via symbols:
+ //
+ // [__ro_start, __ro_end)
+ extern "C" {
+ // The inclusive start of the read-only area, aka the address of the first
+ // byte of the area.
+ static __ro_start: usize;
+
+ // The exclusive end of the read-only area, aka the address of the first
+ // byte _after_ the RO area.
+ static __ro_end: usize;
+ }
+
+ unsafe {
+ // Notice the subtraction to turn the exclusive end into an inclusive end.
+ #[allow(clippy::range_minus_one)]
+ RangeInclusive::new(
+ &__ro_start as *const _ as usize,
+ &__ro_end as *const _ as usize - 1,
+ )
+ }
+ },
+ translation: Translation::Identity,
+ virtual_range: ro_range_inclusive,
+ physical_range_translation: Translation::Identity,
+ attribute_fields: AttributeFields {
+ mem_attributes: MemAttributes::CacheableDRAM,
+ acc_perms: AccessPermissions::ReadOnly,
+ execute_never: false,
+ },
+ },
+ RangeDescriptor {
+ TranslationDescriptor {
+ name: "Remapped Device MMIO",
+ virtual_range: || {
+ // The last 64 KiB slot in the first 512 MiB
+ RangeInclusive::new(0x1FFF_0000, 0x1FFF_FFFF)
+ },
+ translation: Translation::Offset(memory_map::mmio::BASE + 0x20_0000),
+ virtual_range: remapped_mmio_range_inclusive,
+ physical_range_translation: Translation::Offset(memory_map::mmio::BASE + 0x20_0000),
+ attribute_fields: AttributeFields {
+ mem_attributes: MemAttributes::Device,
+ acc_perms: AccessPermissions::ReadWrite,
+ execute_never: true,
+ },
+ },
+ RangeDescriptor {
+ TranslationDescriptor {
+ name: "Device MMIO",
+ virtual_range: || {
+ RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
+ },
+ translation: Translation::Identity,
+ virtual_range: mmio_range_inclusive,
+ physical_range_translation: Translation::Identity,
+ attribute_fields: AttributeFields {
+ mem_attributes: MemAttributes::Device,
+ acc_perms: AccessPermissions::ReadWrite,
@ -730,6 +701,25 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs 11_virtual_memory
+);
+
+//--------------------------------------------------------------------------------------------------
+// Private Code
+//--------------------------------------------------------------------------------------------------
+
+fn ro_range_inclusive() -> RangeInclusive<usize> {
+ // Notice the subtraction to turn the exclusive end into an inclusive end.
+ #[allow(clippy::range_minus_one)]
+ RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
+}
+
+fn remapped_mmio_range_inclusive() -> RangeInclusive<usize> {
+ // The last 64 KiB slot in the first 512 MiB
+ RangeInclusive::new(0x1FFF_0000, 0x1FFF_FFFF)
+}
+
+fn mmio_range_inclusive() -> RangeInclusive<usize> {
+ RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
@ -752,10 +742,19 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_memory/src
+pub mod mmu;
+
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@@ -14,6 +16,8 @@
@@ -12,6 +14,8 @@
// Symbols from the linker script.
extern "C" {
+ static __ro_start: usize;
+ static __ro_end: usize;
static __bss_start: usize;
static __bss_end: usize;
}
@@ -26,6 +30,8 @@
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
@ -764,7 +763,7 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_memory/src
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@@ -25,6 +29,7 @@
@@ -37,6 +43,7 @@
pub const BASE: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
@ -772,7 +771,7 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_memory/src
}
/// Physical devices.
@@ -35,5 +40,6 @@
@@ -47,10 +54,35 @@
pub const BASE: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
@ -780,6 +779,35 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_memory/src
}
}
//--------------------------------------------------------------------------------------------------
+// Private Code
+//--------------------------------------------------------------------------------------------------
+
+/// Start address of the Read-Only (RO) range.
+///
+/// # Safety
+///
+/// - Value is provided by the linker script and must be trusted as-is.
+#[inline(always)]
+fn ro_start() -> usize {
+ unsafe { &__ro_start as *const _ as usize }
+}
+
+/// Size of the Read-Only (RO) range of the kernel binary.
+///
+/// # Safety
+///
+/// - Value is provided by the linker script and must be trusted as-is.
+#[inline(always)]
+fn ro_end() -> usize {
+ unsafe { &__ro_end as *const _ as usize }
+}
+
+//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
diff -uNr 10_privilege_level/src/bsp.rs 11_virtual_memory/src/bsp.rs
--- 10_privilege_level/src/bsp.rs
+++ 11_virtual_memory/src/bsp.rs
@ -866,7 +894,7 @@ diff -uNr 10_privilege_level/src/main.rs 11_virtual_memory/src/main.rs
diff -uNr 10_privilege_level/src/memory/mmu.rs 11_virtual_memory/src/memory/mmu.rs
--- 10_privilege_level/src/memory/mmu.rs
+++ 11_virtual_memory/src/memory/mmu.rs
@@ -0,0 +1,198 @@
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2020 Andre Richter <andre.o.richter@gmail.com>
@ -944,10 +972,10 @@ diff -uNr 10_privilege_level/src/memory/mmu.rs 11_virtual_memory/src/memory/mmu.
+
+/// Architecture agnostic descriptor for a memory range.
+#[allow(missing_docs)]
+pub struct RangeDescriptor {
+pub struct TranslationDescriptor {
+ pub name: &'static str,
+ pub virtual_range: fn() -> RangeInclusive<usize>,
+ pub translation: Translation,
+ pub physical_range_translation: Translation,
+ pub attribute_fields: AttributeFields,
+}
+
@ -957,7 +985,7 @@ diff -uNr 10_privilege_level/src/memory/mmu.rs 11_virtual_memory/src/memory/mmu.
+ max_virt_addr_inclusive: usize,
+
+ /// Array of descriptors for non-standard (normal cacheable DRAM) memory regions.
+ inner: [RangeDescriptor; NUM_SPECIAL_RANGES],
+ inner: [TranslationDescriptor; NUM_SPECIAL_RANGES],
+}
+
+//--------------------------------------------------------------------------------------------------
@ -974,8 +1002,8 @@ diff -uNr 10_privilege_level/src/memory/mmu.rs 11_virtual_memory/src/memory/mmu.
+ }
+}
+
+/// Human-readable output of a RangeDescriptor.
+impl fmt::Display for RangeDescriptor {
+/// Human-readable output of a TranslationDescriptor.
+impl fmt::Display for TranslationDescriptor {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ // Call the function to which self.range points, and dereference the result, which causes
+ // Rust to copy the value.
@ -1023,14 +1051,15 @@ diff -uNr 10_privilege_level/src/memory/mmu.rs 11_virtual_memory/src/memory/mmu.
+
+impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }> {
+ /// Create a new instance.
+ pub const fn new(max: usize, layout: [RangeDescriptor; NUM_SPECIAL_RANGES]) -> Self {
+ pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL_RANGES]) -> Self {
+ Self {
+ max_virt_addr_inclusive: max,
+ inner: layout,
+ }
+ }
+
+ /// For a virtual address, find and return the output address and corresponding attributes.
+ /// For a virtual address, find and return the physical output address and corresponding
+ /// attributes.
+ ///
+ /// If the address is not found in `inner`, return an identity mapped default with normal
+ /// cacheable DRAM attributes.
@ -1044,7 +1073,7 @@ diff -uNr 10_privilege_level/src/memory/mmu.rs 11_virtual_memory/src/memory/mmu.
+
+ for i in self.inner.iter() {
+ if (i.virtual_range)().contains(&virt_addr) {
+ let output_addr = match i.translation {
+ let output_addr = match i.physical_range_translation {
+ Translation::Identity => virt_addr,
+ Translation::Offset(a) => a + (virt_addr - (i.virtual_range)().start()),
+ };

@ -6,6 +6,20 @@
pub mod mmu;
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __ro_start: usize;
static __ro_end: usize;
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -43,3 +57,46 @@ pub(super) mod map {
pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
}
}
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read-Only (RO) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_start() -> usize {
unsafe { &__ro_start as *const _ as usize }
}
/// Size of the Read-Only (RO) range of the kernel binary.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_end() -> usize {
unsafe { &__ro_end as *const _ as usize }
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -21,58 +21,30 @@ const NUM_MEM_RANGES: usize = 3;
pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout::new(
memory_map::END_INCLUSIVE,
[
RangeDescriptor {
TranslationDescriptor {
name: "Kernel code and RO data",
virtual_range: || {
// Using the linker script, we ensure that the RO area is consecutive and 64 KiB
// aligned, and we export the boundaries via symbols:
//
// [__ro_start, __ro_end)
extern "C" {
// The inclusive start of the read-only area, aka the address of the first
// byte of the area.
static __ro_start: usize;
// The exclusive end of the read-only area, aka the address of the first
// byte _after_ the RO area.
static __ro_end: usize;
}
unsafe {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(
&__ro_start as *const _ as usize,
&__ro_end as *const _ as usize - 1,
)
}
},
translation: Translation::Identity,
virtual_range: ro_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
acc_perms: AccessPermissions::ReadOnly,
execute_never: false,
},
},
RangeDescriptor {
TranslationDescriptor {
name: "Remapped Device MMIO",
virtual_range: || {
// The last 64 KiB slot in the first 512 MiB
RangeInclusive::new(0x1FFF_0000, 0x1FFF_FFFF)
},
translation: Translation::Offset(memory_map::mmio::BASE + 0x20_0000),
virtual_range: remapped_mmio_range_inclusive,
physical_range_translation: Translation::Offset(memory_map::mmio::BASE + 0x20_0000),
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::Device,
acc_perms: AccessPermissions::ReadWrite,
execute_never: true,
},
},
RangeDescriptor {
TranslationDescriptor {
name: "Device MMIO",
virtual_range: || {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
},
translation: Translation::Identity,
virtual_range: mmio_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::Device,
acc_perms: AccessPermissions::ReadWrite,
@ -82,6 +54,25 @@ pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout
],
);
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
fn ro_range_inclusive() -> RangeInclusive<usize> {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
}
fn remapped_mmio_range_inclusive() -> RangeInclusive<usize> {
// The last 64 KiB slot in the first 512 MiB
RangeInclusive::new(0x1FFF_0000, 0x1FFF_FFFF)
}
fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

@ -12,7 +12,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -75,10 +75,10 @@ pub struct AttributeFields {
/// Architecture agnostic descriptor for a memory range.
#[allow(missing_docs)]
pub struct RangeDescriptor {
pub struct TranslationDescriptor {
pub name: &'static str,
pub virtual_range: fn() -> RangeInclusive<usize>,
pub translation: Translation,
pub physical_range_translation: Translation,
pub attribute_fields: AttributeFields,
}
@ -88,7 +88,7 @@ pub struct KernelVirtualLayout<const NUM_SPECIAL_RANGES: usize> {
max_virt_addr_inclusive: usize,
/// Array of descriptors for non-standard (normal cacheable DRAM) memory regions.
inner: [RangeDescriptor; NUM_SPECIAL_RANGES],
inner: [TranslationDescriptor; NUM_SPECIAL_RANGES],
}
//--------------------------------------------------------------------------------------------------
@ -105,8 +105,8 @@ impl Default for AttributeFields {
}
}
/// Human-readable output of a RangeDescriptor.
impl fmt::Display for RangeDescriptor {
/// Human-readable output of a TranslationDescriptor.
impl fmt::Display for TranslationDescriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Call the function to which self.range points, and dereference the result, which causes
// Rust to copy the value.
@ -154,14 +154,15 @@ impl fmt::Display for RangeDescriptor {
impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }> {
/// Create a new instance.
pub const fn new(max: usize, layout: [RangeDescriptor; NUM_SPECIAL_RANGES]) -> Self {
pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL_RANGES]) -> Self {
Self {
max_virt_addr_inclusive: max,
inner: layout,
}
}
/// For a virtual address, find and return the output address and corresponding attributes.
/// For a virtual address, find and return the physical output address and corresponding
/// attributes.
///
/// If the address is not found in `inner`, return an identity mapped default with normal
/// cacheable DRAM attributes.
@ -175,7 +176,7 @@ impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }
for i in self.inner.iter() {
if (i.virtual_range)().contains(&virt_addr) {
let output_addr = match i.translation {
let output_addr = match i.physical_range_translation {
Translation::Identity => virt_addr,
Translation::Offset(a) => a + (virt_addr - (i.virtual_range)().start()),
};

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -911,26 +911,35 @@ diff -uNr 11_virtual_memory/src/bsp/raspberrypi/memory/mmu.rs 12_exceptions_part
/// The virtual memory layout.
///
@@ -55,19 +55,6 @@
@@ -32,16 +32,6 @@
},
},
RangeDescriptor {
TranslationDescriptor {
- name: "Remapped Device MMIO",
- virtual_range: || {
- // The last 64 KiB slot in the first 512 MiB
- RangeInclusive::new(0x1FFF_0000, 0x1FFF_FFFF)
- },
- translation: Translation::Offset(memory_map::mmio::BASE + 0x20_0000),
- virtual_range: remapped_mmio_range_inclusive,
- physical_range_translation: Translation::Offset(memory_map::mmio::BASE + 0x20_0000),
- attribute_fields: AttributeFields {
- mem_attributes: MemAttributes::Device,
- acc_perms: AccessPermissions::ReadWrite,
- execute_never: true,
- },
- },
- RangeDescriptor {
- TranslationDescriptor {
name: "Device MMIO",
virtual_range: || {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
virtual_range: mmio_range_inclusive,
physical_range_translation: Translation::Identity,
@@ -64,11 +54,6 @@
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
}
-fn remapped_mmio_range_inclusive() -> RangeInclusive<usize> {
- // The last 64 KiB slot in the first 512 MiB
- RangeInclusive::new(0x1FFF_0000, 0x1FFF_FFFF)
-}
-
fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
}
diff -uNr 11_virtual_memory/src/bsp.rs 12_exceptions_part1_groundwork/src/bsp.rs
--- 11_virtual_memory/src/bsp.rs

@ -6,6 +6,20 @@
pub mod mmu;
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __ro_start: usize;
static __ro_end: usize;
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -43,3 +57,46 @@ pub(super) mod map {
pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
}
}
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read-Only (RO) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_start() -> usize {
unsafe { &__ro_start as *const _ as usize }
}
/// Size of the Read-Only (RO) range of the kernel binary.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_end() -> usize {
unsafe { &__ro_end as *const _ as usize }
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -21,45 +21,20 @@ const NUM_MEM_RANGES: usize = 2;
pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout::new(
memory_map::END_INCLUSIVE,
[
RangeDescriptor {
TranslationDescriptor {
name: "Kernel code and RO data",
virtual_range: || {
// Using the linker script, we ensure that the RO area is consecutive and 64 KiB
// aligned, and we export the boundaries via symbols:
//
// [__ro_start, __ro_end)
extern "C" {
// The inclusive start of the read-only area, aka the address of the first
// byte of the area.
static __ro_start: usize;
// The exclusive end of the read-only area, aka the address of the first
// byte _after_ the RO area.
static __ro_end: usize;
}
unsafe {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(
&__ro_start as *const _ as usize,
&__ro_end as *const _ as usize - 1,
)
}
},
translation: Translation::Identity,
virtual_range: ro_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
acc_perms: AccessPermissions::ReadOnly,
execute_never: false,
},
},
RangeDescriptor {
TranslationDescriptor {
name: "Device MMIO",
virtual_range: || {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
},
translation: Translation::Identity,
virtual_range: mmio_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::Device,
acc_perms: AccessPermissions::ReadWrite,
@ -69,6 +44,20 @@ pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout
],
);
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
fn ro_range_inclusive() -> RangeInclusive<usize> {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
}
fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

@ -12,7 +12,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -76,10 +76,10 @@ pub struct AttributeFields {
/// Architecture agnostic descriptor for a memory range.
#[allow(missing_docs)]
pub struct RangeDescriptor {
pub struct TranslationDescriptor {
pub name: &'static str,
pub virtual_range: fn() -> RangeInclusive<usize>,
pub translation: Translation,
pub physical_range_translation: Translation,
pub attribute_fields: AttributeFields,
}
@ -89,7 +89,7 @@ pub struct KernelVirtualLayout<const NUM_SPECIAL_RANGES: usize> {
max_virt_addr_inclusive: usize,
/// Array of descriptors for non-standard (normal cacheable DRAM) memory regions.
inner: [RangeDescriptor; NUM_SPECIAL_RANGES],
inner: [TranslationDescriptor; NUM_SPECIAL_RANGES],
}
//--------------------------------------------------------------------------------------------------
@ -106,8 +106,8 @@ impl Default for AttributeFields {
}
}
/// Human-readable output of a RangeDescriptor.
impl fmt::Display for RangeDescriptor {
/// Human-readable output of a TranslationDescriptor.
impl fmt::Display for TranslationDescriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Call the function to which self.range points, and dereference the result, which causes
// Rust to copy the value.
@ -155,14 +155,15 @@ impl fmt::Display for RangeDescriptor {
impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }> {
/// Create a new instance.
pub const fn new(max: usize, layout: [RangeDescriptor; NUM_SPECIAL_RANGES]) -> Self {
pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL_RANGES]) -> Self {
Self {
max_virt_addr_inclusive: max,
inner: layout,
}
}
/// For a virtual address, find and return the output address and corresponding attributes.
/// For a virtual address, find and return the physical output address and corresponding
/// attributes.
///
/// If the address is not found in `inner`, return an identity mapped default with normal
/// cacheable DRAM attributes.
@ -176,7 +177,7 @@ impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }
for i in self.inner.iter() {
if (i.virtual_range)().contains(&virt_addr) {
let output_addr = match i.translation {
let output_addr = match i.physical_range_translation {
Translation::Identity => virt_addr,
Translation::Offset(a) => a + (virt_addr - (i.virtual_range)().start()),
};

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

@ -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
@@ -82,3 +82,28 @@
@@ -71,3 +71,28 @@
pub fn virt_mem_layout() -> &'static KernelVirtualLayout<{ NUM_MEM_RANGES }> {
&LAYOUT
}
@ -1462,13 +1462,13 @@ diff -uNr 12_exceptions_part1_groundwork/src/memory/mmu.rs 13_integrated_testing
#[derive(Copy, Clone)]
pub enum Translation {
Identity,
@@ -196,4 +195,9 @@
@@ -197,4 +196,9 @@
info!("{}", i);
}
}
+
+ #[cfg(test)]
+ pub fn inner(&self) -> &[RangeDescriptor; NUM_SPECIAL_RANGES] {
+ pub fn inner(&self) -> &[TranslationDescriptor; NUM_SPECIAL_RANGES] {
+ &self.inner
+ }
}
@ -1551,7 +1551,7 @@ diff -uNr 12_exceptions_part1_groundwork/src/panic_wait.rs 13_integrated_testing
diff -uNr 12_exceptions_part1_groundwork/src/runtime_init.rs 13_integrated_testing/src/runtime_init.rs
--- 12_exceptions_part1_groundwork/src/runtime_init.rs
+++ 13_integrated_testing/src/runtime_init.rs
@@ -51,7 +51,33 @@
@@ -31,7 +31,33 @@
///
/// - Only a single core must be active and running this function.
pub unsafe fn runtime_init() -> ! {
@ -1577,8 +1577,8 @@ diff -uNr 12_exceptions_part1_groundwork/src/runtime_init.rs 13_integrated_testi
+ fn bss_section_is_sane() {
+ use core::mem;
+
+ let start = unsafe { bss_range().start } as *const _ as usize;
+ let end = unsafe { bss_range().end } as *const _ as usize;
+ let start = bsp::memory::bss_range().start as *const _ as usize;
+ let end = bsp::memory::bss_range().end as *const _ as usize;
- crate::kernel_init()
+ assert_eq!(start modulo mem::size_of::<usize>(), 0);

@ -6,6 +6,20 @@
pub mod mmu;
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __ro_start: usize;
static __ro_end: usize;
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -43,3 +57,46 @@ pub(super) mod map {
pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
}
}
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read-Only (RO) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_start() -> usize {
unsafe { &__ro_start as *const _ as usize }
}
/// Size of the Read-Only (RO) range of the kernel binary.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_end() -> usize {
unsafe { &__ro_end as *const _ as usize }
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -21,45 +21,20 @@ const NUM_MEM_RANGES: usize = 2;
pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout::new(
memory_map::END_INCLUSIVE,
[
RangeDescriptor {
TranslationDescriptor {
name: "Kernel code and RO data",
virtual_range: || {
// Using the linker script, we ensure that the RO area is consecutive and 64 KiB
// aligned, and we export the boundaries via symbols:
//
// [__ro_start, __ro_end)
extern "C" {
// The inclusive start of the read-only area, aka the address of the first
// byte of the area.
static __ro_start: usize;
// The exclusive end of the read-only area, aka the address of the first
// byte _after_ the RO area.
static __ro_end: usize;
}
unsafe {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(
&__ro_start as *const _ as usize,
&__ro_end as *const _ as usize - 1,
)
}
},
translation: Translation::Identity,
virtual_range: ro_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
acc_perms: AccessPermissions::ReadOnly,
execute_never: false,
},
},
RangeDescriptor {
TranslationDescriptor {
name: "Device MMIO",
virtual_range: || {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
},
translation: Translation::Identity,
virtual_range: mmio_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::Device,
acc_perms: AccessPermissions::ReadWrite,
@ -69,6 +44,20 @@ pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout
],
);
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
fn ro_range_inclusive() -> RangeInclusive<usize> {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
}
fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

@ -12,7 +12,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -75,10 +75,10 @@ pub struct AttributeFields {
/// Architecture agnostic descriptor for a memory range.
#[allow(missing_docs)]
pub struct RangeDescriptor {
pub struct TranslationDescriptor {
pub name: &'static str,
pub virtual_range: fn() -> RangeInclusive<usize>,
pub translation: Translation,
pub physical_range_translation: Translation,
pub attribute_fields: AttributeFields,
}
@ -88,7 +88,7 @@ pub struct KernelVirtualLayout<const NUM_SPECIAL_RANGES: usize> {
max_virt_addr_inclusive: usize,
/// Array of descriptors for non-standard (normal cacheable DRAM) memory regions.
inner: [RangeDescriptor; NUM_SPECIAL_RANGES],
inner: [TranslationDescriptor; NUM_SPECIAL_RANGES],
}
//--------------------------------------------------------------------------------------------------
@ -105,8 +105,8 @@ impl Default for AttributeFields {
}
}
/// Human-readable output of a RangeDescriptor.
impl fmt::Display for RangeDescriptor {
/// Human-readable output of a TranslationDescriptor.
impl fmt::Display for TranslationDescriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Call the function to which self.range points, and dereference the result, which causes
// Rust to copy the value.
@ -154,14 +154,15 @@ impl fmt::Display for RangeDescriptor {
impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }> {
/// Create a new instance.
pub const fn new(max: usize, layout: [RangeDescriptor; NUM_SPECIAL_RANGES]) -> Self {
pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL_RANGES]) -> Self {
Self {
max_virt_addr_inclusive: max,
inner: layout,
}
}
/// For a virtual address, find and return the output address and corresponding attributes.
/// For a virtual address, find and return the physical output address and corresponding
/// attributes.
///
/// If the address is not found in `inner`, return an identity mapped default with normal
/// cacheable DRAM attributes.
@ -175,7 +176,7 @@ impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }
for i in self.inner.iter() {
if (i.virtual_range)().contains(&virt_addr) {
let output_addr = match i.translation {
let output_addr = match i.physical_range_translation {
Translation::Identity => virt_addr,
Translation::Offset(a) => a + (virt_addr - (i.virtual_range)().start()),
};
@ -197,7 +198,7 @@ impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }
}
#[cfg(test)]
pub fn inner(&self) -> &[RangeDescriptor; NUM_SPECIAL_RANGES] {
pub fn inner(&self) -> &[TranslationDescriptor; NUM_SPECIAL_RANGES] {
&self.inner
}
}

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------
@ -73,8 +53,8 @@ mod tests {
fn bss_section_is_sane() {
use core::mem;
let start = unsafe { bss_range().start } as *const _ as usize;
let end = unsafe { bss_range().end } as *const _ as usize;
let start = bsp::memory::bss_range().start as *const _ as usize;
let end = bsp::memory::bss_range().end as *const _ as usize;
assert_eq!(start % mem::size_of::<usize>(), 0);
assert_eq!(end % mem::size_of::<usize>(), 0);

@ -2145,7 +2145,7 @@ diff -uNr 13_integrated_testing/src/bsp/raspberrypi/exception.rs 14_exceptions_p
diff -uNr 13_integrated_testing/src/bsp/raspberrypi/memory.rs 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs
--- 13_integrated_testing/src/bsp/raspberrypi/memory.rs
+++ 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs
@@ -16,20 +16,22 @@
@@ -30,20 +30,22 @@
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
@ -2175,7 +2175,7 @@ diff -uNr 13_integrated_testing/src/bsp/raspberrypi/memory.rs 14_exceptions_part
}
/// Physical devices.
@@ -37,9 +39,11 @@
@@ -51,10 +53,12 @@
pub mod mmio {
use super::*;
@ -2192,6 +2192,7 @@ diff -uNr 13_integrated_testing/src/bsp/raspberrypi/memory.rs 14_exceptions_part
}
}
diff -uNr 13_integrated_testing/src/bsp/raspberrypi.rs 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs
--- 13_integrated_testing/src/bsp/raspberrypi.rs
+++ 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs

@ -6,6 +6,20 @@
pub mod mmu;
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __ro_start: usize;
static __ro_end: usize;
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -47,3 +61,46 @@ pub(super) mod map {
pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
}
}
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read-Only (RO) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_start() -> usize {
unsafe { &__ro_start as *const _ as usize }
}
/// Size of the Read-Only (RO) range of the kernel binary.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_end() -> usize {
unsafe { &__ro_end as *const _ as usize }
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -21,45 +21,20 @@ const NUM_MEM_RANGES: usize = 2;
pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout::new(
memory_map::END_INCLUSIVE,
[
RangeDescriptor {
TranslationDescriptor {
name: "Kernel code and RO data",
virtual_range: || {
// Using the linker script, we ensure that the RO area is consecutive and 64 KiB
// aligned, and we export the boundaries via symbols:
//
// [__ro_start, __ro_end)
extern "C" {
// The inclusive start of the read-only area, aka the address of the first
// byte of the area.
static __ro_start: usize;
// The exclusive end of the read-only area, aka the address of the first
// byte _after_ the RO area.
static __ro_end: usize;
}
unsafe {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(
&__ro_start as *const _ as usize,
&__ro_end as *const _ as usize - 1,
)
}
},
translation: Translation::Identity,
virtual_range: ro_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
acc_perms: AccessPermissions::ReadOnly,
execute_never: false,
},
},
RangeDescriptor {
TranslationDescriptor {
name: "Device MMIO",
virtual_range: || {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
},
translation: Translation::Identity,
virtual_range: mmio_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::Device,
acc_perms: AccessPermissions::ReadWrite,
@ -69,6 +44,20 @@ pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout
],
);
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
fn ro_range_inclusive() -> RangeInclusive<usize> {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
}
fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

@ -12,7 +12,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -75,10 +75,10 @@ pub struct AttributeFields {
/// Architecture agnostic descriptor for a memory range.
#[allow(missing_docs)]
pub struct RangeDescriptor {
pub struct TranslationDescriptor {
pub name: &'static str,
pub virtual_range: fn() -> RangeInclusive<usize>,
pub translation: Translation,
pub physical_range_translation: Translation,
pub attribute_fields: AttributeFields,
}
@ -88,7 +88,7 @@ pub struct KernelVirtualLayout<const NUM_SPECIAL_RANGES: usize> {
max_virt_addr_inclusive: usize,
/// Array of descriptors for non-standard (normal cacheable DRAM) memory regions.
inner: [RangeDescriptor; NUM_SPECIAL_RANGES],
inner: [TranslationDescriptor; NUM_SPECIAL_RANGES],
}
//--------------------------------------------------------------------------------------------------
@ -105,8 +105,8 @@ impl Default for AttributeFields {
}
}
/// Human-readable output of a RangeDescriptor.
impl fmt::Display for RangeDescriptor {
/// Human-readable output of a TranslationDescriptor.
impl fmt::Display for TranslationDescriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Call the function to which self.range points, and dereference the result, which causes
// Rust to copy the value.
@ -154,14 +154,15 @@ impl fmt::Display for RangeDescriptor {
impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }> {
/// Create a new instance.
pub const fn new(max: usize, layout: [RangeDescriptor; NUM_SPECIAL_RANGES]) -> Self {
pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL_RANGES]) -> Self {
Self {
max_virt_addr_inclusive: max,
inner: layout,
}
}
/// For a virtual address, find and return the output address and corresponding attributes.
/// For a virtual address, find and return the physical output address and corresponding
/// attributes.
///
/// If the address is not found in `inner`, return an identity mapped default with normal
/// cacheable DRAM attributes.
@ -175,7 +176,7 @@ impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }
for i in self.inner.iter() {
if (i.virtual_range)().contains(&virt_addr) {
let output_addr = match i.translation {
let output_addr = match i.physical_range_translation {
Translation::Identity => virt_addr,
Translation::Offset(a) => a + (virt_addr - (i.virtual_range)().start()),
};
@ -197,7 +198,7 @@ impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }
}
#[cfg(test)]
pub fn inner(&self) -> &[RangeDescriptor; NUM_SPECIAL_RANGES] {
pub fn inner(&self) -> &[TranslationDescriptor; NUM_SPECIAL_RANGES] {
&self.inner
}
}

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------
@ -73,8 +53,8 @@ mod tests {
fn bss_section_is_sane() {
use core::mem;
let start = unsafe { bss_range().start } as *const _ as usize;
let end = unsafe { bss_range().end } as *const _ as usize;
let start = bsp::memory::bss_range().start as *const _ as usize;
let end = bsp::memory::bss_range().end as *const _ as usize;
assert_eq!(start % mem::size_of::<usize>(), 0);
assert_eq!(end % mem::size_of::<usize>(), 0);

Binary file not shown.

Binary file not shown.

@ -4,6 +4,18 @@
//! BSP Memory Management.
use core::ops::Range;
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
// Symbols from the linker script.
extern "C" {
static __bss_start: usize;
static __bss_end: usize;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
@ -37,3 +49,22 @@ pub(super) mod map {
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - Values are provided by the linker script and must be trusted as-is.
/// - The linker-provided addresses must be u64 aligned.
pub fn bss_range() -> Range<*mut u64> {
unsafe {
Range {
start: &__bss_start as *const _ as *mut u64,
end: &__bss_end as *const _ as *mut u64,
}
}
}

@ -10,7 +10,7 @@ use core::ops::Range;
// Public Code
//--------------------------------------------------------------------------------------------------
/// Zero out a memory region.
/// Zero out a memory range.
///
/// # Safety
///

@ -4,32 +4,12 @@
//! Rust runtime initialization code.
use crate::memory;
use core::ops::Range;
use crate::{bsp, memory};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Return the range spanning the .bss section.
///
/// # Safety
///
/// - The symbol-provided addresses must be valid.
/// - The symbol-provided addresses must be usize aligned.
unsafe fn bss_range() -> Range<*mut usize> {
extern "C" {
// Boundaries of the .bss section, provided by linker script symbols.
static mut __bss_start: usize;
static mut __bss_end: usize;
}
Range {
start: &mut __bss_start,
end: &mut __bss_end,
}
}
/// Zero out the .bss section.
///
/// # Safety
@ -37,7 +17,7 @@ unsafe fn bss_range() -> Range<*mut usize> {
/// - Must only be called pre `kernel_init()`.
#[inline(always)]
unsafe fn zero_bss() {
memory::zero_volatile(bss_range());
memory::zero_volatile(bsp::memory::bss_range());
}
//--------------------------------------------------------------------------------------------------

Loading…
Cancel
Save