• Jean-Philippe Brucker's avatar
    virtio: Fix ordering of virt_queue__available() · 66ba0bae
    Jean-Philippe Brucker authored
    
    
    After adding buffers to the virtio queue, the guest increments the avail
    index. It then reads the event index to check if it needs to notify the
    host. If the event index corresponds to the previous avail value, then
    the guest notifies the host. Otherwise it means that the host is still
    processing the queue and hasn't had a chance to increment the event
    index yet. Once it gets there, the host will see the new avail index and
    process the descriptors, so there is no need for a notification.
    
    This is only guaranteed to work if both threads write and read the
    indices in the right order. Currently a barrier is missing from
    virt_queue__available(), and the host may not see an up-to-date value of
    event index after writing avail.
    
                 HOST            |           GUEST
                                 |
                                 |    write avail = 1
                                 |    mb()
                                 |    read event -> 0
            write event = 0      |      == prev_avail -> notify
            read avail -> 1      |
                                 |
            write event = 1      |
            read avail -> 1      |
            wait()               |    write avail = 2
                                 |    mb()
                                 |    read event -> 0
                                 |      != prev_avail -> no notification
    
    By adding a memory barrier on the host side, we ensure that it doesn't
    miss any notification.
    Reviewed-By: Steven Price's avatarSteven Price <steven.price@arm.com>
    Signed-off-by: default avatarJean-Philippe Brucker <jean-philippe.brucker@arm.com>
    Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
    66ba0bae
virtio.h 6.35 KB