mini-rv32ima
mini-rv32ima copied to clipboard
Atomic instruction emulation
From riscv privileged spec:
3.1.8 Machine Trap Delegation Registers (medeleg and mideleg)
By default, all traps at any privilege level are handled in machine mode, though a machine-mode handler can redirect traps back to the appropriate level with the MRET instruction (Section 3.3.2).
Generally, linux runs in supervisor mode, and can't guarantee that machine mode interrupt doesn't happens in the middle of emulating atomic instruction
Proper implentation of atomic instructions would look something like this.
- Emulator encounters unknown instruction and emit Illegal instruction trap
- sbi implementation parses instruction and does emulation
bool saved_mie = get_mie_from_mstatus();
set_mie_in_mstatus(0);
// atomic instruction emulation
set_mie_in_mstatus(saved_mie);
Or you can embed same code directly into linux for better perf if:
- linux runs in machine mode
- system has one hart (core)
Is this to be done on an individual instruction basis? I have to admit I don't fully understand the timing on when things are allowed to happen between loads and stores.
Can this be done by just having a global flag of "I have a reservation!" and clearing it if there's an interrupt, and reporting failure to sc
?
Can this be done by just having a global flag of "I have a reservation!" and clearing it if there's an interrupt, and reporting failure to
sc
?
Yes, and them implement amo*_[w|d] instructions in terms of lr/sc
loops.
From spec:
We provided fetch-and-op style atomic primitives as they scale to highly parallel systems better
than LR/SC or CAS. A simple microarchitecture can implement AMOs using the LR/SC primi-
tives, provided the implementation can guarantee the AMO eventually completes.
I don't need to do that. Because it's just one core (or we can control atomicity with an actual semaphore).
Second question: No other memory accesses need to obey this, correct? So if I do have a global memory semaphore, it only needs to be used on RV32A?
Just pasting this here:
i=1
while [ $i -le 10000 ]
do
echo "Running 'ls' in the background, iteration $i"
ls >/dev/null 2>&1 &
i=$((i + 1))
done