Skip to content
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

"Invalidate Cache" operation is unsafe #188

Closed
jonas-schievink opened this issue Jan 13, 2020 · 2 comments
Closed

"Invalidate Cache" operation is unsafe #188

jonas-schievink opened this issue Jan 13, 2020 · 2 comments

Comments

@jonas-schievink
Copy link
Contributor

jonas-schievink commented Jan 13, 2020

The optional Cortex-M cache exposes "clean" and "invalidate" operations. As pointed out by @adamgreig in #47 (comment), performing only the "invalidate" operation without a preceding "clean" is unsound.

  • "Clean" flushes cache lines to main memory and makes operations visible to other peripherals and cores
  • "Invalidate" drops cache lines so that they are fetched from main memory on subsequent accesses, making modifications from other bus masters visible to the core doing the invalidation

This operation is currently exposed via safe interfaces:

  • As methods on CBP
  • As methods on SCB

We should either deprecate the methods and add unsafe replacements, or make the methods unsafe in a breaking change without deprecation period (this avoids having to find new names).

In my opinion there is little to no value in exposing only "invalidate" since it hard to use correctly and has little to no benefits over "clean + invalidate", so removing it is also an option.

@adamgreig
Copy link
Member

performing only the "invalidate" operation without a preceding "clean" is unsound

It might also be that a clean is unsound too, I want to think about this a little more.

make the methods unsafe in a breaking change without deprecation period

Given the planned upcoming breaking changes and I think the relatively uncommon use of the cache operations this is my preferred option.

In my opinion there is little to no value in exposing only "invalidate" since it hard to use correctly and has little to no benefits over "clean + invalidate", so removing it is also an option.

These operations are peripheral registers in Cortex-M, with clean+invalidate being distinct from invalidate - sometimes you need one and sometimes you need the other. The methods in SCB mirror those provided in CMSIS. You very often need to invalidate without cleaning if you know another observer has written to the main memory and your cache is outdated, since a clean+invalidate would overwrite whatever the observer had written. Clean+invalidate is pretty much just used for disabling the cache, when you want to ensure all updates are written out and then the item is removed from the cache. I definitely think we should keep all the methods.

@jonas-schievink jonas-schievink added this to the 1.0.0 milestone Jan 15, 2020
@thejpster thejpster mentioned this issue Jan 15, 2020
16 tasks
adamgreig added a commit that referenced this issue Jan 15, 2020
Closes #47, #188.

Breaking change due to changing safety of d-cache invalidation
functions.
bors bot added a commit that referenced this issue Feb 4, 2020
192: Update and improve cache operations. r=jonas-schievink a=adamgreig

Closes #47, #188.

I've implemented the proposed methods from #47 and marked all d-cache invalidation functions as unsafe. It's not unsafe to invalidate i-cache or branch predictor as they are read-only caches. The clean and clean+invalidate operations do not alter memory from the executing core's point of view so are also safe.

It wasn't possible to remove the requirement to pass in `&mut CPUID` as you require synchronized access to `CPUID` to read the number of sets and ways in the cache, which is required to fully clean or invalidate them, which is required to enable or disable them. So it goes.

Breaking change due to changing safety of d-cache invalidation functions.

Co-authored-by: Adam Greig <[email protected]>
bors bot added a commit that referenced this issue Feb 5, 2020
192: Update and improve cache operations. r=jonas-schievink a=adamgreig

Closes #47, #188.

I've implemented the proposed methods from #47 and marked all d-cache invalidation functions as unsafe. It's not unsafe to invalidate i-cache or branch predictor as they are read-only caches. The clean and clean+invalidate operations do not alter memory from the executing core's point of view so are also safe.

It wasn't possible to remove the requirement to pass in `&mut CPUID` as you require synchronized access to `CPUID` to read the number of sets and ways in the cache, which is required to fully clean or invalidate them, which is required to enable or disable them. So it goes.

Breaking change due to changing safety of d-cache invalidation functions.

Co-authored-by: Adam Greig <[email protected]>
@jonas-schievink
Copy link
Contributor Author

Fixed by #192, closing

adamgreig pushed a commit that referenced this issue Jan 12, 2022
…jects

Tested with 1.34.0 and 1.38.0 and careful inspection of the linker map
generated on the previously failing
https://github.com/rust-lang/rust/files/3722440/minimal-rust-lld-issue.zip

Closes #188 (I believe)
Closes rust-lang/rust#65391

Signed-off-by: Daniel Egger <[email protected]>
adamgreig pushed a commit that referenced this issue Jan 12, 2022
207: Rejig link.x to include more lables to help the linker lay out the ob… r=thejpster a=therealprof

…jects

Tested with 1.34.0 and 1.38.0 and careful inspection of the linker map
generated on the previously failing
https://github.com/rust-lang/rust/files/3722440/minimal-rust-lld-issue.zip

Closes #188 (I believe)
Closes rust-lang/rust#65391

Signed-off-by: Daniel Egger <[email protected]>

Co-authored-by: Daniel Egger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants