Port-xen archive

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

xen_rmb, xen_wmb



In sys/arch/xen/include/hypervisor.h rev. 1.48 and
sys/arch/xen/include/xenring.h rev. 1.2, the macros xen_rmb and
xen_wmb were defined as follows:

#define xen_rmb() membar_producer()
#define xen_wmb() membar_consumer()

This definition doesn't make much sense on its face, because
membar_producer orders writes (and may have no effect on reads), while
membar_consumer orders reads (and may have no effect on writes).

On x86, both functions -- membar_producer and membar_consumer -- are
no-ops, though -- because, on normal memory (wb), x86 never reorders
loads with loads or stores with stores (nor in wp, wt, or uc memory),
and a mere compiler instruction barrier suffices.

So by accident, on x86, these functions are interchangeable and the
definitions aren't exactly wrong -- unless Xen uses these for
operations on wc or wc+ memory, which would be odd for guest software
on a CPU coordinating with hypervisor software on a CPU and no real
I/O devices involved.

But it sure is confusing!  And it would be wrong if NetBSD/xen were
ever extended to non-x86 architectures like aarch64.

The usage is also inconsistent.  In xencons.c, the intent in this
logic is obviously that xen_rmb be a load-before-load barrier (and
perhaps better load-before-load/store, membar_acquire), and xen_wmb be
a store-before-store barrier (actually it needs to be
load/store-before-store, or membar_release):

                cons = xencons_interface->out_cons;
                prod = xencons_interface->out_prod;
                xen_rmb();
                while (prod != cons + sizeof(xencons_interface->out)) {
			...
                }
                xen_wmb();
                xencons_interface->out_prod = prod;
                xen_wmb();

But in xengnt.c, the intent in this logic is obviously that xen_rmb be
a store-before-store barrier:

                grant_table.gntt_v2[*entryp].full_page.frame = ma >> PAGE_SHIFT;
                grant_table.gntt_v2[*entryp].hdr.domid = dom;
                /*
                 * ensure that the above values reach global visibility 
                 * before permitting frame's access (done when we set flags)
                 */
                xen_rmb();
                grant_table.gntt_v2[*entryp].hdr.flags =
                    GTF_permit_access | (ro ? GTF_readonly : 0);

I suggest that:

1. xen_rmb be redefined as membar_acquire (load-before-load/store),
2. xen_wmb be redefined as membar_release (load/store-before-store),
and
3. all uses be audited to confirm they have the right semantics;

or, alternatively, that the macros be eliminated and the uses be
replaced by the appropriate membar_*.


sys/arch/xen/include/hypervisor.h rev. 1.48:
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/xen/include/hypervisor.h?rev=1.48&content-type=text/x-cvsweb-markup&only_with_tag=MAIN
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/xen/include/hypervisor.h.diff?r1=1.47&r2=1.48&only_with_tag=MAIN

sys/arch/xen/include/xenring.h rev. 1.2:
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/xen/include/xenring.h?only_with_tag=MAIN
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/xen/include/xenring.h.diff?r1=1.1&r2=1.2&only_with_tag=MAIN


Home | Main Index | Thread Index | Old Index