From 71187f65f49bf1b4fa764215dc1b73e7e980742a Mon Sep 17 00:00:00 2001 From: Norbert Fabritius Date: Thu, 15 Dec 2022 11:41:19 +0100 Subject: [PATCH 1/6] Add zero-init-ram feature Add the 'zero-init-ram' feature that initializes the RAM with zeros during startup. This is normally not necessary but might be required on custom hardware. If this step is skipped on such hardware, reading from memory that was never written to will cause a hard-fault. --- cortex-m-rt/Cargo.toml | 1 + cortex-m-rt/link.x.in | 4 +++- cortex-m-rt/src/lib.rs | 29 +++++++++++++++++++++-------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/cortex-m-rt/Cargo.toml b/cortex-m-rt/Cargo.toml index f8438fb3..3305d34e 100644 --- a/cortex-m-rt/Cargo.toml +++ b/cortex-m-rt/Cargo.toml @@ -45,6 +45,7 @@ required-features = ["device"] device = [] set-sp = [] set-vtor = [] +zero-init-ram = [] [package.metadata.docs.rs] features = ["device"] diff --git a/cortex-m-rt/link.x.in b/cortex-m-rt/link.x.in index 551f576e..f699decc 100644 --- a/cortex-m-rt/link.x.in +++ b/cortex-m-rt/link.x.in @@ -60,7 +60,9 @@ PROVIDE(__pre_init = DefaultPreInit); /* # Sections */ SECTIONS { - PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM)); + PROVIDE(_ram_start = ORIGIN(RAM) + LENGTH(RAM)); + PROVIDE(_ram_end = ORIGIN(RAM)); + PROVIDE(_stack_start = _ram_start); /* ## Sections in FLASH */ /* ### Vector table */ diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 2070efa3..96d89ddd 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -514,6 +514,19 @@ cfg_global_asm! { "ldr r0, =_stack_start msr msp, r0", + // If enabled, initialize RAM with zeros. This is normally not necessary but might be required + // on custom hardware. + #[cfg(feature = "zero-init-ram")] + "ldr r0, =_ram_end + ldr r1, =_ram_start + movs r2, #0 + 0: + cmp r1, r0 + beq 1f + stm r0!, {{r2}} + b 0b + 1:", + // If enabled, initialise VTOR to the start of the vector table. This is normally initialised // by a bootloader when the non-reset value is required, but some bootloaders do not set it, // leading to frustrating issues where everything seems to work but interrupts are never @@ -533,24 +546,24 @@ cfg_global_asm! { "ldr r0, =__sbss ldr r1, =__ebss movs r2, #0 - 0: + 2: cmp r1, r0 - beq 1f + beq 3f stm r0!, {{r2}} - b 0b - 1:", + b 2b + 3:", // Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the linker script. "ldr r0, =__sdata ldr r1, =__edata ldr r2, =__sidata - 2: + 4: cmp r1, r0 - beq 3f + beq 5f ldm r2!, {{r3}} stm r0!, {{r3}} - b 2b - 3:", + b 4b + 5:", // Potentially enable an FPU. // SCB.CPACR is 0xE000_ED88. From 4714f43cf88198cdfbe19839e1ff7809033d3b42 Mon Sep 17 00:00:00 2001 From: Norbert Fabritius Date: Mon, 19 Dec 2022 15:24:27 +0100 Subject: [PATCH 2/6] Fix _ram_start and _ram_end order --- cortex-m-rt/link.x.in | 6 +++--- cortex-m-rt/src/lib.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cortex-m-rt/link.x.in b/cortex-m-rt/link.x.in index f699decc..01bef98d 100644 --- a/cortex-m-rt/link.x.in +++ b/cortex-m-rt/link.x.in @@ -60,9 +60,9 @@ PROVIDE(__pre_init = DefaultPreInit); /* # Sections */ SECTIONS { - PROVIDE(_ram_start = ORIGIN(RAM) + LENGTH(RAM)); - PROVIDE(_ram_end = ORIGIN(RAM)); - PROVIDE(_stack_start = _ram_start); + PROVIDE(_ram_start = ORIGIN(RAM)); + PROVIDE(_ram_end = ORIGIN(RAM) + LENGTH(RAM)); + PROVIDE(_stack_start = _ram_end); /* ## Sections in FLASH */ /* ### Vector table */ diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 96d89ddd..b90b124c 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -517,8 +517,8 @@ cfg_global_asm! { // If enabled, initialize RAM with zeros. This is normally not necessary but might be required // on custom hardware. #[cfg(feature = "zero-init-ram")] - "ldr r0, =_ram_end - ldr r1, =_ram_start + "ldr r0, =_ram_start + ldr r1, =_ram_end movs r2, #0 0: cmp r1, r0 From 26cae65548eb2c594427caf4a9638e0fdc4f1ba1 Mon Sep 17 00:00:00 2001 From: Norbert Fabritius Date: Mon, 9 Jan 2023 11:02:18 +0100 Subject: [PATCH 3/6] Add documentation, test and changelog entry for `zero-init-ram` feature --- cortex-m-rt/CHANGELOG.md | 4 ++-- cortex-m-rt/ci/script.sh | 2 ++ cortex-m-rt/src/lib.rs | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/cortex-m-rt/CHANGELOG.md b/cortex-m-rt/CHANGELOG.md index 65144cfe..7f1226a1 100644 --- a/cortex-m-rt/CHANGELOG.md +++ b/cortex-m-rt/CHANGELOG.md @@ -7,14 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -## [v0.7.3] - - Fixed a potential miscompilation caused by the initial stack pointer not being 8-byte aligned. This issue affected 0.7.1 and 0.7.2; for more details please see [the advisory] ([#467]). - A linker error is generated if the initial stack pointer is not 8-byte aligned ([#464]). - The initial stack pointer is now forced to be 8-byte aligned in the linker script, to defend against it being overridden outside of the cortex-m-rt linker script ([#465]). +- Add `zero-init-ram` feature to initialize RAM with zeros on startup. This can be necessary on + safety-critical hardware to properly initialize memory integrity measures. [the advisory]: https://github.com/rust-embedded/cortex-m/discussions/469 [#464]: https://github.com/rust-embedded/cortex-m/issues/464 diff --git a/cortex-m-rt/ci/script.sh b/cortex-m-rt/ci/script.sh index 2941e484..02ba51f0 100755 --- a/cortex-m-rt/ci/script.sh +++ b/cortex-m-rt/ci/script.sh @@ -63,6 +63,8 @@ main() { cargo rustc --target "$TARGET" --example minimal --features "set-sp,${needed_features}" -- $linker cargo rustc --target "$TARGET" --example minimal --features "set-sp,${needed_features}" --release -- $linker + cargo rustc --target "$TARGET" --example minimal --features "zero-init-ram,${needed_features}" -- $linker + cargo rustc --target "$TARGET" --example minimal --features "zero-init-ram,${needed_features}" --release -- $linker cargo rustc --target "$TARGET" --example minimal --features "set-vtor,${needed_features}" -- $linker cargo rustc --target "$TARGET" --example minimal --features "set-vtor,${needed_features}" --release -- $linker done diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index b90b124c..f9df60a1 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -169,6 +169,13 @@ //! `_stack_start` value from the linker script. This is not usually required, but some debuggers //! do not initialise SP when performing a soft reset, which can lead to stack corruption. //! +//! ## `zero-init-ram` +//! +//! If this feature is enabled, RAM is initialized with zeros during startup from the `_ram_start` +//! value to the `_ram_end` value from the linker script. This is not usually required, but might be +//! necessary to properly initialize checksum-based memory integrity measures on safety-critical +//! hardware. +//! //! ## `set-vtor` //! //! If this feature is enabled, the vector table offset register (VTOR) is initialised in the reset From 4bf9ef46bae593974e00b3ca072341586d492164 Mon Sep 17 00:00:00 2001 From: Norbert Fabritius Date: Wed, 11 Jan 2023 13:34:38 +0100 Subject: [PATCH 4/6] zero-init-ram: Expand comment above asm code --- cortex-m-rt/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index f9df60a1..6f9f299d 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -521,8 +521,8 @@ cfg_global_asm! { "ldr r0, =_stack_start msr msp, r0", - // If enabled, initialize RAM with zeros. This is normally not necessary but might be required - // on custom hardware. + // If enabled, initialize RAM with zeros. This is not usually required, but might be necessary + // to properly initialize checksum-based memory integrity measures on safety-critical hardware. #[cfg(feature = "zero-init-ram")] "ldr r0, =_ram_start ldr r1, =_ram_end From e50149446c6af5919f928317840716c442a342fe Mon Sep 17 00:00:00 2001 From: Norbert Fabritius Date: Wed, 11 Jan 2023 14:01:56 +0100 Subject: [PATCH 5/6] Skip .bss memory init if zero-init-ram is active --- cortex-m-rt/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 6f9f299d..30fe37e8 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -550,6 +550,7 @@ cfg_global_asm! { "bl __pre_init", // Initialise .bss memory. `__sbss` and `__ebss` come from the linker script. + #[cfg(not(feature = "zero-init-ram"))] "ldr r0, =__sbss ldr r1, =__ebss movs r2, #0 From 9b51b40a96f94a144b6f2006729ac01c52896c67 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Fri, 17 Feb 2023 21:22:49 +0000 Subject: [PATCH 6/6] Move zero-init-ram to just before bss initialisation, so that pre_init occurs before --- cortex-m-rt/CHANGELOG.md | 7 +++++-- cortex-m-rt/src/lib.rs | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/cortex-m-rt/CHANGELOG.md b/cortex-m-rt/CHANGELOG.md index 7f1226a1..fd45a1a0 100644 --- a/cortex-m-rt/CHANGELOG.md +++ b/cortex-m-rt/CHANGELOG.md @@ -7,14 +7,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- Add `zero-init-ram` feature to initialize RAM with zeros on startup. This can be necessary on + safety-critical hardware to properly initialize memory integrity measures. + +## [v0.7.3] + - Fixed a potential miscompilation caused by the initial stack pointer not being 8-byte aligned. This issue affected 0.7.1 and 0.7.2; for more details please see [the advisory] ([#467]). - A linker error is generated if the initial stack pointer is not 8-byte aligned ([#464]). - The initial stack pointer is now forced to be 8-byte aligned in the linker script, to defend against it being overridden outside of the cortex-m-rt linker script ([#465]). -- Add `zero-init-ram` feature to initialize RAM with zeros on startup. This can be necessary on - safety-critical hardware to properly initialize memory integrity measures. [the advisory]: https://github.com/rust-embedded/cortex-m/discussions/469 [#464]: https://github.com/rust-embedded/cortex-m/issues/464 diff --git a/cortex-m-rt/src/lib.rs b/cortex-m-rt/src/lib.rs index 30fe37e8..a6d946c4 100644 --- a/cortex-m-rt/src/lib.rs +++ b/cortex-m-rt/src/lib.rs @@ -521,19 +521,6 @@ cfg_global_asm! { "ldr r0, =_stack_start msr msp, r0", - // If enabled, initialize RAM with zeros. This is not usually required, but might be necessary - // to properly initialize checksum-based memory integrity measures on safety-critical hardware. - #[cfg(feature = "zero-init-ram")] - "ldr r0, =_ram_start - ldr r1, =_ram_end - movs r2, #0 - 0: - cmp r1, r0 - beq 1f - stm r0!, {{r2}} - b 0b - 1:", - // If enabled, initialise VTOR to the start of the vector table. This is normally initialised // by a bootloader when the non-reset value is required, but some bootloaders do not set it, // leading to frustrating issues where everything seems to work but interrupts are never @@ -549,6 +536,19 @@ cfg_global_asm! { // Example use cases include disabling default watchdogs or enabling RAM. "bl __pre_init", + // If enabled, initialize RAM with zeros. This is not usually required, but might be necessary + // to properly initialize checksum-based memory integrity measures on safety-critical hardware. + #[cfg(feature = "zero-init-ram")] + "ldr r0, =_ram_start + ldr r1, =_ram_end + movs r2, #0 + 0: + cmp r1, r0 + beq 1f + stm r0!, {{r2}} + b 0b + 1:", + // Initialise .bss memory. `__sbss` and `__ebss` come from the linker script. #[cfg(not(feature = "zero-init-ram"))] "ldr r0, =__sbss