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

Update and improve cache operations. #192

Merged
merged 4 commits into from
Feb 5, 2020
Merged

Update and improve cache operations. #192

merged 4 commits into from
Feb 5, 2020

Conversation

adamgreig
Copy link
Member

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.

Closes #47, #188.

Breaking change due to changing safety of d-cache invalidation
functions.
@adamgreig adamgreig added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. breaking change labels Jan 15, 2020
@adamgreig adamgreig requested a review from a team as a code owner January 15, 2020 23:36
@rust-highfive
Copy link

r? @ithinuel

(rust_highfive has picked a reviewer for you, use r? to override)

Copy link
Contributor

@jonas-schievink jonas-schievink left a comment

Choose a reason for hiding this comment

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

Looks pretty good!

/// recent writes to `obj` to be lost, potentially including the write that initialised it.
/// Therefore, this method may cause uninitialised memory or invalid values to be read,
/// resulting in undefined behaviour. You must ensure that main memory contains a valid and
/// initialised value for T before invalidating `obj`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't it unsound in general when the memory a &T points to is modified (unless T is an UnsafeCell)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you think we should require &mut here instead of &, or just give a more dire warning about potential consequences?

Copy link
Contributor

Choose a reason for hiding this comment

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

&mut sounds like a good option, as long as it doesn't make the API unusable. Do you happen to have any real-world examples where this API would be used?

Copy link
Member Author

Choose a reason for hiding this comment

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

I've used the previous invalidate API in ethernet peripheral drivers where the descriptors and packet memory are shared between CPU and peripheral. In all of those instances the code had &mut access, though the receive buffers were in principle read-only.

The other use case I can see is sharing memory between cores on a multi-core device, e.g. the STM32H7 dual-core series have D-cache for the M7 core, so communicating with the M4 core could require cache management. Imagine a synchronisation primitive which needs to invalidate some interior memory to ensure it's reading a fresh value from the other core, and wants to be able to do this with only &self. But probably such a primitive should contain an UnsafeCell which can handle the interior mutability, and then it would still be able to pass &mut to the cache invalidation function.

On balance I think it's probably a more obvious API if it takes &mut to make it clear that the value might change, and in the rare case someone needs to access it with a non-mut, it's only a one line function that calls another public unsafe method anyway, so it's not that much extra effort. I'll update this PR.

@adamgreig
Copy link
Member Author

A couple of other notes:

  • The comments refer to 32-byte alignment and length. Technically in ARMv7-M this length is core-specific and available from the DMinLine field of the CTR register. Currently, only Cortex-M7 cores can have a D-cache, and Cortex-M7 cores can only have 32-byte DMinLine. In the future ARM might release other cores with other cache sizes. I'll update the docstrings to clarify.
  • The above means we probably should not have an assert that the memory being invalidated is 32-byte aligned and a multiple of 32 bytes long. Which is a shame as those asserts would probably be quire useful and make this a less sharp API. Perhaps we could read the DMinLine register and check based on that, I'll investigate.

Please don't merge just yet.

@adamgreig
Copy link
Member Author

I've updated the documentation to more clearly convey what's required and what will happen, updated the methods to take &mut where appropriate, and updated the underlying loops to use DminLine to obtain the cache size at runtime instead of hardcoding 32, although at the moment all released devices will use 32.

This is ready for review now.

Copy link
Contributor

@jonas-schievink jonas-schievink left a comment

Choose a reason for hiding this comment

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

Great work! I have only some documentation nits.

@adamgreig
Copy link
Member Author

Thanks, I've applied suggestions and updated some other initialised 🇬🇧

@jonas-schievink
Copy link
Contributor

Great, let's do this!

bors r+

@bors
Copy link
Contributor

bors bot commented Feb 4, 2020

👎 Rejected by too few approved reviews

Copy link
Contributor

@jonas-schievink jonas-schievink left a comment

Choose a reason for hiding this comment

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

bors r+

bors bot added a commit that referenced this pull request 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
Copy link
Contributor

bors bot commented Feb 5, 2020

Build failed

@jonas-schievink
Copy link
Contributor

Apparently we're downloading stuff from Arm servers during CI. Not sure why but we shouldn't be doing that.

@adamgreig
Copy link
Member Author

adamgreig commented Feb 5, 2020 via email

bors bot added a commit that referenced this pull request 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]>
@adamgreig
Copy link
Member Author

adamgreig commented Feb 5, 2020 via email

@jonas-schievink
Copy link
Contributor

Using apt-get is better for that since Travis caches it. I'll open an issue.

@adamgreig
Copy link
Member Author

adamgreig commented Feb 5, 2020 via email

@bors
Copy link
Contributor

bors bot commented Feb 5, 2020

Build succeeded

@bors bors bot merged commit 9ad4e10 into master Feb 5, 2020
@bors bors bot deleted the cache-safety branch February 5, 2020 00:24
@adamgreig adamgreig mentioned this pull request Jul 5, 2020
adamgreig pushed a commit that referenced this pull request Jan 12, 2022
192: add a .uninit section r=therealprof a=japaric

that contains static variables that will not be initialized by the runtime

this implements only the linker section described in RFC #116 so that downstream
libraries / framework can leverage it without (a) forking this crate or (b)
requiring the end user to pass additional linker scripts to the linker when
building their crate.

This commit doesn't add the user interface described in RFC #116; instead it
documents how to use this linker section in the advanced section of the crate
level documentation

Co-authored-by: Jorge Aparicio <[email protected]>
adamgreig pushed a commit that referenced this pull request Jan 12, 2022
prepare a new patch release that includes PRs #190 and #192
adamgreig pushed a commit that referenced this pull request Jan 12, 2022
194: v0.6.9 r=adamgreig a=japaric

prepare a new patch release that includes PRs #190 and #192

Co-authored-by: Jorge Aparicio <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-cortex-m
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RFC: Even higher-level cache maintenance operations
4 participants