Merge audit-2026-05-fix/p1-gpubug-006-mmio-ordering

This commit is contained in:
MechaCat02
2026-05-03 14:26:09 +02:00

View File

@@ -522,15 +522,27 @@ impl GpuSystem {
/// per-round GPU hook: the guest may have advanced `CP_RB_WPTR` since
/// we last ran, and we in turn reflect our read-pointer back to the
/// mirror register so the guest sees progress.
///
/// GPUBUG-006: under `--parallel`, the producer (the guest CP_RB_WPTR
/// MMIO write) uses `Release` to publish prior ring-memory writes;
/// the consumer here must `Acquire`-load to pair correctly. With
/// Relaxed-on-load, ring-memory writes that the guest performed
/// before bumping WPTR could be reordered past our subsequent reads
/// — leading to garbage PM4 packet contents. The producer side at
/// `mmio_region.rs:78` already uses Release; the consumer's Relaxed
/// was the missing half. Symmetrically, the RPTR mirror store
/// publishes our read progress to the guest and benefits from a
/// Release.
pub fn sync_with_mmio(&mut self) {
let wptr_dwords = self.mmio.cp_rb_wptr.load(Ordering::Relaxed);
let wptr_dwords = self.mmio.cp_rb_wptr.load(Ordering::Acquire);
if wptr_dwords != self.ring.write_offset_dwords && self.ring.size_dwords != 0 {
self.ring.write_offset_dwords = wptr_dwords % self.ring.size_dwords;
}
// Mirror our read pointer.
// Mirror our read pointer (Release pairs with any guest-side
// Acquire-load of CP_RB_RPTR for ring writeback bookkeeping).
self.mmio
.cp_rb_rptr
.store(self.ring.read_offset_dwords, Ordering::Relaxed);
.store(self.ring.read_offset_dwords, Ordering::Release);
}
/// True iff `execute_one` is expected to make progress without blocking.