Updated: 2025/Nov/16
Please read Privacy Policy. It's for your privacy.
PARAVIRT_MEMBAR_SYNC(9) Kernel Developer's Manual PARAVIRT_MEMBAR_SYNC(9)
NAME
paravirt_membar_sync - memory barrier for paravirtualized device drivers
SYNOPSIS
#include <sys/paravirt_membar.h>
void
paravirt_membar_sync(void);
DESCRIPTION
The paravirt_membar_sync function issues a store-before-load barrier for
coordination with a paravirtualized device.
This function has the same ordering semantics as membar_sync(3), but
membar_sync(3) can only coordinate with other CPUs that NetBSD is running
on. In a virtual machine, NetBSD may be running on a single virtual CPU,
and patch membar_sync(3) to be a no-op, while the host side of a
paravirtualized device may be running on a different physical CPU
requiring a barrier that membar_sync(3) does not issue.
EXAMPLES
Submit a request to the host device, and notify the host to process
it--but elide the notification, which is expensive, if the host is
already reading requests anyway:
/*
* Write the request into the ring buffer.
*/
memcpy(cputodev_ring->buffer[sc->sc_cputodev_idx], request,
sizeof(*request));
/*
* Publish the request to the host device side.
*/
cputodev_ring->header->producer_tail = ++sc->sc_cputodev_idx;
/*
* Ensure we have published it _before_ we check whether the
* host needs notification.
*/
paravirt_membar_sync();
/*
* Notify the host, if needed. Notifying the host is usually
* expensive (trap to hypervisor), so we try to avoid it if not
* needed.
*/
if (cputodev_ring->header->needs_notification)
notify_host();
Enable interrupts from the host and check whether any were pending while
interrupts were disabled:
/*
* Tell the host device to deliver interrupts after this
* point.
*/
restart:
devtocpu_ring->header->needs_notification = true;
/*
* Ensure we have requested interrupts _before_ we check
* whether we missed any notifications.
*/
paravirt_membar_sync();
/*
* Check whether there were any pending notifications while
* interrupts were blocked. If not, stop here.
*/
idx = devtocpu_ring->header->producer_idx;
if (sc->sc_devtocpu_idx == idx)
return;
/*
* Process the notifications.
*/
devtocpu_ring->header->needs_notification = false;
while (sc->sc_devtocpu_idx != idx) {
struct buffer *buf =
devtocpu_ring->buffer[sc->sc_devtocpu_idx];
process_notification(buf);
sc->sc_devtocpu_idx++;
sc->sc_devtocpu_idx %= ringlen;
}
goto restart;
N.B.: Other ordering or bouncing may be required with bus_dmamap_sync(9);
this is independent of paravirt_membar_sync, which is needed in addition
to bus_dmamap_sync(9) to guarantee store-before-load ordering when there
is no intervening I/O doorbell trigger for a DMA operation, nor interrupt
delivery for a DMA completion.
SEE ALSO
membar_ops(3), bus_dma(9), bus_space(9)
HISTORY
These atomic operations first appeared in NetBSD 12.0.
NetBSD 11.99 August 31, 2025 NetBSD 11.99