On 2026-06-01 11:59 PM, Michael S. Tsirkin wrote:
> On Tue, Jun 02, 2026 at 08:04:13AM +0200, Eugenio Perez Martin wrote:
>> On Tue, Jun 2, 2026 at 6:34 AM yangjiale <[email protected]> wrote:
>>>
>>> When a descriptor list spans across cache lines,
>>> updating the flag first can lead to a scenario where the device side
>>> perceives the flag as valid, yet the corresponding address and length
>>> fields remain unupdated—resulting in invalid values.
>>> Therefore, the flag field must be updated last.
>>>
>>> Signed-off-by: yangjiale <[email protected]>
>>> ---
>>>  drivers/virtio/virtio_ring.c | 8 ++++----
>>>  1 file changed, 4 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
>>> index fbca7ce1c6bf..036b4f90d30f 100644
>>> --- a/drivers/virtio/virtio_ring.c
>>> +++ b/drivers/virtio/virtio_ring.c
>>> @@ -1688,6 +1688,10 @@ static inline int virtqueue_add_packed(struct 
>>> vring_virtqueue *vq,
>>>                                              &addr, &len, premapped, attr))
>>>                                 goto unmap_release;
>>>
>>> +                       desc[i].addr = cpu_to_le64(addr);
>>> +                       desc[i].len = cpu_to_le32(len);
>>> +                       desc[i].id = cpu_to_le16(id);
>>> +
>>>                         flags = cpu_to_le16(vq->packed.avail_used_flags |
>>>                                     (++c == total_sg ? 0 : 
>>> VRING_DESC_F_NEXT) |
>>>                                     (n < out_sgs ? 0 : VRING_DESC_F_WRITE));
>>> @@ -1696,10 +1700,6 @@ static inline int virtqueue_add_packed(struct 
>>> vring_virtqueue *vq,
>>>                         else
>>>                                 desc[i].flags = flags;
>>>
>>> -                       desc[i].addr = cpu_to_le64(addr);
>>> -                       desc[i].len = cpu_to_le32(len);
>>> -                       desc[i].id = cpu_to_le16(id);
>>> -
>>>                         if (unlikely(vq->use_map_api)) {
>>>                                 vq->packed.desc_extra[curr].addr = 
>>> premapped ?
>>>                                         DMA_MAPPING_ERROR : addr;
>>
>> These flags are updated before the flags of the head descriptor at the
>> end of the function, at "vq->packed.vring.desc[head].flags =
>> head_flags", so the device should not see these. Because of that, the
>> relative order between the rest of the fields of the same descriptor
>> or other descriptors' fields, except for the head descriptor's flags,
>> should not matter. There is a write memory barrier just before
>> updating the head's flags.
>>
>> Also, I don't get why the cache line matters here. Can you expand? Am
>> I missing something?
> 
> Oh desc is just a local thing. ENOCOFFEE )
> 
> 

Whether or not this can happen in practice, I notice
virtqueue_add_packed_in_order() has the same write pattern.

Dongli Zhang

Reply via email to