[herd] Event Register Semantics#1777
Conversation
f12dd3d to
0459620
Compare
diaolo01
left a comment
There was a problem hiding this comment.
Thanks for this!
I'm confused by EventReg being modelled as a symbolic location and as a register. Architecturally, it is register, but software cannot access it through direct reads/writes. My current preference would be to model it as register state, while making sure it is not reachable through the ordinary architectural register access paths such as MRS/MSR.
| let rec wfe_loop n = | ||
| if n <= 0 then M.zeroT | ||
| else | ||
| M.altT |
There was a problem hiding this comment.
Since the architectural behaviour is to read the Event Register, then either clear or continue waiting depending on that value, I think this should be restructured so the choice is made from the read's result.
There was a problem hiding this comment.
I did try a choiceT approach, and the problem I had was the edges between WFE events depend on which combinator we use (choiceT vs altT):
altT with seq_mem (current implementation): produces iico_order between successive reads and between the final read and write. This is seems correct since the data from the read doesn't flow to the next read or to the write (which always writes 0).
choiceT: produces iico_data throughout, since the value must flow through the condition check.
Which edges are preferred?
There was a problem hiding this comment.
Thanks, this is helpful. I’m fairly convinced the edges we want here are order edges rather than data edges. I’m still uncomfortable with the current altT encoding though, because it duplicates the EVREG read across the two paths. I can’t yet fully justify that objection in terms of the graph relations, but it does not feel like the right abstraction: architecturally this is a single read followed by a guarded choice rather than two separate guarded reads.
|
I also found in the Arm ARM that: "The Event Register for the PE executing the Exception return instruction is set." This needs to be reflected in the ERET semantics. |
Thanks for the reviews! Registers as they are currenlty implemented don't seem to allow writes from remote threads, and I get the following warning when I try this:
A work-around for this is perhaps to have the local thread (to which the event register being written to belongs) write to its own register after SEV reads a 0 on the remote thread's event register, which doesn't sound faithful to the implementation where SEV acts like a broadcast write. So for now I have implemented this as a global memory location. Unless it is worthwhile to create a type of a register that allows remote writes. It could also be that I am missing something and using registers in a way where SEV can work correctly is already possible. |
78593c6 to
a3ff9b3
Compare
1ab51cf to
00b881f
Compare
This is interesting, this is perhaps an example of a "spurious" update, so the thread is woken up without an SEV, thanks for catching this! For now I am going to implement it as a parallel write alongside the ELR read, unsure if this the right way to do it. |
00b881f to
d9badb9
Compare
The three instructions interact with event registers as follows: SEVL: Send Event Local. Sets the current PE's event register to 1. SEV: Send Event. Sets every PE's event register to 1 (broadcast wake-up). WFE: Wait For Event. If the event register is 1, clear it and fall through. If it is 0, wait until some other PE issues SEV before clearing and continuing. The event register is modelled as a per-thread symbolic memory location
|
Thanks, that makes sense. I understand that the current registers are not able to take cross threaded writes. However, I don't think modelling Event Registers as symbolic locations is the right abstraction. Architecturally, it's a hidden per-PE register, which is neither ordinary memory nor software accessible register. It feels like this needs to be a separate category of state/location that does not currently exist: something register-like and per-PE, but whose location still includes the target PE so that remote writes are possible. |
I don’t think “spurious” is the right term here. The Arm ARM explicitly lists exception return as a cause that sets the Event Register, so this is an architected update. Modelling it alongside ERET makes sense. |
Adds semantics for the event register instructions:
WFE, SEV, SEVLSummary
The three instructions interact with event registers as follows:
SEVL: Send Event Local. Sets the current PE's event register to 1.
SEV: Send Event. Sets every PE's event register to 1 (broadcast wake-up).
WFE: Wait For Event. If the event register is 1, clear it and fall through. If it is 0, wait until some other PE issues SEV before clearing and continuing.
The event register is modelled as a per-thread symbolic memory location. A new
Constant.EventRegofstring symbolickind is introduced, initialised to 0 at test start intest_herd.ml.AnAccess.EVREGaccess kind is added so reads/writes to these locations can be distinguished from ordinary memory.SEVL: a single
write_locof 1 to the current thread's event register.SEV: iterates over
test.start_points,emitting onewrite_loc1 per thread's event register in parallel.WFE: a bounded loop (
wfe_loop 3) non-deterministically branches on the value read.Tests
Not added