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



The following reply was made to PR kern/60144; it has been noted by GNATS.

From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: Jason Thorpe <thorpej%me.com@localhost>
Cc: Tetsuya Isaki <isaki%pastel-flower.jp@localhost>, gnats-bugs%netbsd.org@localhost,
	kern-bug-people%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost
Subject: Re: kern/60144: virtio(4) cache coherence issue
Date: Sat, 11 Apr 2026 02:54:31 +0000

 > 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