Re: [PATCH 1/6] KVM: Fix coalesced_mmio_has_room()

Stamatis, Ilias
2024-07-12T19:03:39Z

On Fri, 2024-07-12 at 17:55 +0200, Roman Kagan wrote:
> On Wed, Jul 10, 2024 at 09:52:54AM +0100, 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
>
> Where exactly do you see a problem? As you correctly point out, all
> values are unsigned, so unsigned arithmetics with wraparound applies,
> and then % operator is applied to the resulting unsigned value. Out
> your three examples, only the last one is relevant, and it's perfectly
> the intended behavior.
>
> Thanks,
> Roman.

KVM_COALESCED_MMIO_MAX on x86 is 170, which means the ring buffer has
170 entries (169 of which should be usable).

If first = 0 and last = 85 then the calculation gives 0 available
entries in which case we consider the buffer to be full and we exit to
userspace. But we shouldn't as there are still 84 unused entries.

So I don't see how this could have been the intended behaviour.

Ilias