Skip to content

Commit 68b81aa

Browse files
committed
Panic: Guard against infinite panic loops
1 parent 0f2db4b commit 68b81aa

File tree

27 files changed

+566
-15
lines changed

27 files changed

+566
-15
lines changed

01_wait_forever/src/panic_wait.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
77
use core::panic::PanicInfo;
88

9+
//--------------------------------------------------------------------------------------------------
10+
// Private Code
11+
//--------------------------------------------------------------------------------------------------
12+
913
#[panic_handler]
1014
fn panic(_info: &PanicInfo) -> ! {
1115
unimplemented!()

02_runtime_init/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,16 @@ diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs
327327
diff -uNr 01_wait_forever/src/panic_wait.rs 02_runtime_init/src/panic_wait.rs
328328
--- 01_wait_forever/src/panic_wait.rs
329329
+++ 02_runtime_init/src/panic_wait.rs
330-
@@ -4,9 +4,10 @@
330+
@@ -4,6 +4,7 @@
331331

332332
//! A panic handler that infinitely waits.
333333

334334
+use crate::cpu;
335335
use core::panic::PanicInfo;
336336

337+
//--------------------------------------------------------------------------------------------------
338+
@@ -12,5 +13,5 @@
339+
337340
#[panic_handler]
338341
fn panic(_info: &PanicInfo) -> ! {
339342
- unimplemented!()

02_runtime_init/src/panic_wait.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
use crate::cpu;
88
use core::panic::PanicInfo;
99

10+
//--------------------------------------------------------------------------------------------------
11+
// Private Code
12+
//--------------------------------------------------------------------------------------------------
13+
1014
#[panic_handler]
1115
fn panic(_info: &PanicInfo) -> ! {
1216
cpu::wait_forever()

03_hacky_hello_world/README.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,17 +238,53 @@ diff -uNr 02_runtime_init/src/main.rs 03_hacky_hello_world/src/main.rs
238238
diff -uNr 02_runtime_init/src/panic_wait.rs 03_hacky_hello_world/src/panic_wait.rs
239239
--- 02_runtime_init/src/panic_wait.rs
240240
+++ 03_hacky_hello_world/src/panic_wait.rs
241-
@@ -4,10 +4,16 @@
241+
@@ -4,14 +4,52 @@
242242

243243
//! A panic handler that infinitely waits.
244244

245245
-use crate::cpu;
246246
+use crate::{cpu, println};
247247
use core::panic::PanicInfo;
248248

249+
//--------------------------------------------------------------------------------------------------
250+
// Private Code
251+
//--------------------------------------------------------------------------------------------------
252+
253+
+/// Stop immediately if called a second time.
254+
+///
255+
+/// # Note
256+
+///
257+
+/// Using atomics here relieves us from needing to use `unsafe` for the static variable.
258+
+///
259+
+/// On `AArch64`, which is the only implemented architecture at the time of writing this,
260+
+/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store
261+
+/// instructions. They are therefore safe to use even with MMU + caching deactivated.
262+
+///
263+
+/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load
264+
+/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store
265+
+fn panic_prevent_reenter() {
266+
+ use core::sync::atomic::{AtomicBool, Ordering};
267+
+
268+
+ #[cfg(not(target_arch = "aarch64"))]
269+
+ compile_error!("Add the target_arch to above's check if the following code is safe to use");
270+
+
271+
+ static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false);
272+
+
273+
+ if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) {
274+
+ PANIC_IN_PROGRESS.store(true, Ordering::Relaxed);
275+
+
276+
+ return;
277+
+ }
278+
+
279+
+ cpu::wait_forever()
280+
+}
281+
+
249282
#[panic_handler]
250283
-fn panic(_info: &PanicInfo) -> ! {
251284
+fn panic(info: &PanicInfo) -> ! {
285+
+ // Protect against panic infinite loops if any of the following code panics itself.
286+
+ panic_prevent_reenter();
287+
+
252288
+ if let Some(args) = info.message() {
253289
+ println!("\nKernel panic: {}", args);
254290
+ } else {

03_hacky_hello_world/src/panic_wait.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,44 @@
77
use crate::{cpu, println};
88
use core::panic::PanicInfo;
99

10+
//--------------------------------------------------------------------------------------------------
11+
// Private Code
12+
//--------------------------------------------------------------------------------------------------
13+
14+
/// Stop immediately if called a second time.
15+
///
16+
/// # Note
17+
///
18+
/// Using atomics here relieves us from needing to use `unsafe` for the static variable.
19+
///
20+
/// On `AArch64`, which is the only implemented architecture at the time of writing this,
21+
/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store
22+
/// instructions. They are therefore safe to use even with MMU + caching deactivated.
23+
///
24+
/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load
25+
/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store
26+
fn panic_prevent_reenter() {
27+
use core::sync::atomic::{AtomicBool, Ordering};
28+
29+
#[cfg(not(target_arch = "aarch64"))]
30+
compile_error!("Add the target_arch to above's check if the following code is safe to use");
31+
32+
static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false);
33+
34+
if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) {
35+
PANIC_IN_PROGRESS.store(true, Ordering::Relaxed);
36+
37+
return;
38+
}
39+
40+
cpu::wait_forever()
41+
}
42+
1043
#[panic_handler]
1144
fn panic(info: &PanicInfo) -> ! {
45+
// Protect against panic infinite loops if any of the following code panics itself.
46+
panic_prevent_reenter();
47+
1248
if let Some(args) = info.message() {
1349
println!("\nKernel panic: {}", args);
1450
} else {

04_safe_globals/src/panic_wait.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,44 @@
77
use crate::{cpu, println};
88
use core::panic::PanicInfo;
99

10+
//--------------------------------------------------------------------------------------------------
11+
// Private Code
12+
//--------------------------------------------------------------------------------------------------
13+
14+
/// Stop immediately if called a second time.
15+
///
16+
/// # Note
17+
///
18+
/// Using atomics here relieves us from needing to use `unsafe` for the static variable.
19+
///
20+
/// On `AArch64`, which is the only implemented architecture at the time of writing this,
21+
/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store
22+
/// instructions. They are therefore safe to use even with MMU + caching deactivated.
23+
///
24+
/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load
25+
/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store
26+
fn panic_prevent_reenter() {
27+
use core::sync::atomic::{AtomicBool, Ordering};
28+
29+
#[cfg(not(target_arch = "aarch64"))]
30+
compile_error!("Add the target_arch to above's check if the following code is safe to use");
31+
32+
static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false);
33+
34+
if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) {
35+
PANIC_IN_PROGRESS.store(true, Ordering::Relaxed);
36+
37+
return;
38+
}
39+
40+
cpu::wait_forever()
41+
}
42+
1043
#[panic_handler]
1144
fn panic(info: &PanicInfo) -> ! {
45+
// Protect against panic infinite loops if any of the following code panics itself.
46+
panic_prevent_reenter();
47+
1248
if let Some(args) = info.message() {
1349
println!("\nKernel panic: {}", args);
1450
} else {

05_drivers_gpio_uart/README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,19 +1414,19 @@ diff -uNr 04_safe_globals/src/main.rs 05_drivers_gpio_uart/src/main.rs
14141414
diff -uNr 04_safe_globals/src/panic_wait.rs 05_drivers_gpio_uart/src/panic_wait.rs
14151415
--- 04_safe_globals/src/panic_wait.rs
14161416
+++ 05_drivers_gpio_uart/src/panic_wait.rs
1417-
@@ -4,15 +4,35 @@
1417+
@@ -4,13 +4,29 @@
14181418

14191419
//! A panic handler that infinitely waits.
14201420

14211421
-use crate::{cpu, println};
14221422
-use core::panic::PanicInfo;
14231423
+use crate::{bsp, cpu};
14241424
+use core::{fmt, panic::PanicInfo};
1425-
+
1426-
+//--------------------------------------------------------------------------------------------------
1427-
+// Private Code
1428-
+//--------------------------------------------------------------------------------------------------
1429-
+
1425+
1426+
//--------------------------------------------------------------------------------------------------
1427+
// Private Code
1428+
//--------------------------------------------------------------------------------------------------
1429+
14301430
+fn _panic_print(args: fmt::Arguments) {
14311431
+ use fmt::Write;
14321432
+
@@ -1442,9 +1442,13 @@ diff -uNr 04_safe_globals/src/panic_wait.rs 05_drivers_gpio_uart/src/panic_wait.
14421442
+ _panic_print(format_args_nl!($($arg)*));
14431443
+ })
14441444
+}
1445+
+
1446+
/// Stop immediately if called a second time.
1447+
///
1448+
/// # Note
1449+
@@ -46,9 +62,9 @@
1450+
panic_prevent_reenter();
14451451

1446-
#[panic_handler]
1447-
fn panic(info: &PanicInfo) -> ! {
14481452
if let Some(args) = info.message() {
14491453
- println!("\nKernel panic: {}", args);
14501454
+ panic_println!("\nKernel panic: {}", args);

05_drivers_gpio_uart/src/panic_wait.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,40 @@ macro_rules! panic_println {
2727
})
2828
}
2929

30+
/// Stop immediately if called a second time.
31+
///
32+
/// # Note
33+
///
34+
/// Using atomics here relieves us from needing to use `unsafe` for the static variable.
35+
///
36+
/// On `AArch64`, which is the only implemented architecture at the time of writing this,
37+
/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store
38+
/// instructions. They are therefore safe to use even with MMU + caching deactivated.
39+
///
40+
/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load
41+
/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store
42+
fn panic_prevent_reenter() {
43+
use core::sync::atomic::{AtomicBool, Ordering};
44+
45+
#[cfg(not(target_arch = "aarch64"))]
46+
compile_error!("Add the target_arch to above's check if the following code is safe to use");
47+
48+
static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false);
49+
50+
if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) {
51+
PANIC_IN_PROGRESS.store(true, Ordering::Relaxed);
52+
53+
return;
54+
}
55+
56+
cpu::wait_forever()
57+
}
58+
3059
#[panic_handler]
3160
fn panic(info: &PanicInfo) -> ! {
61+
// Protect against panic infinite loops if any of the following code panics itself.
62+
panic_prevent_reenter();
63+
3264
if let Some(args) = info.message() {
3365
panic_println!("\nKernel panic: {}", args);
3466
} else {
32 Bytes
Binary file not shown.
24 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)