-
Notifications
You must be signed in to change notification settings - Fork 168
Add zero-init-ram feature #455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
e2dc971
to
c44c123
Compare
Do you have any examples of hardware that requires this? It seems very unusual to need to initialise the stack as Rust already doesn't assume it's been zero-initialised; usually I've only seen this in the context of stack painting to measure a high water mark, but that's perhaps better left to debugging tools rather than the init code. |
It is a piece of automotive hardware. The fault is caused by an integrity protection feature that uses checksums for every block of 8 bytes. Writing a single byte causes a read-modify-write of the block that contains that byte. If the block was never written before, the integrity verification during the read step will fail as the checksum for that block was never generated. This will cause the whole read-modify-write to fail. I also tried to initialize the RAM using the pre-init mechanism, but returning from pre-init is not possible once the RAM is wiped. It might be possible if pre-init was naked and inlined but those attributes are not allowed for pre-init. |
To me, it feels like ram_start and ram_end are backwards. I think of most regions as proceeding "up" through memory (lower number is start, higher number is end). The stack is the specific exception because it grows down on Arm. |
Ah, yes. It only worked because I also swapped the arguments in the assembly routine. I corrected the order. |
D'oh, this is covered above. |
I think maybe this could work as a pre-init hook if you wrote it in global asm instead? Like, in your main.rs, global_asm!("
.cfi_sections .debug_frame
.section .__pre_init, \"ax\"
.global __pre_init
.type __pre_init,%function
.thumb_func
.cfi_startproc
__pre_init:
ldr r0, =_ram_start
ldr r1, =_ram_end
movs r2, #0
0:
cmp r1, r0
beq 1f
stm r0!, {{r2}}
b 0b
.cfi_endproc
.size __pre_init, . - __pre_init
"); Still it's a bit unwieldy and requires adding the ram_start/ram_end symbols to your own |
Thanks, I would also prefer a
The |
Hmm, I hadn't tested it but just tried on another project and it does at least build without errors. Could the error be from anything else? |
Found the problem. The hook was missing the global_asm!(
".cfi_sections .debug_frame
.section .__pre_init, \"ax\"
.global __pre_init
.type __pre_init,%function
.thumb_func
.cfi_startproc
__pre_init:
ldr r0, =_ram_start
ldr r1, =_ram_end
movs r2, #0
0:
cmp r1, r0
beq 1f
stm r0!, {{r2}}
b 0b
1:
bx lr
.cfi_endproc
.size __pre_init, . - __pre_init"
); This means that together with the label definitions in Thanks for the help. I think this PR can be closed. |
I can imagine that other ASIL D compliant automotive ECUs have similar RAM protection mechanisms. So maybe this feature is not as niche as it appears to be. |
We discussed this feature in this week's meeting and decided it does make sense to include it in cortex-m-rt. However, before we can merge this the new feature needs to be described in the documentation (in lib.rs, next to set-sp and set-vtor), tested in CI (in ci/script.sh), and mentioned in the CHANGELOG. Would you be able to update those files in this PR? |
I am glad to hear it. I'll update the PR but it may take a few weeks until I have the time to do so. |
I made the requested changes. Please let me know what you think. |
Thanks for the updates, looks good. One concern I have now is that the initialising is done before calling the |
True, both orders of |
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.
da41f39
to
9b51b40
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again for this feature! I've rebased onto master and moved the zero-init-ram routine to just before bss, so that it occurs after pre_init, because many of the use cases for pre_init don't work after writing all of RAM, whereas any RAM that must be accessed during pre_init can conceivably be written to by the user.
Possibly we could add a late_pre_init that runs after memory initialisation (mainly as a pre-main hook for HALs etc) as an optional feature, and maybe even more the normal pre_init to an optional-feature early_pre_init in the next breaking release.
bors r+
455: Add zero-init-ram feature r=adamgreig a=inorick 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. Co-authored-by: Norbert Fabritius <[email protected]> Co-authored-by: Adam Greig <[email protected]>
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.