From 68b81aa6a0c464413145075dc9d4f4a2389a633e Mon Sep 17 00:00:00 2001 From: Andre Richter Date: Fri, 8 Apr 2022 22:24:12 +0200 Subject: [PATCH] Panic: Guard against infinite panic loops --- 01_wait_forever/src/panic_wait.rs | 4 ++ 02_runtime_init/README.md | 5 ++- 02_runtime_init/src/panic_wait.rs | 4 ++ 03_hacky_hello_world/README.md | 38 +++++++++++++++++- 03_hacky_hello_world/src/panic_wait.rs | 36 +++++++++++++++++ 04_safe_globals/src/panic_wait.rs | 36 +++++++++++++++++ 05_drivers_gpio_uart/README.md | 20 +++++---- 05_drivers_gpio_uart/src/panic_wait.rs | 32 +++++++++++++++ 06_uart_chainloader/demo_payload_rpi3.img | Bin 6664 -> 6696 bytes 06_uart_chainloader/demo_payload_rpi4.img | Bin 6512 -> 6536 bytes 06_uart_chainloader/src/panic_wait.rs | 32 +++++++++++++++ 07_timestamps/README.md | 5 ++- 07_timestamps/src/panic_wait.rs | 32 +++++++++++++++ 08_hw_debug_JTAG/src/panic_wait.rs | 32 +++++++++++++++ 09_privilege_level/src/panic_wait.rs | 32 +++++++++++++++ .../src/panic_wait.rs | 32 +++++++++++++++ .../src/panic_wait.rs | 32 +++++++++++++++ 12_integrated_testing/README.md | 11 ++++- 12_integrated_testing/src/panic_wait.rs | 32 +++++++++++++++ 13_exceptions_part2_peripheral_IRQs/README.md | 6 +-- .../src/panic_wait.rs | 32 +++++++++++++++ .../src/panic_wait.rs | 32 +++++++++++++++ .../src/panic_wait.rs | 32 +++++++++++++++ .../src/panic_wait.rs | 32 +++++++++++++++ X1_JTAG_boot/jtag_boot_rpi3.img | Bin 7808 -> 7840 bytes X1_JTAG_boot/jtag_boot_rpi4.img | Bin 6832 -> 6864 bytes X1_JTAG_boot/src/panic_wait.rs | 32 +++++++++++++++ 27 files changed, 566 insertions(+), 15 deletions(-) diff --git a/01_wait_forever/src/panic_wait.rs b/01_wait_forever/src/panic_wait.rs index c0ee2be3..c9a8f5e4 100644 --- a/01_wait_forever/src/panic_wait.rs +++ b/01_wait_forever/src/panic_wait.rs @@ -6,6 +6,10 @@ use core::panic::PanicInfo; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + #[panic_handler] fn panic(_info: &PanicInfo) -> ! { unimplemented!() diff --git a/02_runtime_init/README.md b/02_runtime_init/README.md index bcb3f8c3..221113ef 100644 --- a/02_runtime_init/README.md +++ b/02_runtime_init/README.md @@ -327,13 +327,16 @@ diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs 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 @@ +@@ -4,6 +4,7 @@ //! A panic handler that infinitely waits. +use crate::cpu; use core::panic::PanicInfo; + //-------------------------------------------------------------------------------------------------- +@@ -12,5 +13,5 @@ + #[panic_handler] fn panic(_info: &PanicInfo) -> ! { - unimplemented!() diff --git a/02_runtime_init/src/panic_wait.rs b/02_runtime_init/src/panic_wait.rs index cc0e1ae0..7e9adfce 100644 --- a/02_runtime_init/src/panic_wait.rs +++ b/02_runtime_init/src/panic_wait.rs @@ -7,6 +7,10 @@ use crate::cpu; use core::panic::PanicInfo; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + #[panic_handler] fn panic(_info: &PanicInfo) -> ! { cpu::wait_forever() diff --git a/03_hacky_hello_world/README.md b/03_hacky_hello_world/README.md index 131e45b3..dffbbb8a 100644 --- a/03_hacky_hello_world/README.md +++ b/03_hacky_hello_world/README.md @@ -238,7 +238,7 @@ diff -uNr 02_runtime_init/src/main.rs 03_hacky_hello_world/src/main.rs diff -uNr 02_runtime_init/src/panic_wait.rs 03_hacky_hello_world/src/panic_wait.rs --- 02_runtime_init/src/panic_wait.rs +++ 03_hacky_hello_world/src/panic_wait.rs -@@ -4,10 +4,16 @@ +@@ -4,14 +4,52 @@ //! A panic handler that infinitely waits. @@ -246,9 +246,45 @@ diff -uNr 02_runtime_init/src/panic_wait.rs 03_hacky_hello_world/src/panic_wait. +use crate::{cpu, println}; use core::panic::PanicInfo; + //-------------------------------------------------------------------------------------------------- + // Private Code + //-------------------------------------------------------------------------------------------------- + ++/// Stop immediately if called a second time. ++/// ++/// # Note ++/// ++/// Using atomics here relieves us from needing to use `unsafe` for the static variable. ++/// ++/// On `AArch64`, which is the only implemented architecture at the time of writing this, ++/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store ++/// instructions. They are therefore safe to use even with MMU + caching deactivated. ++/// ++/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load ++/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store ++fn panic_prevent_reenter() { ++ use core::sync::atomic::{AtomicBool, Ordering}; ++ ++ #[cfg(not(target_arch = "aarch64"))] ++ compile_error!("Add the target_arch to above's check if the following code is safe to use"); ++ ++ static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); ++ ++ if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { ++ PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); ++ ++ return; ++ } ++ ++ cpu::wait_forever() ++} ++ #[panic_handler] -fn panic(_info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { ++ // Protect against panic infinite loops if any of the following code panics itself. ++ panic_prevent_reenter(); ++ + if let Some(args) = info.message() { + println!("\nKernel panic: {}", args); + } else { diff --git a/03_hacky_hello_world/src/panic_wait.rs b/03_hacky_hello_world/src/panic_wait.rs index 3c1ca85b..e37724a4 100644 --- a/03_hacky_hello_world/src/panic_wait.rs +++ b/03_hacky_hello_world/src/panic_wait.rs @@ -7,8 +7,44 @@ use crate::{cpu, println}; use core::panic::PanicInfo; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + if let Some(args) = info.message() { println!("\nKernel panic: {}", args); } else { diff --git a/04_safe_globals/src/panic_wait.rs b/04_safe_globals/src/panic_wait.rs index 3c1ca85b..e37724a4 100644 --- a/04_safe_globals/src/panic_wait.rs +++ b/04_safe_globals/src/panic_wait.rs @@ -7,8 +7,44 @@ use crate::{cpu, println}; use core::panic::PanicInfo; +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + if let Some(args) = info.message() { println!("\nKernel panic: {}", args); } else { diff --git a/05_drivers_gpio_uart/README.md b/05_drivers_gpio_uart/README.md index d54fa722..44e5aadf 100644 --- a/05_drivers_gpio_uart/README.md +++ b/05_drivers_gpio_uart/README.md @@ -1414,7 +1414,7 @@ diff -uNr 04_safe_globals/src/main.rs 05_drivers_gpio_uart/src/main.rs diff -uNr 04_safe_globals/src/panic_wait.rs 05_drivers_gpio_uart/src/panic_wait.rs --- 04_safe_globals/src/panic_wait.rs +++ 05_drivers_gpio_uart/src/panic_wait.rs -@@ -4,15 +4,35 @@ +@@ -4,13 +4,29 @@ //! A panic handler that infinitely waits. @@ -1422,11 +1422,11 @@ diff -uNr 04_safe_globals/src/panic_wait.rs 05_drivers_gpio_uart/src/panic_wait. -use core::panic::PanicInfo; +use crate::{bsp, cpu}; +use core::{fmt, panic::PanicInfo}; -+ -+//-------------------------------------------------------------------------------------------------- -+// Private Code -+//-------------------------------------------------------------------------------------------------- -+ + + //-------------------------------------------------------------------------------------------------- + // Private Code + //-------------------------------------------------------------------------------------------------- + +fn _panic_print(args: fmt::Arguments) { + use fmt::Write; + @@ -1442,9 +1442,13 @@ diff -uNr 04_safe_globals/src/panic_wait.rs 05_drivers_gpio_uart/src/panic_wait. + _panic_print(format_args_nl!($($arg)*)); + }) +} ++ + /// Stop immediately if called a second time. + /// + /// # Note +@@ -46,9 +62,9 @@ + panic_prevent_reenter(); - #[panic_handler] - fn panic(info: &PanicInfo) -> ! { if let Some(args) = info.message() { - println!("\nKernel panic: {}", args); + panic_println!("\nKernel panic: {}", args); diff --git a/05_drivers_gpio_uart/src/panic_wait.rs b/05_drivers_gpio_uart/src/panic_wait.rs index 946041b3..e879b5b3 100644 --- a/05_drivers_gpio_uart/src/panic_wait.rs +++ b/05_drivers_gpio_uart/src/panic_wait.rs @@ -27,8 +27,40 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + if let Some(args) = info.message() { panic_println!("\nKernel panic: {}", args); } else { diff --git a/06_uart_chainloader/demo_payload_rpi3.img b/06_uart_chainloader/demo_payload_rpi3.img index 800ae2132d4aaf9745d5e39fe7fa3e8986e34362..b95058e4377a7f061a86cb39025e188660b064fe 100755 GIT binary patch delta 974 zcmYjPUr1A76hGg+`=4(2PPe<;THBm?H=!aM$VSjKhNeVf4?fOWWFq~6Ug{<1QxZMw z<1;LX)Q4c#he(Fd5Mts}&_hy5(nFg*xYmiU=R{hcz;NY+;-_O_(6L6Cu_6d^~@>^^-V$xDxGVUT%TEdaE zJMTB|uxK#PAA8B5GI`V3k22(6qc@N@4011I2CI@$w$joF@{(D5{7jb* zFYR(z4K=CZ^a)K@We8-Ab>4^XcZcyFrKGxu*%7x*hU(I(+wVBZ1W%H2N4pLA@%o6Q zCCxfIn3gd4?C7wM_;E$4cUH@rxITvdQe209GN7_#`{+z6GRwtH>7Z8rgKP6ylQr5t z+b$*wRS0xmM2UipPuBX3fNeZ!;X50tH|_)HQyOXD$xXg9SZc-H#Sp%pX~kt0;ok?! zjJhbg#4JLYL6{@&c`sv3lJ9&xYE0Jr&!FIc0fi!)T31%l+QE6ynp#(G#l`@lsQ~*` zQ4}FUN3^blV;{+Br-$j{NssdtKkUL`1O>Xcth(07JlS)$ARuB>ZsG_QRH_SLMDt$*B?2GM|qEg5+vps6)nf>*gZXm)BWe9 e;OSvFkuc&TG({#w3B4n-=s#S7>ZbSol?=#95LxFr?=BRiJ^qBb(q%gd2Ba7yp1$T-jB=op4GhE9-s{y%M6$ ziZkmoZ15zJ6?Q%0$Yp#{pCEvL>pjtNnSKWt0s=F@6k%4Tr~Z|P^8hnNh6mW^2mePS z|B#|nOauboZ5|J=IFk; zJ#^-tm8y_kg%wYwuVNQuDyji5z4czEznLWK3k{a2i8NMQXKBLHz)g6u-_l}AHPDqp zsIqCy65*c7xNM1-3k|ebuAZ!x+pTeq{kp9YGx4h`={WPGGGo@LUh!ATzgR=wQb&m$ zpKg(2xi#>&9VM}xi5xG*bwEu7gF;(9%lf@wd&rPFf>(sLz@;YI9&4mM&_orU(9Ny# zusSF<#55tvPVnP9!NYBK;AbHk+3YC!9zo7G0=Zefd!;;2mbMN-X_*xbGE2s<&u=CT z@Y=+Rzp>uqOIGZ$Jr(i}8YYlq<4UX3Y!0B!9wY`lY@f94;KC|55yGE#R~@_V;$2;) zFc0(t3J%8s)u(?i^BJNF121YmjZLvkfhSXW-Z-W3wNw3DWf34&dWq*8WgKw3alm;} zcq_5F?1)iZbp8?UyQ-*5V@7ewEt)UfcqQ#%~QhO0BVoRauMJis32+2V~ zi{K7ZD1wJj53*it4H0{56c0UBQ0vj8BBZ_a4~h|VeY+Wh4;JS8-kWc}_hxpl_u)x3 z=ty-CjL>o<+p!|IaE@sUS}<`bKgcy9o5y5Z=Cztr`nvT*0*8nXA+>OjB$X>jGX=rIHBxeu(sM+%ps~e2`eLd9B@cPiu4;>f={J|Z-zed0CG${{ zv!H(HMzyaF8(pbg!PM#wl9EF>wdyDiS4XUfIEu7OIBf^?7*KPO-V(aqS&48^e|9o# zj9Q(RB>GD5wV7J!nSq-K^<9_vFS@P=jK=Nhj)Cv=gRsD*Wjf(*Z#J!Bvh^O3D1G3* zf2|lbCsa{*V|uC$o`asTXcd@Jy*C+*!-gZc_uMbN58i=_{uxO{n2{(cLroT%WA8z= z73hpd#@YP5$Bk*uJ1MM*aK?WT&kMdrEO`7i8m`HVIF0+mc#K~1E0H;tv#{JfhV2Y* zP~r~+-!j(9*q%gxq6gL=Y0)1RDlF@&@7eb&17e_ds+X~n83`%H_y)$GXBg&g#s<9{ zP=qkh%jbIJ! Nu_4VeEYfta`!D)w4)_27 delta 951 zcmYjPT}V@L6#xJ4-E^BD+uhvm*35l5t}{@wY-Nzkq)cDJm#hq21>r;X&_mG6W(ZjX z-9Kkw4?S!K)eWL-Eb~q4$v2^}dTJAbIf6n#u&{ORN78`{|KIueo!>d#X;=2!U>l*@(le)9%3=fW&DnRnK1@Knm1 z>mG5G!feA3mlfehLsw5C%0?;45K0OJsmWNBo!Y6+6bUJuMt_i~U+|*^W0qVi;|Xcf z-lbN!(0C}6^s=&KRt89VxDugCHN`3GJZ0+P+Tk|jZpw8Yx)6j1By9**)rs?6bM3k*hoL)Ey=j{QE-?IBd$z~SA z)*d8ToeiTD6G|{ETd5koeHz}_B}-qF75S#;W%y=qtxcthA{(PPTCfIh1y?;$y_ ztClY>2H>UOrWGg&8LkwDo6eScO%7#i?+J@R&N+24i6>U|O1!!u*@7pprc6p1H?gZf zg5t1X2XCAGRXvEemdU?n#h}qF#7dZR2L~{2E?X41?TXM~{)x*;;k&mPR+Em`9J9jMxDoT{Veo+jyi8_Cc5$iB8Zd0>)7#AgB%<$r0XLxhS@DP^8URngJ uH$_L_u2-VdFy{^Ij%nY`E_o&EluPfF0m0YlJLA*QXG8ypfeD=Rb^Zle%m(iO diff --git a/06_uart_chainloader/src/panic_wait.rs b/06_uart_chainloader/src/panic_wait.rs index 946041b3..e879b5b3 100644 --- a/06_uart_chainloader/src/panic_wait.rs +++ b/06_uart_chainloader/src/panic_wait.rs @@ -27,8 +27,40 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + if let Some(args) = info.message() { panic_println!("\nKernel panic: {}", args); } else { diff --git a/07_timestamps/README.md b/07_timestamps/README.md index 762e3cb3..bfd2ee14 100644 --- a/07_timestamps/README.md +++ b/07_timestamps/README.md @@ -635,12 +635,15 @@ diff -uNr 06_uart_chainloader/src/main.rs 07_timestamps/src/main.rs diff -uNr 06_uart_chainloader/src/panic_wait.rs 07_timestamps/src/panic_wait.rs --- 06_uart_chainloader/src/panic_wait.rs +++ 07_timestamps/src/panic_wait.rs -@@ -29,10 +29,23 @@ +@@ -58,13 +58,26 @@ #[panic_handler] fn panic(info: &PanicInfo) -> ! { + use crate::time::interface::TimeManager; + + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + + let timestamp = crate::time::time_manager().uptime(); + if let Some(args) = info.message() { diff --git a/07_timestamps/src/panic_wait.rs b/07_timestamps/src/panic_wait.rs index 923db329..3c57f562 100644 --- a/07_timestamps/src/panic_wait.rs +++ b/07_timestamps/src/panic_wait.rs @@ -27,10 +27,42 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/08_hw_debug_JTAG/src/panic_wait.rs b/08_hw_debug_JTAG/src/panic_wait.rs index 923db329..3c57f562 100644 --- a/08_hw_debug_JTAG/src/panic_wait.rs +++ b/08_hw_debug_JTAG/src/panic_wait.rs @@ -27,10 +27,42 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/09_privilege_level/src/panic_wait.rs b/09_privilege_level/src/panic_wait.rs index 923db329..3c57f562 100644 --- a/09_privilege_level/src/panic_wait.rs +++ b/09_privilege_level/src/panic_wait.rs @@ -27,10 +27,42 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/10_virtual_mem_part1_identity_mapping/src/panic_wait.rs b/10_virtual_mem_part1_identity_mapping/src/panic_wait.rs index 923db329..3c57f562 100644 --- a/10_virtual_mem_part1_identity_mapping/src/panic_wait.rs +++ b/10_virtual_mem_part1_identity_mapping/src/panic_wait.rs @@ -27,10 +27,42 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/11_exceptions_part1_groundwork/src/panic_wait.rs b/11_exceptions_part1_groundwork/src/panic_wait.rs index 923db329..3c57f562 100644 --- a/11_exceptions_part1_groundwork/src/panic_wait.rs +++ b/11_exceptions_part1_groundwork/src/panic_wait.rs @@ -27,10 +27,42 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/12_integrated_testing/README.md b/12_integrated_testing/README.md index b5649cd0..5de7c0ef 100644 --- a/12_integrated_testing/README.md +++ b/12_integrated_testing/README.md @@ -1744,7 +1744,16 @@ diff -uNr 11_exceptions_part1_groundwork/src/panic_wait.rs 12_integrated_testing /// Prints with a newline - only use from the panic handler. /// /// Carbon copy from -@@ -48,5 +65,5 @@ +@@ -53,7 +70,7 @@ + return; + } + +- cpu::wait_forever() ++ _panic_exit() + } + + #[panic_handler] +@@ -80,5 +97,5 @@ ); } diff --git a/12_integrated_testing/src/panic_wait.rs b/12_integrated_testing/src/panic_wait.rs index 2e56f1ce..a1b090d7 100644 --- a/12_integrated_testing/src/panic_wait.rs +++ b/12_integrated_testing/src/panic_wait.rs @@ -44,10 +44,42 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + _panic_exit() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/13_exceptions_part2_peripheral_IRQs/README.md b/13_exceptions_part2_peripheral_IRQs/README.md index 72b3fa5e..d89093df 100644 --- a/13_exceptions_part2_peripheral_IRQs/README.md +++ b/13_exceptions_part2_peripheral_IRQs/README.md @@ -2511,15 +2511,15 @@ diff -uNr 12_integrated_testing/src/panic_wait.rs 13_exceptions_part2_peripheral use core::{fmt, panic::PanicInfo}; //-------------------------------------------------------------------------------------------------- -@@ -48,6 +48,8 @@ +@@ -77,6 +77,8 @@ fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; + unsafe { exception::asynchronous::local_irq_mask() }; + - let timestamp = crate::time::time_manager().uptime(); + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); - if let Some(args) = info.message() { diff -uNr 12_integrated_testing/src/state.rs 13_exceptions_part2_peripheral_IRQs/src/state.rs --- 12_integrated_testing/src/state.rs diff --git a/13_exceptions_part2_peripheral_IRQs/src/panic_wait.rs b/13_exceptions_part2_peripheral_IRQs/src/panic_wait.rs index da7106c9..787bc7dc 100644 --- a/13_exceptions_part2_peripheral_IRQs/src/panic_wait.rs +++ b/13_exceptions_part2_peripheral_IRQs/src/panic_wait.rs @@ -44,12 +44,44 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + _panic_exit() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; unsafe { exception::asynchronous::local_irq_mask() }; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/14_virtual_mem_part2_mmio_remap/src/panic_wait.rs b/14_virtual_mem_part2_mmio_remap/src/panic_wait.rs index da7106c9..787bc7dc 100644 --- a/14_virtual_mem_part2_mmio_remap/src/panic_wait.rs +++ b/14_virtual_mem_part2_mmio_remap/src/panic_wait.rs @@ -44,12 +44,44 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + _panic_exit() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; unsafe { exception::asynchronous::local_irq_mask() }; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/15_virtual_mem_part3_precomputed_tables/src/panic_wait.rs b/15_virtual_mem_part3_precomputed_tables/src/panic_wait.rs index da7106c9..787bc7dc 100644 --- a/15_virtual_mem_part3_precomputed_tables/src/panic_wait.rs +++ b/15_virtual_mem_part3_precomputed_tables/src/panic_wait.rs @@ -44,12 +44,44 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + _panic_exit() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; unsafe { exception::asynchronous::local_irq_mask() }; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/16_virtual_mem_part4_higher_half_kernel/src/panic_wait.rs b/16_virtual_mem_part4_higher_half_kernel/src/panic_wait.rs index da7106c9..787bc7dc 100644 --- a/16_virtual_mem_part4_higher_half_kernel/src/panic_wait.rs +++ b/16_virtual_mem_part4_higher_half_kernel/src/panic_wait.rs @@ -44,12 +44,44 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + _panic_exit() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; unsafe { exception::asynchronous::local_irq_mask() }; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() { diff --git a/X1_JTAG_boot/jtag_boot_rpi3.img b/X1_JTAG_boot/jtag_boot_rpi3.img index 64189d659354f3894c8887bc419ede120173112f..9fcd693ec7b0fc4bda4a744f682aa366843ed900 100755 GIT binary patch delta 924 zcmah`T}TvB6ux(+tyx8PXLsFoXSdy%m3A7--%NAC-=IV(WgmnL%Ce+T>Mco-MvPdo zA1_BL2uUBu2$aPK=|$-wdXlgndTLDycYWzCjB2}gXP|`$&&%PQd%o{{=ev5-T+_7Q zuEz*QXi-^Rib$NJ)rMwRnc6}`K}xcVE5LXadifC!mnGNvPP`vSh=wB&wq53MBspPw zXe+@g(Re+cd5y>sq{r{m5oHddg}wM&a;)$!N3pQZ6PPLfg2!Rh(Z$J8c;mRiDKThp zHiy>A$uPyeyi`Zhr_ru3w(zWz*6EWu5dhA!+?Wbm&RPcWiKi+RjqJ4W#uObo{A+N- zj?lE$*1!&#-tI;#*JwXeWiv7s!IT&+&}&G0e>EA9Yv7d_<*rgb@fL1_K39ti#mFIy zW)Mcph*BUq1}|Jv@!Ctll>K?h9 zL-SRC&vECS!<*;qxZCs9GMqLshio?M(6*0(u%xJVqU`bN#vd<)|hE1tT(nDsIlFXd2Y9RpSfsoh}Fxy^h(;%D+gmD6H2fCG% prRskw7a<*J!6!fq-ocAt1jCWN5OxVN!F%FAWAHJ^md+pi^aopH^xgmf delta 923 zcmah`-%C?r7=FKVoNbD_v(34k&22|%b7sw%KUm<;$V{QdF1+Y!DaF9*QcI9F?7}eW ze7urH7flf26hSh&kZu&g@JhsPx@snZn}2|KVfLM!0}Unm;PCSPc%Jup-jnW3cFIl@ zT%iQuvjj_ZB3BhLz?_<9cY#VtUuK9aBcun1`3Wvnm)Yb8Noh)=!IXqv!w8p>GSh|^ zhU%1`2Ki(xzXtRIBxBFnh~z_m`7p_4rpljk42zpQ#ktBoLU6Kbh)bWxZ&eSug$Q<- zyF9&(^ghFV+PO?~*Wt)G_2KOx%X3!?A`s0txnn=>np;#rjnIE-p@ANB^U5q6YB;{P zZ32*ktL>^0c|Quv30BXC3`$-nm=*kG5TP!EAQ zAn*kk1*9YR(IQs%Hc=kHW@IH}stLC(?au5)nq{Q>ff8jvT@o-Th2;{~S;tg$FRfi3 zDfHKlwa5;y**UQG6|3p6wc(6yfGpycZMx$9?~{2WypGMhg5^cLQ+=y-wTOeHlM znGK06B*r~jwjydVq38P|4!S%-vr8-6^-cZw*ySY&eB+8rE4r$Gsg%*=?j{br;eJA7 e+;Dq^GYDL$^`fKpQTR;fl;e$4juW_A`|}T@Wcn%q diff --git a/X1_JTAG_boot/jtag_boot_rpi4.img b/X1_JTAG_boot/jtag_boot_rpi4.img index 6c029255bf7f1c2d8b7941ca8d39524fc1606c02..fb16a02b18124c41465c5d4ffafac9455f46d64c 100755 GIT binary patch delta 738 zcmaiyOK1~O6o${elaw?u&8st$8QUhKO=A*85o0agWa`2~5v7XIm8o4xp-`v~+?b*Z zl@f9|g)VLFMqNe5f^JI1g$ox(@CCYP&XXK5Lr_$Sj4It}R$f}jS_ zk6iSTjb4;QpIYw2rr0Ssp2v~+``uyKalIRP920Y3u;ywzkC~s&k`1sn>iS`^mD|FI z1e*I>f!!{X(L-- zxLW(yzx2UR(DrXfa7wsJJ7m>4x)EYX7@ z#B?$wcoX!*tz<)@!6+N!Sxo$MZSjENxgT@1MnSAqpGxNQdx0$VFtA=kQ zg94zI;@p!JbE{Kdg@3jU7TjXg%t@b+6_qY1_ob!LZUAYr?Nz&_;((=6#B*I*s(IJ* z#G_hAaX_gQcHRM=gi2wakyMdl{wre8yybr+x!v3i+!11g%E3!o-N5IJDS`Z65fWd3 zO~6lsJ_KW8oOXhvG!_~YtAwG=jz$9K81(~GZ#0s0GyJAQB=CE>eZ|Wq?`%KiI%5wu zqFA4nxb;xr{k9kD0BaKt4-3t?O&dXPDc&3ybv!M{>09SnY4uV(((SGE zVf{SdJsOGJ_LVYtg!y?ZO>ZN8lHG4dj^~^1UkKdd*W2Fz*Zn%{|J|Q(-9s-nxaYk& z9#sTgR*T^ol^y&QWz$lJg;9;U<;R+vpSE<3!g^Z%(&(IC7BjS>52s!lF2c8QV!fsL zPdHH{(WMU^MlI>?lu)bdhi+c%(u6oeCF6AXYHOy}IxW+(kq}j~jEO_{zox<1vp?ml B!ZQE> diff --git a/X1_JTAG_boot/src/panic_wait.rs b/X1_JTAG_boot/src/panic_wait.rs index 923db329..3c57f562 100644 --- a/X1_JTAG_boot/src/panic_wait.rs +++ b/X1_JTAG_boot/src/panic_wait.rs @@ -27,10 +27,42 @@ macro_rules! panic_println { }) } +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { use crate::time::interface::TimeManager; + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + let timestamp = crate::time::time_manager().uptime(); if let Some(args) = info.message() {