Skip to content

Tidy up some inline asm and add compiler fences where appropriate #264

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

Merged
merged 4 commits into from
Sep 15, 2020

Conversation

adamgreig
Copy link
Member

This PR updates the inline asm:

  • Use compiler-assigned registers instead of specifying r0/r1/r2
  • Write multi-line asm as multiple string literals, with normal Rust comments outside the strings
  • Add ISB after writing to CONTROL as per ARM architectural requirements (see eg app note 321). As far as I can see no other requirements from AN321 apply here.
  • Add compiler fences around enabling and disabling interrupts
    • No runtime barriers are required, but the compiler fences ensure the compiler won't reorder instructions around these operations, which would break critical section soundness.
  • Add compiler fences around DMB, DSB, ISB to align compiler behaviour with the barrier runtime behaviour.
  • Add compiler fences after the cache enable routines and writing to CONTROL since those routines include an ISB instruction.

Open to feedback on whether more or fewer fences are necessary; I've thought about these a bit but I think it's a tricky subject. I think in general the FFI-esque treatment of the new asm! block probably does most of what we need, but I'm told LLVM may still reorder instructions around FFI calls, which we really don't want to happen here.

@adamgreig adamgreig requested a review from a team as a code owner September 3, 2020 22:14
@rust-highfive
Copy link

r? @therealprof

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

@rust-highfive rust-highfive added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-cortex-m labels Sep 3, 2020
@therealprof
Copy link
Contributor

Nice one. Looks good on first glance but I want to give people some time to look it over.

@therealprof
Copy link
Contributor

Hm, superweird that some archives are shrinking massively in size. These functions are always compiled with optimisation? Otherwise the compiler_fences are going to be really bad...

@adamgreig
Copy link
Member Author

I don't understand the GitHub percentages (I think it's "number of lines" somehow?); the files are all around 14k-25kB; the changes are all less than 1kB. I don't understand why they're changing this much still though, the ones I inspected manually had some different debug strings in the ELF but otherwise no obvious clues.

@adamgreig
Copy link
Member Author

The xtask build generates the staticlib and LTO libs with optimisations enabled. If you're using the inline-asm feature you directly use this code, in which case optimisation depends on your own build.

@therealprof
Copy link
Contributor

The xtask build generates the staticlib and LTO libs with optimisations enabled. If you're using the inline-asm feature you directly use this code, in which case optimisation depends on your own build.

I wonder whether that's the right play here or whether we should place the fences ourselves, rather than using compiler_fence. It doesn't sound great to get additional panicking paths in dev mode by using those primitives.

@adamgreig
Copy link
Member Author

Without the fences the functions are potentially unsound but they are marked unsafe, so we could just document the fence requirement in each relevant method's safety requirements. It's a bit of a chore though and it means users must put those fences in themselves, where they're subject to the exact same issues. At least having them here means that for most users not using inline-asm, they get the optimised build of these methods even when they're in debug mode themselves.

Having said that, it's not clear to me how the fence here makes a difference to a caller of either the staticlib or LTO lib, which presumably only sees the FFI call, which also suggests to me that LLVM really shouldn't dare reorder instructions around an FFI call.

asm!("msr CONTROL, {}", "isb", in(reg) w);

// Ensure instructions are not reordered around the CONTROL update.
compiler_fence(Ordering::SeqCst);
Copy link
Contributor

Choose a reason for hiding this comment

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

This only affects memory instructions. Probably a good idea to clarify that in the comments.

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 done so, but will the asm! block's default memory clobber ensure no memory accesses can be reordered around the block anyway? Will the compiler fence even survive being turned into an FFI call?

I've added these fences on the understanding that the compiler might otherwise reorder instructions around the asm call, but I don't fully see what the fence would prevent that's not prevented by the asm! block and/or FFI call (with or without LTO inlining).

Copy link
Contributor

@therealprof therealprof left a comment

Choose a reason for hiding this comment

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

Oh, and as usual, this is missing a CHANGELOG entry. ;)

@adamgreig
Copy link
Member Author

Oh, and as usual, this is missing a CHANGELOG entry. ;)

There's no CHANGELOG entry for the new asm stuff at all, and it doesn't change the user-facing API (in other words it's an implementation detail). I've added a very brief description to the CHANGELOG about it.

@therealprof
Copy link
Contributor

There's no CHANGELOG entry for the new asm stuff at all,

I agree, but that doesn't make it any better.

and it doesn't change the user-facing API (in other words it's an implementation detail).

Not quite. It can now be linked with via the LTO linker plugin.

therealprof
therealprof previously approved these changes Sep 5, 2020
Copy link
Contributor

@therealprof therealprof left a comment

Choose a reason for hiding this comment

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

LGTM

@adamgreig
Copy link
Member Author

Not quite. It can now be linked with via the LTO linker plugin.

Good point, I've added a specific note about that to the CHANGELOG too.

@therealprof
Copy link
Contributor

Hm, weird. Why is it complaining about the blobs not being up-to-date?

bors try

bors bot added a commit that referenced this pull request Sep 10, 2020
@bors
Copy link
Contributor

bors bot commented Sep 10, 2020

try

Build failed:

@jonas-schievink
Copy link
Contributor

Because 5d5e151 didn't update the blobs

Copy link
Contributor

@therealprof therealprof left a comment

Choose a reason for hiding this comment

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

@jonas-schievink Ah, thanks!

I guess all comments have been sufficiently addressed so I'm inclined to get this on the road then?

Anyone want to give it another nod and pull the trigger?

@adamgreig
Copy link
Member Author

I'm away from my computer for a few days but if anyone else wants to rebuild the blobs and push to the branch please go ahead!

@therealprof
Copy link
Contributor

I'm away from my computer for a few days but if anyone else wants to rebuild the blobs and push to the branch please go ahead!

Already done.

@adamgreig
Copy link
Member Author

bors r=therealprof

@bors
Copy link
Contributor

bors bot commented Sep 15, 2020

Build succeeded:

@bors bors bot merged commit aa77c89 into master Sep 15, 2020
@bors bors bot deleted the inline-fences branch September 15, 2020 21:43
adamgreig pushed a commit that referenced this pull request Jan 12, 2022
264: Document MSRV in README r=korken89 a=eldruin

See: rust-embedded/wg#445

Co-authored-by: Diego Barrios Romero <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

5 participants