rust-embedded / rust-embedded/cortex-m
Critical sections do nothing in unprivileged code
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 1k
- Forks
- 202
- Avg merge
- 6d 2h
- Merged PRs (30d)
- 2
Description
Currently, the cortex_m::interrupt::free mechanism, for executing a closure without the interference of interrupts, brackets the closure with cpsid and (conditionally, to support nesting) cpsie instructions.
These instructions do nothing in unprivileged mode. (You might expect them to trap; nope.) As a result, cortex_m::interrupt:free becomes a relatively expensive FnOnce::call in unprivileged code.
It's not clear whether cortex_m supports the privileged/unprivileged distinction (there aren't a lot of signs that it does, we're hitting a lot of issues) but this seems like a magnificent footgun.
Options for fixing this off the top of my head:
-
Use a Cargo feature to change the implementation of things that expect privileged code for use in unprivileged contexts. In this case, operations that are inherently privileged -- like all peripherals on the PPB -- would become contingent on the
privilegedfeature and disappear in unprivileged code. Compile time failures are nice. This is my preferred approach, because my unprivileged code is separately compiled and memory isolated, but I bet it won't cover most peoples' use cases -- I suspect that most users ofcortex_mthat are doing any multitasking or priv/unpriv distinction are probably using one big blob of code without isolation, all linked against the same cargo features. (Also, because of how Cargo features are defined, it would be super easy to accidentally pick up theprivilegedfeature from your dependency graph. Laaame.) -
Detect at runtime the current privileged mode and panic if
interrupt::freeis used in unprivileged code. This is a less-good option because it introduces a runtime failure, but it sure is easy. -
Detect at runtime the current privileged mode and call into hooks for entering and leaving a critical section. (There is no standard way of doing this from unpriv code; it depends on the OS. Our OS doesn't actually support global critical sections in unprivileged code for latency reasons, so we'd leave the hooks unimplemented if you went this way. I'm not even sure you could design a useful hook signature since
cortex_m::interrupt::freeis ambient authority that requires no context information.) -
Declare that
cortex_mis not to be used in code that uses unprivileged mode and hope that nobody ever does the wrong thing. (This is actually the conclusion we're heading toward; the APIs really do assume privilege. But it'd be nice to fix this.)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the cortex_m::interrupt::free entry point and verify how it brackets the closure with cpsid and conditionally cpsie in privileged and unprivileged modes. Compare the listed feature, runtime detection, hook, and unsupported-use options, then define a resolved behavior and validation approach before making a change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- embedded-iot
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100