NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/60144: virtio(4) cache coherence issue



> Date: Sat, 11 Apr 2026 02:35:39 +0000
> From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
> 
> So that raises the key question:
> 
> 	If we POSTREAD and read _one part_ of the transfer buffer at
> 	one time, and POSTREAD and read _another part_ of it at
> 	another time, do we have to do a PREREAD in the interim at (6)
> 	because between the two reads is essentially a new DMA
> 	operation?
> 
> The question doesn't just apply here -- it also applies to the polling
> scenario (like PR kern/60182: ld@virtio sometimes hangs up):
> 
> 	bus_dmamap_sync(buf, BUS_DMASYNC_PREREAD);
> 	trigger_dma();
> 	for (;;) {
> 		bus_dmamap_sync(buf, BUS_DMASYNC_POSTREAD);
> 		if (buf->ready)
> 			break;
> 	}
> 	use(buf->data);
> 
> Does this need to be rewritten with another PREREAD for every
> iteration?
> 
> 	bus_dmamap_sync(buf, BUS_DMASYNC_PREREAD);
> 	trigger_dma();
> 	for (;;) {
> 		bus_dmamap_sync(buf, BUS_DMASYNC_POSTREAD);
> 		if (buf->ready)
> 			break;
> 		bus_dmamap_sync(buf, BUS_DMASYNC_PREREAD);
> 	}
> 	use(buf->data);

Oops -- I forgot add another POSTREAD between testing buf->ready and
using buf->data, in case the device's stores are reordered as observed
by loads in the driver.  So the options are:

	bus_dmamap_sync(buf, BUS_DMASYNC_PREREAD);
	trigger_dma();
	for (;;) {
		bus_dmamap_sync(buf, BUS_DMASYNC_POSTREAD);
		if (buf->ready)
			break;
	}
	bus_dmamap_sync(buf, BUS_DMASYNC_POSTREAD);
	use(buf->data);

versus

	bus_dmamap_sync(buf, BUS_DMASYNC_PREREAD);
	trigger_dma();
	for (;;) {
		bus_dmamap_sync(buf, BUS_DMASYNC_POSTREAD);
		ready = buf->ready;
		bus_dmamap_sync(buf, BUS_DMASYNC_PREREAD);
		if (ready)
			break;
	}
	bus_dmamap_sync(buf, BUS_DMASYNC_POSTREAD);
	use(buf->data);



Home | Main Index | Thread Index | Old Index