2
2
3
3
## tl;dr
4
4
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!() ` .
7
8
- Check out ` make qemu ` again to see the additional code run.
8
9
9
10
## Notable additions
12
13
- New sections: ` .rodata ` , ` .got ` , ` .data ` , ` .bss ` .
13
14
- A dedicated place for linking boot-time arguments that need to be read by ` _start() ` .
14
15
- ` _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() ` :
20
21
- Calls ` kernel_init() ` , which calls ` panic!() ` , which eventually halts core0 as well.
21
22
- The library now uses the [ cortex-a] crate, which provides zero-overhead abstractions and wraps
22
23
` unsafe ` parts when dealing with the CPU's resources.
@@ -64,12 +65,8 @@ diff -uNr 01_wait_forever/Makefile 02_runtime_init/Makefile
64
65
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.rs 02_runtime_init/src/_arch/aarch64/cpu/boot.rs
65
66
--- 01_wait_forever/src/_arch/aarch64/cpu/boot.rs
66
67
+++ 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 @@
70
69
71
- + use crate::runtime_init;
72
- +
73
70
// Assembly counterpart to this file.
74
71
global_asm!(include_str!("boot.s"));
75
72
+
@@ -80,13 +77,9 @@ diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.rs 02_runtime_init/src/_arc
80
77
+ /// The Rust entry of the `kernel` binary.
81
78
+ ///
82
79
+ /// 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.
87
80
+ #[no_mangle]
88
81
+ pub unsafe fn _start_rust() -> ! {
89
- + runtime_init::runtime_init ()
82
+ + crate::kernel_init ()
90
83
+ }
91
84
92
85
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
117
110
// Public Code
118
111
//--------------------------------------------------------------------------------------------------
119
112
.section .text._start
120
- @@ -11,6 +29,22 @@
113
+ @@ -11,9 +29,38 @@
121
114
// fn _start()
122
115
//------------------------------------------------------------------------------
123
116
_start:
@@ -126,10 +119,22 @@ diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.s 02_runtime_init/src/_arch
126
119
+ and x1, x1, _core_id_mask
127
120
+ ldr x2, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs
128
121
+ 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
130
129
+
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
132
135
+
136
+ + // Prepare the jump to Rust code.
137
+ + prepare_rust:
133
138
+ // Set the stack pointer.
134
139
+ ADR_REL x0, __boot_core_stack_end_exclusive
135
140
+ mov sp, x0
@@ -138,8 +143,14 @@ diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.s 02_runtime_init/src/_arch
138
143
+ b _start_rust
139
144
+
140
145
// 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
143
154
144
155
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu.rs 02_runtime_init/src/_arch/aarch64/cpu.rs
145
156
--- 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
194
205
diff -uNr 01_wait_forever/src/bsp/raspberrypi/link.ld 02_runtime_init/src/bsp/raspberrypi/link.ld
195
206
--- 01_wait_forever/src/bsp/raspberrypi/link.ld
196
207
+++ 02_runtime_init/src/bsp/raspberrypi/link.ld
197
- @@ -11,17 +11,45 @@
208
+ @@ -11,17 +11,43 @@
198
209
PHDRS
199
210
{
200
211
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
230
241
+ ***********************************************************************************************/
231
242
+ .data : { *(.data*) } :segment_rw
232
243
+
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 )
235
246
+ {
236
247
+ __bss_start = .;
237
248
+ *(.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 = .;
242
251
+ } :NONE
243
252
}
244
253
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
-
287
254
diff -uNr 01_wait_forever/src/bsp/raspberrypi.rs 02_runtime_init/src/bsp/raspberrypi.rs
288
255
--- 01_wait_forever/src/bsp/raspberrypi.rs
289
256
+++ 02_runtime_init/src/bsp/raspberrypi.rs
290
- @@ -4,4 +4,5 @@
257
+ @@ -4,4 +4,4 @@
291
258
292
259
//! Top-level BSP file for the Raspberry Pi 3 and 4.
293
260
294
261
- // Coming soon.
295
262
+ pub mod cpu;
296
- + pub mod memory;
297
263
298
264
diff -uNr 01_wait_forever/src/cpu.rs 02_runtime_init/src/cpu.rs
299
265
--- 01_wait_forever/src/cpu.rs
@@ -316,24 +282,19 @@ diff -uNr 01_wait_forever/src/cpu.rs 02_runtime_init/src/cpu.rs
316
282
diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs
317
283
--- 01_wait_forever/src/main.rs
318
284
+++ 02_runtime_init/src/main.rs
319
- @@ -102,14 +102,25 @@
285
+ @@ -102,8 +102,8 @@
320
286
//!
321
287
//! 1. The kernel's entry point is the function `cpu::boot::arch_boot::_start()`.
322
288
//! - 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()`.
326
290
327
291
- #![feature(asm)]
328
292
#![feature(global_asm)]
329
293
#![no_main]
330
294
#![no_std]
331
-
332
- mod bsp;
295
+ @@ -112,4 +112,11 @@
333
296
mod cpu;
334
- + mod memory;
335
297
mod panic_wait;
336
- + mod runtime_init;
337
298
338
299
- // Kernel code coming next tutorial.
339
300
+ /// Early init code.
@@ -345,41 +306,6 @@ diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs
345
306
+ panic!()
346
307
+ }
347
308
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
-
383
309
diff -uNr 01_wait_forever/src/panic_wait.rs 02_runtime_init/src/panic_wait.rs
384
310
--- 01_wait_forever/src/panic_wait.rs
385
311
+++ 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
396
322
+ cpu::wait_forever()
397
323
}
398
324
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
-
441
325
```
0 commit comments