@ -2,7 +2,7 @@
## tl;dr
我们拓展了`cpu .S`, 在第一次启动的时候调用Rust代码。在Rust的代码中先清零了[bss] section, 然后通过调用`panic()`挂起CPU。再次运行`make qemu`看看新增加的代码是怎么运行的。
我们拓展了`boot .S`, 在第一次启动的时候调用Rust代码。在Rust的代码中先清零了[bss] section, 然后通过调用`panic()`挂起CPU。再次运行`make qemu`看看新增加的代码是怎么运行的。
## 值得注意的变化
@ -21,9 +21,23 @@
## 相比之前的变化( diff)
```diff
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu.S 02_runtime_init/src/_arch/aarch64/cpu.S
--- 01_wait_forever/src/_arch/aarch64/cpu.S
+++ 02_runtime_init/src/_arch/aarch64/cpu.S
diff -uNr 01_wait_forever/Cargo.toml 02_runtime_init/Cargo.toml
--- 01_wait_forever/Cargo.toml
+++ 02_runtime_init/Cargo.toml
@@ -4,6 +4,9 @@
authors = ["Andre Richter < andre.o.richter @ gmail . com > "]
edition = "2018"
+[profile.release]
+lto = true
+
# The features section is used to select the target board.
[features]
default = []
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.S 02_runtime_init/src/_arch/aarch64/cpu/boot.S
--- 01_wait_forever/src/_arch/aarch64/cpu/boot.S
+++ 02_runtime_init/src/_arch/aarch64/cpu/boot.S
@@ -7,5 +7,15 @@
.global _start
@ -43,10 +57,45 @@ diff -uNr 01_wait_forever/src/_arch/aarch64/cpu.S 02_runtime_init/src/_arch/aarc
+ b 1b // We should never reach here. But just in case,
+ // park this core aswell
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu.rs 02_runtime_init/src/_arch/aarch64/cpu.rs
--- 01_wait_forever/src/_arch/aarch64/cpu.rs
+++ 02_runtime_init/src/_arch/aarch64/cpu.rs
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2021 Andre Richter < andre.o.richter @ gmail . com >
+
+//! Architectural processor code.
+//!
+//! # Orientation
+//!
+//! Since arch modules are imported into generic modules using the path attribute, the path of this
+//! file is:
+//!
+//! crate::cpu::arch_cpu
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Pause execution on the core.
+#[inline(always)]
+pub fn wait_forever() -> ! {
+ unsafe {
+ loop {
+ #[rustfmt::skip]
+ asm!(
+ "wfe",
+ options(nomem, nostack, preserves_flags)
+ );
+ }
+ }
+}
diff -uNr 01_wait_forever/src/bsp/raspberrypi/link.ld 02_runtime_init/src/bsp/raspberrypi/link.ld
--- 01_wait_forever/src/bsp/raspberrypi/link.ld
+++ 02_runtime_init/src/bsp/raspberrypi/link.ld
@@ -13,5 +13,24 @@
@@ -13,5 +13,27 @@
*(.text._start) * (.text*)
}
@ -66,22 +115,97 @@ diff -uNr 01_wait_forever/src/bsp/raspberrypi/link.ld 02_runtime_init/src/bsp/ra
+ __bss_start = .;
+ *(.bss* );
+ . = ALIGN(8);
+ __bss_end = .;
+
+ /* Fill for the bss == 0 case, so that __bss_start < = __bss_end_inclusive holds */
+ . += 8;
+ __bss_end_inclusive = . - 8;
+ }
+
/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,37 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2021 Andre Richter < andre.o.richter @ gmail . com >
+
+//! BSP Memory Management.
+
+use core::{cell::UnsafeCell, ops::RangeInclusive};
+
+//--------------------------------------------------------------------------------------------------
+// Private Definitions
+//--------------------------------------------------------------------------------------------------
+
+// Symbols from the linker script.
+extern "Rust" {
+ static __bss_start: UnsafeCell< u64 > ;
+ static __bss_end_inclusive: UnsafeCell< u64 > ;
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Return the inclusive 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_inclusive() -> RangeInclusive< *mut u64> {
+ let range;
+ unsafe {
+ range = RangeInclusive::new(__bss_start.get(), __bss_end_inclusive.get());
+ }
+ assert!(!range.is_empty());
+
+ range
+}
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/cpu.rs 02_runtime_init/src/cpu.rs
--- 01_wait_forever/src/cpu.rs
+++ 02_runtime_init/src/cpu.rs
@@ -4,4 +4,13 @@
//! Processor code.
+#[cfg(target_arch = "aarch64")]
+#[path = "_arch/aarch64/cpu.rs"]
+mod arch_cpu;
+
mod boot;
+
+//--------------------------------------------------------------------------------------------------
+// Architectural Public Reexports
+//--------------------------------------------------------------------------------------------------
+pub use arch_cpu::wait_forever;
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
@@ -97,10 +97,20 @@
#![no_main]
#![no_std]
@@ -102,6 +102,7 @@
//!
//! 1. The kernel's entry point is the function [`cpu::boot::arch_boot::_start()`].
//! - It is implemented in `src/_arch/__arch_name__/cpu/boot.rs` .
+//! 2. Once finished with architectural setup, the arch code calls [`runtime_init::runtime_init()`].
//!
//! [`cpu::boot::arch_boot::_start()`]: cpu/boot/arch_boot/fn._start.html
-// `mod cpu` provides the `_start()` function, the first function to run.
+// `mod cpu` provides the `_start()` function, the first function to run. `_start()` then calls
+// `runtime_init()` , which jumps to `kernel_init()` .
@@ -112,6 +113,15 @@
mod bsp;
mod cpu;
@ -102,73 +226,70 @@ diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs
diff -uNr 01_wait_forever/src/memory.rs 02_runtime_init/src/memory.rs
--- 01_wait_forever/src/memory.rs
+++ 02_runtime_init/src/memory.rs
@@ -0,0 +1,29 @@
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2021 Andre Richter < andre.o.richter @ gmail . com >
+
+//! Memory Management.
+
+use core::ops::Range;
+use core::ops::RangeInclusive ;
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Zero out a memory region .
+/// Zero out an inclusive memory range .
+///
+/// # Safety
+///
+/// - `range.start` and `range.end` must be valid.
+/// - `range.start` and `range.end` must be `T` aligned.
+pub unsafe fn zero_volatile< T > (range: Range< *mut T>)
+pub unsafe fn zero_volatile< T > (range: RangeInclusive < *mut T>)
+where
+ T: From< u8 > ,
+{
+ let mut ptr = range.start;
+ let mut ptr = *range.start();
+ let end_inclusive = *range.end();
+
+ while ptr < range.end {
+ while ptr < = end_inclusive {
+ core::ptr::write_volatile(ptr, T::from(0));
+ ptr = ptr.offset(1);
+ }
+}
diff -uNr 01_wait_forever/src/panic_wait.rs 02_runtime_init/src/panic_wait.rs
--- 01_wait_forever/src/panic_wait.rs
+++ 02_runtime_init/src/panic_wait.rs
@@ -4,9 +4,10 @@
//! A panic handler that infinitely waits.
+use crate::cpu;
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: & PanicInfo) -> ! {
- unimplemented!()
+ cpu::wait_forever()
}
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,3 8 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2021 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
@ -176,7 +297,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::bs s_range_inclusiv e());
+}
+
+//--------------------------------------------------------------------------------------------------
@ -190,7 +311,7 @@ diff -uNr 01_wait_forever/src/runtime_init.rs 02_runtime_init/src/runtime_init.r
+///
+/// - Only a single core must be active and running this function.
+#[no_mangle]
+pub unsafe extern "C" fn runtime_init() -> ! {
+pub unsafe fn runtime_init() -> ! {
+ zero_bss();
+
+ crate::kernel_init()