<re_irc>
<jannic> Isn't this plain wrong? Iirc atomic load and store are available, just not CAS, and that's exactly what the old target file described.
<re_irc>
<jannic> Or is this not guaranteed for all thumbv6m chips? I didn't check the ARM specs.
crabbedhaloablut has quit [Write error: Connection reset by peer]
crabbedhaloablut has joined #rust-embedded
crabbedhaloablut has quit [Remote host closed the connection]
<re_irc>
<jannic> I don't fully understand the reasoning behind the change in rustc: is it forced by the change in LLVM, or is there a choice to revert it in rustc?
<re_irc>
<adamgreig> My (currently very rough) understanding is that rustc has to change something due to the llvm change, but potentially it could handle this in a different way for thumbv6 targets that doesn't just horribly break a ton of existing code
<re_irc>
<adamgreig> The suggestion to use volatile instead of atomic is kind of annoying because in rust volatile is a property of the access but atomics are their own type... there's no VolatileU32
<re_irc>
<jannic> Is there a nightly which includes the LLVM change and not the rustc one? Does that generate broken code?
<re_irc>
(I only have mobile date ATM and can't download the nightly versions)
<re_irc>
<jannic> * data
<re_irc>
<adamgreig> I guess we'd have noticed by now if a nightly had broken cm0, so probably the latest llvm isn't merged into nightly?
<re_irc>
<jannic> Well it may generate technically broken code which happens to work because in practice none of the cortex-m multi core chips use data caches.
<re_irc>
<adamgreig> They certainly do have and use dcaches
<re_irc>
<adamgreig> Oh, not cortex-m0
<re_irc>
<jannic> m0, that's is.
<re_irc>
<adamgreig> ARMv6-M can't have a dcache architecturally, it's not in the arch reference manual, so it would be outside the scope of atomics anyway
<re_irc>
<adamgreig> But even on cm7 atomic ops don't Interact with the dcache
<re_irc>
<jannic> The ARM talks about visibility and ordering of memory access though, doesn't it? How does that make sense without caches?
<re_irc>
<adamgreig> I think that's mostly to do with the effect of fences and potential cpu reordering of accesses, rather than anything strictly to do with a cache
<re_irc>
<adamgreig> this is maybe wrong and I mean "cortex-m0" not "ARMv6-M"
<re_irc>
<adamgreig> armv6-m does talk about how any potential system caches would interact with the different memory region attributes, though the same rules about exclusives apply as for cm7 in that link above
<re_irc>
<adamgreig> A3.5.2 in the v6-m arch reference manual
<re_irc>
<jannic> To be honest I don't even know which cores map to armv6-m.
<re_irc>
<adamgreig> cm0, cm0+, cm1
<re_irc>
<jannic> I'm at a music festival today so I have very limited resources :-)
<re_irc>
<adamgreig> i don't think the presence of caches has any effect on whether llvm is generating correct atomic code, basically
<re_irc>
<adamgreig> my still very rough understanding is that llvm may want to always handle all atomic ops (regular load/store and CAS) the same way, and the problem is if you allow atomic load/store to directly do a fence and load/store, it no longer plays well with putting the CAS operations through the software shims of __atomic_* because they won't care about any potential software lock those use
<re_irc>
<adamgreig> * "__atomic_*"
<re_irc>
<adamgreig> on rust this isn't obviously an issue because the CAS operations are simply not exposed at all
<re_irc>
<adamgreig> does the atomic-polyfill CAS emulation on armv6 prevent a non-emulated load/store from interfering with an emulated CAS?
<re_irc>
<mabez> Selfishly, I'm quite glad LLVM reverted the arm change, because it means there is hope for getting atomic load/stores for riscvi targets 😅
<re_irc>
<mabez> Obviously I don't want the change to break half the embedded rust ecosystem though...
<re_irc>
<adamgreig> LLVM reverted the arm change?
<re_irc>
<mabez> Reverted allowing emitting atomic codegen for thumbv6 targets
<re_irc>
<adamgreig> as in, now only emits "__atomic_*" lib calls even for load/store?
<re_irc>
<mabez> Yes :)
<re_irc>
<adamgreig> I can certainly see how it fixes a bug in LLVM
<re_irc>
<adamgreig> how does it affect riscv for you?
<re_irc>
<adamgreig> (I'm still not sure I follow, did they revert the change that causes it to only emit __atomic, or are you saying you're glad they've fixed this very longstanding bug and now only emit __atomic?)
<re_irc>
<mabez> Well indirectly it affects riscv. LLVM refused patches to allow atomic codegen for riscv non atomic targets and then upstream rust wouldn't allow PR's adding manual lowering for riscv targets.
<re_irc>
I'm glad the arm codegen has been removed in LLVM 15 because it forces upstream rust to handle this properly instead if relying on an LLVM bug
<re_irc>
<mabez> And in fixing it properly should allow other targets, like riscv to get atomic load/stores
<re_irc>
<mabez> But obviously the way to do this is to discuss it instead of just breaking half the embedded Rust ecosystem, which fortunately Amanieu is on top of
<re_irc>
<adamgreig> ah yea, got it, I agree
<re_irc>
<adamgreig> everything that touches llvm's memory model like this seems to end up kind of cursed, perhaps because it's hard to definitively say how something is even meant to behave
<re_irc>
<adamgreig> but at least if rust does provide its own lowering of Atomic* load/store for thumbv6 there seems to be no reason it couldn't also do this for rv non-A, and both cases would be clearly documented why this is OK and why it's different from LLVM
<re_irc>
<mabez> adamgreig: Exactly, that's what I'm hoping for at least!
causal has joined #rust-embedded
crabbedhaloablut has quit [Remote host closed the connection]
crabbedhaloablut has joined #rust-embedded
Amadiro has joined #rust-embedded
Amadiro_ has joined #rust-embedded
Amadiro has quit [Ping timeout: 255 seconds]
<cr1901>
https://github.com/rust-lang/rust/issues/99668 Amanieu: I believe this also applies to msp430, but I'm gonna be honest... the whole "msp430 and LLVM atomics" thing is a mess 1/2
<cr1901>
While I can explain what atomic operations msp430 offers in terms of "msp430 has bitset/clear insns that will not be interrupted before completing", and "msp430 is a single core arch", I don't know how to map that back to what LLVM and Rust expects
<cr1901>
Historically, I've used a separate crate for implementing e.g. AtomicBool that uses inline assembly
crabbedhaloablut has quit [Remote host closed the connection]
crabbedhaloablut has joined #rust-embedded
<re_irc>
<thalesfragoso> jannic: CM7 has something called store queue, that is essentially a cache, but it isn't something else than the normal optional dcache
<re_irc>
<thalesfragoso> * is
<re_irc>
<thalesfragoso> Basically, stores in normal memory can be re-ordered in the store queue, that's where DMB (fences) from atomics come into play
<re_irc>
<thalesfragoso> cr1901: The problem is that LLVM considers "software atomics" as "first class", so your normal hardware implementation would break them
<re_irc>
<thalesfragoso> Even if you use inline asm
<re_irc>
<thalesfragoso> I.e. they expose "software CAS" which would break with any other atomic implementation, even just normal load/store
<re_irc>
<thalesfragoso> But rust doesn't expose software atomics, so there's hope, but that needs to be done in rustc itself
<re_irc>
<thalesfragoso> That is usually only needed when dealing with multi master situations, e.g. multi core or DMA
<re_irc>
<thalesfragoso> And that's the cause of a year-long bug in ST's official Ethernet driver
<re_irc>
<thalesfragoso> * years-long
<cr1901>
thalesfragoso: >The problem is that LLVM considers "software atomics" as "first class", so your normal hardware implementation would break them <-- I'm afraid I don't understand this line at all.
<cr1901>
What is the problem? What normal hardware implementation? Break what?
<cr1901>
>they expose "software CAS"... what is "they" referring to? My crate or "the code LLVM generates"?
<re_irc>
<thalesfragoso> cr1901: libatomic exposes software implementations for atomics, they are used for CAS operations where the target doesn't support CAS, e.g. tumbv6. If you link code that uses normal store/load for atomics then you break libatomic
<re_irc>
<thalesfragoso> Rust doesn't link to libatomic and doesn't plan to, but LLVM wants to support such software implementations, that's why they did what they did
<cr1901>
What does libatomic disable interrupts for thumbv6?
<re_irc>
<thalesfragoso> Tbh, I have no idea what libatomic does exactly on specific targets
<re_irc>
<thalesfragoso> But it's known that you can't mix its atomics with others
<cr1901>
msp430 atomic lowering isn't implemented in LLVM. If LLVM sees those insns, the backend bails
<cr1901>
So I use a separate Rust crate as a workaround. This seems to work fine, especially since the LLVM backend itself bails before it would ever try to use libatomic
crabbedhaloablut has quit [Remote host closed the connection]
crabbedhaloablut has joined #rust-embedded
<re_irc>
<thejpster> thalesfragoso: I guess the usual answer is that it asks the OS for help.
<re_irc>
<thejpster> I remember my early embedded projects where I just used gcc targeting arm-none-linux-gnueabi. It was not great 😂
<re_irc>
<dirbaio> which uses ... spinlocks implemented with atomics. How's that not a chicken-and-egg? 😂
<cr1901>
The smallest atomic primitives must be impl'd in terms of "something that either fails or succeeds without there being a visible halfway point". These could be smaller atomics, OS support, or disabling/enabling interrupts.
<cr1901>
s/smallest//
<cr1901>
The latter two only work on single core, which AFAIK makes multicore w/o some sort of small atomic primitive not very useful in practice.
<re_irc>
<dirbaio> yeah but.. this _is_ the thing that implements atomics for archs without hardware CAS, based on global spinlocks
<re_irc>
<dirbaio> but these spinlocks use CAS 😂
<cr1901>
Where's the CAS?
<cr1901>
(in the spinlocks?)
<cr1901>
(Anyways if it's what you say- CAS in terms in CAS- I have no idea how that can work either :P...)
<cr1901>
which sounds special enough that I don't care after that point :P
<re_irc>
<dirbaio> yeah, rustc lowers that to llvm ir atomic ops, then llvm lowers it to either the right asm instructions or libcalls depending on the target