]> xenbits.xensource.com Git - xenclient/kernel.git/commitdiff
linux/evtchn: Add memory barriers to evtchn ring accesses.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 22 Jul 2008 10:59:42 +0000 (11:59 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 22 Jul 2008 10:59:42 +0000 (11:59 +0100)
Xenstore infrequently hangs up on IA64.
Actually the xenstored is still alive but no response from
xenstore-XXX commands.

After tracking down, I've found that evtchn_read() infrequently
returns a wrong evtchn port number and evtchn_write() never
unmask the exact port.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
Yes, updates of the ring_prod and ring_cons are separately protected
by different locks/mutexes, but the data communication between
producer and consumer is lock-free. Barriers are needed.

Acked-by: Keir Fraser <keir.fraser@citrix.com>
drivers/xen/evtchn/evtchn.c

index 1c14cf8120e234f36587f75e22eef3326932de88..f814a8f8feaadc6dadfd3486c09f457579911151 100644 (file)
@@ -84,6 +84,7 @@ void evtchn_device_upcall(int port)
        if ((u = port_user[port]) != NULL) {
                if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
                        u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port;
+                       wmb(); /* Ensure ring contents visible */
                        if (u->ring_cons == u->ring_prod++) {
                                wake_up_interruptible(&u->evtchn_wait);
                                kill_fasync(&u->evtchn_async_queue,
@@ -180,6 +181,7 @@ static ssize_t evtchn_read(struct file *file, char __user *buf,
        }
 
        rc = -EFAULT;
+       rmb(); /* Ensure that we see the port before we copy it. */
        if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
            ((bytes2 != 0) &&
             copy_to_user(&buf[bytes1], &u->ring[0], bytes2)))