Message ID | 20240820133333.1724191-2-ilstam@amazon.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: Improve MMIO Coalescing API | expand |
On Tue, Aug 20, 2024, Ilias Stamatis wrote: > The following calculation used in coalesced_mmio_has_room() to check > whether the ring buffer is full is wrong and only allows half the buffer > to be used. > > avail = (ring->first - last - 1) % KVM_COALESCED_MMIO_MAX; > if (avail == 0) > /* full */ > > The % operator in C is not the modulo operator but the remainder > operator. Modulo and remainder operators differ with respect to negative > values. But all values are unsigned in this case anyway. > > The above might have worked as expected in python for example: > >>> (-86) % 170 > 84 > > However it doesn't work the same way in C. > > printf("avail: %d\n", (-86) % 170); > printf("avail: %u\n", (-86) % 170); > printf("avail: %u\n", (-86u) % 170u); > > Using gcc-11 these print: > > avail: -86 > avail: 4294967210 > avail: 0 > > Fix the calculation and allow all but one entries in the buffer to be > used as originally intended. > > Fixes: 105f8d40a737 ("KVM: Calculate available entries in coalesced mmio ring") > Signed-off-by: Ilias Stamatis <ilstam@amazon.com> > Reviewed-by: Paul Durrant <paul@xen.org> > --- Doh, I applied v2 instead of v3. Though unless mine eyes deceive me, they're the same.
diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c index 1b90acb6e3fe..184c5c40c9c1 100644 --- a/virt/kvm/coalesced_mmio.c +++ b/virt/kvm/coalesced_mmio.c @@ -43,7 +43,6 @@ static int coalesced_mmio_in_range(struct kvm_coalesced_mmio_dev *dev, static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev, u32 last) { struct kvm_coalesced_mmio_ring *ring; - unsigned avail; /* Are we able to batch it ? */ @@ -52,8 +51,7 @@ static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev, u32 last) * there is always one unused entry in the buffer */ ring = dev->kvm->coalesced_mmio_ring; - avail = (ring->first - last - 1) % KVM_COALESCED_MMIO_MAX; - if (avail == 0) { + if ((last + 1) % KVM_COALESCED_MMIO_MAX == READ_ONCE(ring->first)) { /* full */ return 0; }