Fix amo offset forgetfulness with write-through caches
Created by: chaseblock
This fixes an issue relating to non-8-byte-aligned SC operations.
I noticed this issue on an older version of cva6 in use by the openesp project, and from reading the code here, I believe it probably applies to the current version as well. However, I have not managed to get any testbench set up with the master branch here, so I'm not 100% certain. The fix appears to be working fine with the openesp setup that I have, and I would be interested to know whether it helps here also.
The problem is demonstrated with the following example code:
inline int load_reserve(volatile int * ptr) {
volatile int rc;
__asm__ volatile (
"lr.w %0, (%1)\n\t"
: "=r" (rc)
: "r" (ptr)
);
return rc;
}
inline int store_conditional(volatile int * ptr, int val) {
volatile int rc;
__asm__ volatile (
"sc.w %0, %1, (%2)\n\t"
: "=r" (rc)
: "r" (val), "r" (ptr)
);
return rc;
}
int main() {
int data[2];
int rc;
rc = store_conditional(&data[0], -1); // Fails (rc = 1), as it should
rc = store_conditional(&data[1], -1); // rc = 0, which is wrong, as it indicates success
// However, if you look at data[1], it was never really updated, so this was really a failure
}
Essentially, it appears that the write-through cache just forgets the offset of the return code between sending the message to the backing cache and getting the response. This means that the SC operation always returns a success code when accessing word-sized data that is not 8-byte aligned. The fix is just one line.