Skip to content

Commit 7f66600

Browse files
committed
Init DRAM in assembly instead of Rust
See rust-embedded/cortex-m-rt#300
1 parent 39a066c commit 7f66600

File tree

136 files changed

+872
-2585
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

136 files changed

+872
-2585
lines changed

02_runtime_init/README.md

+42-158
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
## tl;dr
44

5-
- We extend `boot.s` to call into Rust code for the first time. There, we zero the [bss] section
6-
before execution is halted with a call to `panic()`.
5+
- We extend `boot.s` to call into Rust code for the first time. Before the jump
6+
to Rust happens, a bit of runtime init work is done.
7+
- The Rust code being called just halts execution with a call to `panic!()`.
78
- Check out `make qemu` again to see the additional code run.
89

910
## Notable additions
@@ -12,11 +13,11 @@
1213
- New sections: `.rodata`, `.got`, `.data`, `.bss`.
1314
- A dedicated place for linking boot-time arguments that need to be read by `_start()`.
1415
- `_start()` in `_arch/__arch_name__/cpu/boot.s`:
15-
1. Halt core if core != core0.
16-
1. Set up the `stack pointer`.
17-
1. Jump to the `_start_rust()` function, defined in `arch/__arch_name__/cpu/boot.rs`.
18-
- `runtime_init()` in `runtime_init.rs`:
19-
- Zeros the `.bss` section.
16+
1. Halts core if core != core0.
17+
1. Initializes the `DRAM` by zeroing the [bss] section.
18+
1. Sets up the `stack pointer`.
19+
1. Jumps to the `_start_rust()` function, defined in `arch/__arch_name__/cpu/boot.rs`.
20+
- `_start_rust()`:
2021
- Calls `kernel_init()`, which calls `panic!()`, which eventually halts core0 as well.
2122
- The library now uses the [cortex-a] crate, which provides zero-overhead abstractions and wraps
2223
`unsafe` parts when dealing with the CPU's resources.
@@ -64,12 +65,8 @@ diff -uNr 01_wait_forever/Makefile 02_runtime_init/Makefile
6465
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.rs 02_runtime_init/src/_arch/aarch64/cpu/boot.rs
6566
--- 01_wait_forever/src/_arch/aarch64/cpu/boot.rs
6667
+++ 02_runtime_init/src/_arch/aarch64/cpu/boot.rs
67-
@@ -11,5 +11,23 @@
68-
//!
69-
//! crate::cpu::boot::arch_boot
68+
@@ -13,3 +13,15 @@
7069

71-
+use crate::runtime_init;
72-
+
7370
// Assembly counterpart to this file.
7471
global_asm!(include_str!("boot.s"));
7572
+
@@ -80,13 +77,9 @@ diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.rs 02_runtime_init/src/_arc
8077
+/// The Rust entry of the `kernel` binary.
8178
+///
8279
+/// The function is called from the assembly `_start` function.
83-
+///
84-
+/// # Safety
85-
+///
86-
+/// - The `bss` section is not initialized yet. The code must not use or reference it in any way.
8780
+#[no_mangle]
8881
+pub unsafe fn _start_rust() -> ! {
89-
+ runtime_init::runtime_init()
82+
+ crate::kernel_init()
9083
+}
9184

9285
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.s 02_runtime_init/src/_arch/aarch64/cpu/boot.s
@@ -117,7 +110,7 @@ diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.s 02_runtime_init/src/_arch
117110
// Public Code
118111
//--------------------------------------------------------------------------------------------------
119112
.section .text._start
120-
@@ -11,6 +29,22 @@
113+
@@ -11,9 +29,38 @@
121114
// fn _start()
122115
//------------------------------------------------------------------------------
123116
_start:
@@ -126,10 +119,22 @@ diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.s 02_runtime_init/src/_arch
126119
+ and x1, x1, _core_id_mask
127120
+ ldr x2, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs
128121
+ cmp x1, x2
129-
+ b.ne 1f
122+
+ b.ne parking_loop
123+
+
124+
+ // If execution reaches here, it is the boot core.
125+
+
126+
+ // Initialize DRAM.
127+
+ ADR_REL x0, __bss_start
128+
+ ADR_REL x1, __bss_end_exclusive
130129
+
131-
+ // If execution reaches here, it is the boot core. Now, prepare the jump to Rust code.
130+
+bss_init_loop:
131+
+ cmp x0, x1
132+
+ b.eq prepare_rust
133+
+ stp xzr, xzr, [x0], #16
134+
+ b bss_init_loop
132135
+
136+
+ // Prepare the jump to Rust code.
137+
+prepare_rust:
133138
+ // Set the stack pointer.
134139
+ ADR_REL x0, __boot_core_stack_end_exclusive
135140
+ mov sp, x0
@@ -138,8 +143,14 @@ diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.s 02_runtime_init/src/_arch
138143
+ b _start_rust
139144
+
140145
// Infinitely wait for events (aka "park the core").
141-
1: wfe
142-
b 1b
146+
-1: wfe
147+
- b 1b
148+
+parking_loop:
149+
+ wfe
150+
+ b parking_loop
151+
152+
.size _start, . - _start
153+
.type _start, function
143154

144155
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu.rs 02_runtime_init/src/_arch/aarch64/cpu.rs
145156
--- 01_wait_forever/src/_arch/aarch64/cpu.rs
@@ -194,7 +205,7 @@ diff -uNr 01_wait_forever/src/bsp/raspberrypi/cpu.rs 02_runtime_init/src/bsp/ras
194205
diff -uNr 01_wait_forever/src/bsp/raspberrypi/link.ld 02_runtime_init/src/bsp/raspberrypi/link.ld
195206
--- 01_wait_forever/src/bsp/raspberrypi/link.ld
196207
+++ 02_runtime_init/src/bsp/raspberrypi/link.ld
197-
@@ -11,17 +11,45 @@
208+
@@ -11,17 +11,43 @@
198209
PHDRS
199210
{
200211
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
@@ -230,70 +241,25 @@ diff -uNr 01_wait_forever/src/bsp/raspberrypi/link.ld 02_runtime_init/src/bsp/ra
230241
+ ***********************************************************************************************/
231242
+ .data : { *(.data*) } :segment_rw
232243
+
233-
+ /* Section is zeroed in u64 chunks, align start and end to 8 bytes */
234-
+ .bss : ALIGN(8)
244+
+ /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
245+
+ .bss : ALIGN(16)
235246
+ {
236247
+ __bss_start = .;
237248
+ *(.bss*);
238-
+ . = ALIGN(8);
239-
+
240-
+ . += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
241-
+ __bss_end_inclusive = . - 8;
249+
+ . = ALIGN(16);
250+
+ __bss_end_exclusive = .;
242251
+ } :NONE
243252
}
244253

245-
diff -uNr 01_wait_forever/src/bsp/raspberrypi/memory.rs 02_runtime_init/src/bsp/raspberrypi/memory.rs
246-
--- 01_wait_forever/src/bsp/raspberrypi/memory.rs
247-
+++ 02_runtime_init/src/bsp/raspberrypi/memory.rs
248-
@@ -0,0 +1,37 @@
249-
+// SPDX-License-Identifier: MIT OR Apache-2.0
250-
+//
251-
+// Copyright (c) 2018-2021 Andre Richter <[email protected]>
252-
+
253-
+//! BSP Memory Management.
254-
+
255-
+use core::{cell::UnsafeCell, ops::RangeInclusive};
256-
+
257-
+//--------------------------------------------------------------------------------------------------
258-
+// Private Definitions
259-
+//--------------------------------------------------------------------------------------------------
260-
+
261-
+// Symbols from the linker script.
262-
+extern "Rust" {
263-
+ static __bss_start: UnsafeCell<u64>;
264-
+ static __bss_end_inclusive: UnsafeCell<u64>;
265-
+}
266-
+
267-
+//--------------------------------------------------------------------------------------------------
268-
+// Public Code
269-
+//--------------------------------------------------------------------------------------------------
270-
+
271-
+/// Return the inclusive range spanning the .bss section.
272-
+///
273-
+/// # Safety
274-
+///
275-
+/// - Values are provided by the linker script and must be trusted as-is.
276-
+/// - The linker-provided addresses must be u64 aligned.
277-
+pub fn bss_range_inclusive() -> RangeInclusive<*mut u64> {
278-
+ let range;
279-
+ unsafe {
280-
+ range = RangeInclusive::new(__bss_start.get(), __bss_end_inclusive.get());
281-
+ }
282-
+ assert!(!range.is_empty());
283-
+
284-
+ range
285-
+}
286-
287254
diff -uNr 01_wait_forever/src/bsp/raspberrypi.rs 02_runtime_init/src/bsp/raspberrypi.rs
288255
--- 01_wait_forever/src/bsp/raspberrypi.rs
289256
+++ 02_runtime_init/src/bsp/raspberrypi.rs
290-
@@ -4,4 +4,5 @@
257+
@@ -4,4 +4,4 @@
291258

292259
//! Top-level BSP file for the Raspberry Pi 3 and 4.
293260

294261
-// Coming soon.
295262
+pub mod cpu;
296-
+pub mod memory;
297263

298264
diff -uNr 01_wait_forever/src/cpu.rs 02_runtime_init/src/cpu.rs
299265
--- 01_wait_forever/src/cpu.rs
@@ -316,24 +282,19 @@ diff -uNr 01_wait_forever/src/cpu.rs 02_runtime_init/src/cpu.rs
316282
diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs
317283
--- 01_wait_forever/src/main.rs
318284
+++ 02_runtime_init/src/main.rs
319-
@@ -102,14 +102,25 @@
285+
@@ -102,8 +102,8 @@
320286
//!
321287
//! 1. The kernel's entry point is the function `cpu::boot::arch_boot::_start()`.
322288
//! - It is implemented in `src/_arch/__arch_name__/cpu/boot.s`.
323-
+//! 2. Once finished with architectural setup, the arch code calls [`runtime_init::runtime_init()`].
324-
+//!
325-
+//! [`runtime_init::runtime_init()`]: runtime_init/fn.runtime_init.html
289+
+//! 2. Once finished with architectural setup, the arch code calls `kernel_init()`.
326290

327291
-#![feature(asm)]
328292
#![feature(global_asm)]
329293
#![no_main]
330294
#![no_std]
331-
332-
mod bsp;
295+
@@ -112,4 +112,11 @@
333296
mod cpu;
334-
+mod memory;
335297
mod panic_wait;
336-
+mod runtime_init;
337298

338299
-// Kernel code coming next tutorial.
339300
+/// Early init code.
@@ -345,41 +306,6 @@ diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs
345306
+ panic!()
346307
+}
347308

348-
diff -uNr 01_wait_forever/src/memory.rs 02_runtime_init/src/memory.rs
349-
--- 01_wait_forever/src/memory.rs
350-
+++ 02_runtime_init/src/memory.rs
351-
@@ -0,0 +1,30 @@
352-
+// SPDX-License-Identifier: MIT OR Apache-2.0
353-
+//
354-
+// Copyright (c) 2018-2021 Andre Richter <[email protected]>
355-
+
356-
+//! Memory Management.
357-
+
358-
+use core::ops::RangeInclusive;
359-
+
360-
+//--------------------------------------------------------------------------------------------------
361-
+// Public Code
362-
+//--------------------------------------------------------------------------------------------------
363-
+
364-
+/// Zero out an inclusive memory range.
365-
+///
366-
+/// # Safety
367-
+///
368-
+/// - `range.start` and `range.end` must be valid.
369-
+/// - `range.start` and `range.end` must be `T` aligned.
370-
+pub unsafe fn zero_volatile<T>(range: RangeInclusive<*mut T>)
371-
+where
372-
+ T: From<u8>,
373-
+{
374-
+ let mut ptr = *range.start();
375-
+ let end_inclusive = *range.end();
376-
+
377-
+ while ptr <= end_inclusive {
378-
+ core::ptr::write_volatile(ptr, T::from(0));
379-
+ ptr = ptr.offset(1);
380-
+ }
381-
+}
382-
383309
diff -uNr 01_wait_forever/src/panic_wait.rs 02_runtime_init/src/panic_wait.rs
384310
--- 01_wait_forever/src/panic_wait.rs
385311
+++ 02_runtime_init/src/panic_wait.rs
@@ -396,46 +322,4 @@ diff -uNr 01_wait_forever/src/panic_wait.rs 02_runtime_init/src/panic_wait.rs
396322
+ cpu::wait_forever()
397323
}
398324

399-
diff -uNr 01_wait_forever/src/runtime_init.rs 02_runtime_init/src/runtime_init.rs
400-
--- 01_wait_forever/src/runtime_init.rs
401-
+++ 02_runtime_init/src/runtime_init.rs
402-
@@ -0,0 +1,37 @@
403-
+// SPDX-License-Identifier: MIT OR Apache-2.0
404-
+//
405-
+// Copyright (c) 2018-2021 Andre Richter <[email protected]>
406-
+
407-
+//! Rust runtime initialization code.
408-
+
409-
+use crate::{bsp, memory};
410-
+
411-
+//--------------------------------------------------------------------------------------------------
412-
+// Private Code
413-
+//--------------------------------------------------------------------------------------------------
414-
+
415-
+/// Zero out the .bss section.
416-
+///
417-
+/// # Safety
418-
+///
419-
+/// - Must only be called pre `kernel_init()`.
420-
+#[inline(always)]
421-
+unsafe fn zero_bss() {
422-
+ memory::zero_volatile(bsp::memory::bss_range_inclusive());
423-
+}
424-
+
425-
+//--------------------------------------------------------------------------------------------------
426-
+// Public Code
427-
+//--------------------------------------------------------------------------------------------------
428-
+
429-
+/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then jumps to kernel
430-
+/// init code.
431-
+///
432-
+/// # Safety
433-
+///
434-
+/// - Only a single core must be active and running this function.
435-
+pub unsafe fn runtime_init() -> ! {
436-
+ zero_bss();
437-
+
438-
+ crate::kernel_init()
439-
+}
440-
441325
```

02_runtime_init/src/_arch/aarch64/cpu/boot.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
//!
1212
//! crate::cpu::boot::arch_boot
1313
14-
use crate::runtime_init;
15-
1614
// Assembly counterpart to this file.
1715
global_asm!(include_str!("boot.s"));
1816

@@ -23,11 +21,7 @@ global_asm!(include_str!("boot.s"));
2321
/// The Rust entry of the `kernel` binary.
2422
///
2523
/// The function is called from the assembly `_start` function.
26-
///
27-
/// # Safety
28-
///
29-
/// - The `bss` section is not initialized yet. The code must not use or reference it in any way.
3024
#[no_mangle]
3125
pub unsafe fn _start_rust() -> ! {
32-
runtime_init::runtime_init()
26+
crate::kernel_init()
3327
}

02_runtime_init/src/_arch/aarch64/cpu/boot.s

+17-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,22 @@ _start:
3434
and x1, x1, _core_id_mask
3535
ldr x2, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs
3636
cmp x1, x2
37-
b.ne 1f
37+
b.ne parking_loop
3838

39-
// If execution reaches here, it is the boot core. Now, prepare the jump to Rust code.
39+
// If execution reaches here, it is the boot core.
4040

41+
// Initialize DRAM.
42+
ADR_REL x0, __bss_start
43+
ADR_REL x1, __bss_end_exclusive
44+
45+
bss_init_loop:
46+
cmp x0, x1
47+
b.eq prepare_rust
48+
stp xzr, xzr, [x0], #16
49+
b bss_init_loop
50+
51+
// Prepare the jump to Rust code.
52+
prepare_rust:
4153
// Set the stack pointer.
4254
ADR_REL x0, __boot_core_stack_end_exclusive
4355
mov sp, x0
@@ -46,8 +58,9 @@ _start:
4658
b _start_rust
4759

4860
// Infinitely wait for events (aka "park the core").
49-
1: wfe
50-
b 1b
61+
parking_loop:
62+
wfe
63+
b parking_loop
5164

5265
.size _start, . - _start
5366
.type _start, function

02_runtime_init/src/bsp/raspberrypi.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@
55
//! Top-level BSP file for the Raspberry Pi 3 and 4.
66
77
pub mod cpu;
8-
pub mod memory;

02_runtime_init/src/bsp/raspberrypi/link.ld

+4-6
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,12 @@ SECTIONS
4242
***********************************************************************************************/
4343
.data : { *(.data*) } :segment_rw
4444

45-
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
46-
.bss : ALIGN(8)
45+
/* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
46+
.bss : ALIGN(16)
4747
{
4848
__bss_start = .;
4949
*(.bss*);
50-
. = ALIGN(8);
51-
52-
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
53-
__bss_end_inclusive = . - 8;
50+
. = ALIGN(16);
51+
__bss_end_exclusive = .;
5452
} :NONE
5553
}

0 commit comments

Comments
 (0)