Add Artemis stress test for detecting cache aliasing bugs. Include statistical hypothesis evaluations, fix validation data, and run reports for validation across architectures.
Signed-off-by: Robert Allan James <robert.allan.james@gmail.com>
This commit is contained in:
@@ -177,12 +177,20 @@ static int blk_vm_evict(VM *vm) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
/* All slots dirty: evict round-robin, sync back to C buffer first. */
|
||||
/* All slots dirty: evict round-robin, sync back to C buffer first.
|
||||
* Re-resolve the buffer pointer by LBN rather than trusting the
|
||||
* stored one -- the block-subsystem's own devblock cache may have
|
||||
* shifted (struct-copy eviction) since this slot was populated,
|
||||
* which silently invalidates any raw pointer captured earlier. */
|
||||
int s = vm->blk_vm_next;
|
||||
vm->blk_vm_next = (vm->blk_vm_next + 1) % BLK_VM_SLOTS;
|
||||
vaddr_t base = BLK_VM_WINDOW_BASE + (vaddr_t)s * BLOCK_SIZE;
|
||||
memcpy(vm->blk_vm_cbuf[s], vm->memory + base, BLOCK_SIZE);
|
||||
blk_update(vm->blk_vm_lbn[s]);
|
||||
uint8_t* fresh = blk_get_buffer(vm->blk_vm_lbn[s], 1);
|
||||
if (fresh)
|
||||
{
|
||||
memcpy(fresh, vm->memory + base, BLOCK_SIZE);
|
||||
blk_update(vm->blk_vm_lbn[s]);
|
||||
}
|
||||
vm->blk_vm_lbn[s] = 0;
|
||||
vm->blk_vm_cbuf[s] = NULL;
|
||||
vm->blk_vm_dirty[s] = 0;
|
||||
@@ -230,13 +238,19 @@ static vaddr_t blk_vm_assign(VM *vm, uint32_t lbn) {
|
||||
return BLK_VM_WINDOW_BASE + (vaddr_t)s * BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* Sync all dirty slots to their C buffers and flush the subsystem. */
|
||||
/* Sync all dirty slots to their C buffers and flush the subsystem.
|
||||
* Re-resolve each buffer pointer by LBN rather than trusting the stored
|
||||
* one -- see blk_vm_evict for why a stored pointer can go stale. */
|
||||
static void blk_vm_flush_all(VM *vm) {
|
||||
for (int i = 0; i < BLK_VM_SLOTS; i++) {
|
||||
if (vm->blk_vm_cbuf[i] != NULL && vm->blk_vm_dirty[i]) {
|
||||
vaddr_t base = BLK_VM_WINDOW_BASE + (vaddr_t)i * BLOCK_SIZE;
|
||||
memcpy(vm->blk_vm_cbuf[i], vm->memory + base, BLOCK_SIZE);
|
||||
blk_update(vm->blk_vm_lbn[i]);
|
||||
uint8_t* fresh = blk_get_buffer(vm->blk_vm_lbn[i], 1);
|
||||
if (fresh)
|
||||
{
|
||||
memcpy(fresh, vm->memory + base, BLOCK_SIZE);
|
||||
blk_update(vm->blk_vm_lbn[i]);
|
||||
}
|
||||
vm->blk_vm_dirty[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -267,14 +281,23 @@ void block_word_buffer(VM *vm) {
|
||||
vm_push(vm, CELL(vaddr));
|
||||
}
|
||||
|
||||
/* UPDATE ( -- ) : sync current SCR slot to C layer and mark dirty */
|
||||
/* UPDATE ( -- ) : sync current SCR slot to C layer and mark dirty.
|
||||
* Re-resolve the buffer pointer by LBN rather than trusting the stored
|
||||
* one -- see blk_vm_evict for why a stored pointer can go stale. */
|
||||
void block_word_update(VM *vm) {
|
||||
cell_t blk = vm_load_cell(vm, vm->scr_addr);
|
||||
if (blk == 0 || !blk_is_valid((uint32_t) blk)) { vm->error = 1; return; }
|
||||
int s = blk_vm_find(vm, (uint32_t) blk);
|
||||
if (s < 0) { vm->error = 1; return; }
|
||||
vaddr_t base = BLK_VM_WINDOW_BASE + (vaddr_t)s * BLOCK_SIZE;
|
||||
memcpy(vm->blk_vm_cbuf[s], vm->memory + base, BLOCK_SIZE);
|
||||
uint8_t* fresh = blk_get_buffer((uint32_t)blk, 1);
|
||||
if (!fresh)
|
||||
{
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
memcpy(fresh, vm->memory + base, BLOCK_SIZE);
|
||||
vm->blk_vm_cbuf[s] = fresh;
|
||||
vm->blk_vm_dirty[s] = 1;
|
||||
blk_update((uint32_t) blk);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user