Re: [RFC 1/8] virtio/virtio-pci: Handle extra notification data

Jonah Palmer <[email protected]>
Newsgroups dev.linux.lists.virtio-fs,org.nongnu.qemu-devel
Message-ID <[email protected]>

On 3/1/24 2:55 PM, Eugenio Perez Martin wrote:
> On Fri, Mar 1, 2024 at 2:44 PM Jonah Palmer <[email protected]> wrote:
>>
>> Add support to virtio-pci devices for handling the extra data sent
>> from the driver to the device when the VIRTIO_F_NOTIFICATION_DATA
>> transport feature has been negotiated.
>>
>> The extra data that's passed to the virtio-pci device when this
>> feature is enabled varies depending on the device's virtqueue
>> layout.
>>
>> In a split virtqueue layout, this data includes:
>>   - upper 16 bits: last_avail_idx
>>   - lower 16 bits: virtqueue index
>>
>> In a packed virtqueue layout, this data includes:
>>   - upper 16 bits: 1-bit wrap counter & 15-bit last_avail_idx
>>   - lower 16 bits: virtqueue index
>>
>> Signed-off-by: Jonah Palmer <[email protected]>
>> ---
>>   hw/virtio/virtio-pci.c     | 13 ++++++++++---
>>   hw/virtio/virtio.c         | 13 +++++++++++++
>>   include/hw/virtio/virtio.h |  1 +
>>   3 files changed, 24 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
>> index 1a7039fb0c..c7c577b177 100644
>> --- a/hw/virtio/virtio-pci.c
>> +++ b/hw/virtio/virtio-pci.c
>> @@ -384,7 +384,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
>>   {
>>       VirtIOPCIProxy *proxy = opaque;
>>       VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
>> -    uint16_t vector;
>> +    uint16_t vector, vq_idx;
>>       hwaddr pa;
>>
>>       switch (addr) {
>> @@ -408,8 +408,15 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
>>               vdev->queue_sel = val;
>>           break;
>>       case VIRTIO_PCI_QUEUE_NOTIFY:
>> -        if (val < VIRTIO_QUEUE_MAX) {
>> -            virtio_queue_notify(vdev, val);
>> +        if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) {
>> +            vq_idx = val & 0xFFFF;
>> +            virtio_set_notification_data(vdev, vq_idx, val);
>> +        } else {
>> +            vq_idx = val;
>> +        }
>> +
>> +        if (vq_idx < VIRTIO_QUEUE_MAX) {
>> +            virtio_queue_notify(vdev, vq_idx);
>>           }
>>           break;
>>       case VIRTIO_PCI_STATUS:
>> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
>> index d229755eae..a61f69b7fd 100644
>> --- a/hw/virtio/virtio.c
>> +++ b/hw/virtio/virtio.c
>> @@ -2052,6 +2052,19 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val)
>>       return 0;
>>   }
>>
>> +void virtio_set_notification_data(VirtIODevice *vdev, uint16_t i, uint32_t data)
>> +{
>> +    VirtQueue *vq = &vdev->vq[i];
> 
> Sorry I sent the previous mail too fast :).
> 
> i should also be checked against VIRTIO_QUEUE_MAX and vq->vring.desc
> before continuing this function. Otherwise is an out of bound access.

Missed this, thank you. I will add these checks in!

> 
>> +
>> +    if (virtio_vdev_has_feature(vdev, VIRTIO_F_RING_PACKED)) {
>> +        vq->last_avail_wrap_counter = (data >> 31) & 0x1;
>> +        vq->last_avail_idx = (data >> 16) & 0x7FFF;
>> +    } else {
>> +        vq->last_avail_idx = (data >> 16) & 0xFFFF;
>> +    }
>> +    vq->shadow_avail_idx = vq->last_avail_idx;
>> +}
>> +
>>   static enum virtio_device_endian virtio_default_endian(void)
>>   {
>>       if (target_words_bigendian()) {
>> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
>> index c8f72850bc..c92d8afc42 100644
>> --- a/include/hw/virtio/virtio.h
>> +++ b/include/hw/virtio/virtio.h
>> @@ -345,6 +345,7 @@ void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index);
>>   void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index);
>>   void virtio_update_irq(VirtIODevice *vdev);
>>   int virtio_set_features(VirtIODevice *vdev, uint64_t val);
>> +void virtio_set_notification_data(VirtIODevice *vdev, uint16_t i, uint32_t data);
>>
>>   /* Base devices.  */
>>   typedef struct VirtIOBlkConf VirtIOBlkConf;
>> --
>> 2.39.3
>>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.