Skip to content

Conversation

@romancardenas
Copy link
Contributor

Alternative to #325 . This is simpler, as it reduces register preservation to the minimum. New documentation specifies that registers a1 and a2 must not be modified during _mp_hook and __pre_init.

I personally prefer this over #325, but let me know your opinion.

Closes #315

@romancardenas romancardenas requested a review from a team as a code owner July 4, 2025 16:20

- Removed usage of the stack before `_start_rust`. This was unsound, as in the `.init`
section RAM is still uninitialized.
- Now, `a1` and `a2` are **not** preserved during the startup process. New documentation
Copy link
Contributor

@rmsyn rmsyn Jul 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think clobbering a1 at startup is a good idea. For instance, if riscv-rt code is being run as a kernel-like SBI payload, a1 stores the address location of the DeviceTree.

I think this is just a convention, so not a hard requirement. I'm not aware of any conventions requiring preservation of the a2 register.

Edit: after reviewing the startup code, it doesn't look like a1 is clobbered, unless implicitly by a function return. If that's the case, it may be worth storing it in one of the higher numbered a* registers, since we don't have other s* or t* registers available in RV32E contexts.

Copy link
Contributor Author

@romancardenas romancardenas Jul 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In RVI, we can store a0-a2 in s1-s3. We can even use s0-s2 and initialize the frame pointer later, as proposed in the other PR. But im RVE we only have s0-s1, so we need to use a4 and/or a5. Using aX registers for preservation is not part of the ABI, so we must document it to avoid misuse.

Here, while we are not preserving a1-a2, we clearly specify in the documentation for _mp_hook and __preinit that these registers are reserved and must not be used.

Let me know what you prefer and I'll try it.

Note that registers can get dirty only when using _mp_hook and __pre_init, which is not always the case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can even use s0-s2 and initialize the frame pointer later, as proposed in the other PR. But im RVE we only have s0-s1, so we need to use a4 and/or a5. Using aX registers for preservation is not part of the ABI, so we must document it to avoid misuse.

I was wondering about the framepointer init, since that frees up s0 for storing a0, and s1 for a1. Which would still leave a2 to maybe be preserved in higher-number a* registers, which may not be necessary if we just make note of a2 being reserved, like you mention.

In my opinion, as long as we hold the invariants in our default _mp_hook and __preinit impls, i.e. not clobbering reserved registers, we should be fine with documentation for users that want custom implementations.

Let me know what you prefer and I'll try it.

If the framepointer late-init is workable, that sounds like the simplest solution to me. If it ends up being to complicated, maybe we store in stack after doing the RAM init (.bss clearing), and store on the stack like in your other PR?

@romancardenas romancardenas force-pushed the rvrt-asm-alternative branch from 654fcc4 to df61545 Compare July 7, 2025 06:19
@romancardenas
Copy link
Contributor Author

New push with your feedback @rmsyn . This is now very similar to #325 , but register preservation is now only performed when either the pre-init feature is enabled OR the single-hart feature is disabled. Also, new docs are clearer about implementation details for RVE.

@romancardenas
Copy link
Contributor Author

@hegza can you check this PR too? Which one do you prefer?

@romancardenas romancardenas changed the title riscv-rt: Preserve only a0 in startup riscv-rt: Preserve a0-a2 in startup only when startup functions are expected Jul 8, 2025
@romancardenas romancardenas added this pull request to the merge queue Jul 8, 2025
Merged via the queue into master with commit 2d2d7c6 Jul 8, 2025
139 checks passed
@hegza
Copy link
Contributor

hegza commented Jul 9, 2025

Still compiles on RVE. I have no preference whatsoever, both work. One nice thing about this is that the only implementation that gets a bit of unreasonable extra complexity is the mythical multicore RVE. I'm pretty sure that if anyone's going to build one anytime soon it's going to be our lab 😅

@romancardenas romancardenas deleted the rvrt-asm-alternative branch September 9, 2025 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stack is used before __pre_init.

3 participants