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

[qemu-xen stable-4.14] virtio-ccw: fix virtio_set_ind_atomic



commit b8fdfa9d6388823d66b22039b9dfb61fc7a8f401
Author:     Halil Pasic <pasic@xxxxxxxxxxxxx>
AuthorDate: Tue Jun 16 06:50:34 2020 +0200
Commit:     Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
CommitDate: Thu Sep 10 13:09:51 2020 -0500

    virtio-ccw: fix virtio_set_ind_atomic
    
    The atomic_cmpxchg() loop is broken because we occasionally end up with
    old and _old having different values (a legit compiler can generate code
    that accessed *ind_addr again to pick up a value for _old instead of
    using the value of old that was already fetched according to the
    rules of the abstract machine). This means the underlying CS instruction
    may use a different old (_old) than the one we intended to use if
    atomic_cmpxchg() performed the xchg part.
    
    Let us use volatile to force the rules of the abstract machine for
    accesses to *ind_addr. Let us also rewrite the loop so, we that the
    new old is used to compute the new desired value if the xchg part
    is not performed.
    
    Fixes: 7e7494627f ("s390x/virtio-ccw: Adapter interrupt support.")
    Reported-by: Andre Wild <Andre.Wild1@xxxxxxx>
    Signed-off-by: Halil Pasic <pasic@xxxxxxxxxxxxx>
    Reviewed-by: Christian Borntraeger <borntraeger@xxxxxxxxxx>
    Message-Id: <20200616045035.51641-2-pasic@xxxxxxxxxxxxx>
    Signed-off-by: Cornelia Huck <cohuck@xxxxxxxxxx>
    (cherry picked from commit 1a8242f7c3f53341dd66253b142ecd06ce1d2a97)
    Signed-off-by: Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
---
 hw/s390x/virtio-ccw.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 64f928fc7d..9d4e80ccfd 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -786,9 +786,10 @@ static inline VirtioCcwDevice 
*to_virtio_ccw_dev_fast(DeviceState *d)
 static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
                                      uint8_t to_be_set)
 {
-    uint8_t ind_old, ind_new;
+    uint8_t expected, actual;
     hwaddr len = 1;
-    uint8_t *ind_addr;
+    /* avoid  multiple fetches */
+    uint8_t volatile *ind_addr;
 
     ind_addr = cpu_physical_memory_map(ind_loc, &len, true);
     if (!ind_addr) {
@@ -796,14 +797,15 @@ static uint8_t virtio_set_ind_atomic(SubchDev *sch, 
uint64_t ind_loc,
                      __func__, sch->cssid, sch->ssid, sch->schid);
         return -1;
     }
+    actual = *ind_addr;
     do {
-        ind_old = *ind_addr;
-        ind_new = ind_old | to_be_set;
-    } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old);
-    trace_virtio_ccw_set_ind(ind_loc, ind_old, ind_new);
-    cpu_physical_memory_unmap(ind_addr, len, 1, len);
+        expected = actual;
+        actual = atomic_cmpxchg(ind_addr, expected, expected | to_be_set);
+    } while (actual != expected);
+    trace_virtio_ccw_set_ind(ind_loc, actual, actual | to_be_set);
+    cpu_physical_memory_unmap((void *)ind_addr, len, 1, len);
 
-    return ind_old;
+    return actual;
 }
 
 static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
--
generated by git-patchbot for /home/xen/git/qemu-xen.git#stable-4.14



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.