Message ID | 20220801063902.129329-31-xuanzhuo@linux.alibaba.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | virtio pci support VIRTIO_F_RING_RESET | expand |
On Mon, Aug 01, 2022 at 02:38:50PM +0800, Xuan Zhuo wrote: > Introduce new helpers to implement queue reset and get queue reset > status. > > https://github.com/oasis-tcs/virtio-spec/issues/124 > https://github.com/oasis-tcs/virtio-spec/issues/139 > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> > Acked-by: Jason Wang <jasowang@redhat.com> > --- > drivers/virtio/virtio_pci_modern_dev.c | 39 ++++++++++++++++++++++++++ > include/linux/virtio_pci_modern.h | 2 ++ > 2 files changed, 41 insertions(+) > > diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c > index fa2a9445bb18..869cb46bef96 100644 > --- a/drivers/virtio/virtio_pci_modern_dev.c > +++ b/drivers/virtio/virtio_pci_modern_dev.c > @@ -3,6 +3,7 @@ > #include <linux/virtio_pci_modern.h> > #include <linux/module.h> > #include <linux/pci.h> > +#include <linux/delay.h> > > /* > * vp_modern_map_capability - map a part of virtio pci capability > @@ -474,6 +475,44 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev, > } > EXPORT_SYMBOL_GPL(vp_modern_set_status); > > +/* > + * vp_modern_get_queue_reset - get the queue reset status > + * @mdev: the modern virtio-pci device > + * @index: queue index > + */ > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > +{ > + struct virtio_pci_modern_common_cfg __iomem *cfg; > + > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; This should use container_of, and assignment combined with the declaration. > + > + vp_iowrite16(index, &cfg->cfg.queue_select); > + return vp_ioread16(&cfg->queue_reset); > +} > +EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset); > + > +/* > + * vp_modern_set_queue_reset - reset the queue > + * @mdev: the modern virtio-pci device > + * @index: queue index > + */ > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > +{ > + struct virtio_pci_modern_common_cfg __iomem *cfg; > + > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; > + > + vp_iowrite16(index, &cfg->cfg.queue_select); > + vp_iowrite16(1, &cfg->queue_reset); > + > + while (vp_ioread16(&cfg->queue_reset)) > + msleep(1); > + > + while (vp_ioread16(&cfg->cfg.queue_enable)) > + msleep(1); > +} > +EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset); > + > /* > * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue > * @mdev: the modern virtio-pci device > diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h > index 05123b9a606f..c4eeb79b0139 100644 > --- a/include/linux/virtio_pci_modern.h > +++ b/include/linux/virtio_pci_modern.h > @@ -113,4 +113,6 @@ void __iomem * vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev, > u16 index, resource_size_t *pa); > int vp_modern_probe(struct virtio_pci_modern_device *mdev); > void vp_modern_remove(struct virtio_pci_modern_device *mdev); > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > #endif > -- > 2.31.0
On Mon, Aug 01, 2022 at 02:38:50PM +0800, Xuan Zhuo wrote: > Introduce new helpers to implement queue reset and get queue reset > status. > > https://github.com/oasis-tcs/virtio-spec/issues/124 > https://github.com/oasis-tcs/virtio-spec/issues/139 > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> > Acked-by: Jason Wang <jasowang@redhat.com> > --- > drivers/virtio/virtio_pci_modern_dev.c | 39 ++++++++++++++++++++++++++ > include/linux/virtio_pci_modern.h | 2 ++ > 2 files changed, 41 insertions(+) > > diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c > index fa2a9445bb18..869cb46bef96 100644 > --- a/drivers/virtio/virtio_pci_modern_dev.c > +++ b/drivers/virtio/virtio_pci_modern_dev.c > @@ -3,6 +3,7 @@ > #include <linux/virtio_pci_modern.h> > #include <linux/module.h> > #include <linux/pci.h> > +#include <linux/delay.h> > > /* > * vp_modern_map_capability - map a part of virtio pci capability > @@ -474,6 +475,44 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev, > } > EXPORT_SYMBOL_GPL(vp_modern_set_status); > > +/* > + * vp_modern_get_queue_reset - get the queue reset status > + * @mdev: the modern virtio-pci device > + * @index: queue index > + */ > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > +{ > + struct virtio_pci_modern_common_cfg __iomem *cfg; > + > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; > + > + vp_iowrite16(index, &cfg->cfg.queue_select); > + return vp_ioread16(&cfg->queue_reset); > +} > +EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset); > + Actually, this does not validate that the config structure is big enough. So it can access some unrelated memory. Don't know whether that's exploitable e.g. for CoCo but not nice, anyway. Need to validate the size and disable reset if it's too small. > +/* > + * vp_modern_set_queue_reset - reset the queue > + * @mdev: the modern virtio-pci device > + * @index: queue index > + */ > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > +{ > + struct virtio_pci_modern_common_cfg __iomem *cfg; > + > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; > + > + vp_iowrite16(index, &cfg->cfg.queue_select); > + vp_iowrite16(1, &cfg->queue_reset); > + > + while (vp_ioread16(&cfg->queue_reset)) > + msleep(1); > + > + while (vp_ioread16(&cfg->cfg.queue_enable)) > + msleep(1); > +} > +EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset); > + > /* > * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue > * @mdev: the modern virtio-pci device > diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h > index 05123b9a606f..c4eeb79b0139 100644 > --- a/include/linux/virtio_pci_modern.h > +++ b/include/linux/virtio_pci_modern.h > @@ -113,4 +113,6 @@ void __iomem * vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev, > u16 index, resource_size_t *pa); > int vp_modern_probe(struct virtio_pci_modern_device *mdev); > void vp_modern_remove(struct virtio_pci_modern_device *mdev); > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > #endif > -- > 2.31.0
On Thu, 21 Sep 2023 10:02:53 -0400, "Michael S. Tsirkin" <mst@redhat.com> wrote: > On Mon, Aug 01, 2022 at 02:38:50PM +0800, Xuan Zhuo wrote: > > Introduce new helpers to implement queue reset and get queue reset > > status. > > > > https://github.com/oasis-tcs/virtio-spec/issues/124 > > https://github.com/oasis-tcs/virtio-spec/issues/139 > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> > > Acked-by: Jason Wang <jasowang@redhat.com> > > --- > > drivers/virtio/virtio_pci_modern_dev.c | 39 ++++++++++++++++++++++++++ > > include/linux/virtio_pci_modern.h | 2 ++ > > 2 files changed, 41 insertions(+) > > > > diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c > > index fa2a9445bb18..869cb46bef96 100644 > > --- a/drivers/virtio/virtio_pci_modern_dev.c > > +++ b/drivers/virtio/virtio_pci_modern_dev.c > > @@ -3,6 +3,7 @@ > > #include <linux/virtio_pci_modern.h> > > #include <linux/module.h> > > #include <linux/pci.h> > > +#include <linux/delay.h> > > > > /* > > * vp_modern_map_capability - map a part of virtio pci capability > > @@ -474,6 +475,44 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev, > > } > > EXPORT_SYMBOL_GPL(vp_modern_set_status); > > > > +/* > > + * vp_modern_get_queue_reset - get the queue reset status > > + * @mdev: the modern virtio-pci device > > + * @index: queue index > > + */ > > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > > +{ > > + struct virtio_pci_modern_common_cfg __iomem *cfg; > > + > > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; > > + > > + vp_iowrite16(index, &cfg->cfg.queue_select); > > + return vp_ioread16(&cfg->queue_reset); > > +} > > +EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset); > > + > > Actually, this does not validate that the config structure is big > enough. So it can access some unrelated memory. Don't know whether > that's exploitable e.g. for CoCo but not nice, anyway. > Need to validate the size and disable reset if it's too small. static int vp_modern_disable_vq_and_reset(struct virtqueue *vq) { struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); struct virtio_pci_modern_device *mdev = &vp_dev->mdev; struct virtio_pci_vq_info *info; unsigned long flags; -> if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET)) return -ENOENT; vp_modern_set_queue_reset(mdev, vq->index); I checked VIRTIO_F_RING_RESET before call this. Do you mean, we should put the check to this function. Thanks. > > > > +/* > > + * vp_modern_set_queue_reset - reset the queue > > + * @mdev: the modern virtio-pci device > > + * @index: queue index > > + */ > > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > > +{ > > + struct virtio_pci_modern_common_cfg __iomem *cfg; > > + > > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; > > + > > + vp_iowrite16(index, &cfg->cfg.queue_select); > > + vp_iowrite16(1, &cfg->queue_reset); > > + > > + while (vp_ioread16(&cfg->queue_reset)) > > + msleep(1); > > + > > + while (vp_ioread16(&cfg->cfg.queue_enable)) > > + msleep(1); > > +} > > +EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset); > > + > > /* > > * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue > > * @mdev: the modern virtio-pci device > > diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h > > index 05123b9a606f..c4eeb79b0139 100644 > > --- a/include/linux/virtio_pci_modern.h > > +++ b/include/linux/virtio_pci_modern.h > > @@ -113,4 +113,6 @@ void __iomem * vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev, > > u16 index, resource_size_t *pa); > > int vp_modern_probe(struct virtio_pci_modern_device *mdev); > > void vp_modern_remove(struct virtio_pci_modern_device *mdev); > > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > > #endif > > -- > > 2.31.0 >
On Fri, Sep 22, 2023 at 09:49:18AM +0800, Xuan Zhuo wrote: > On Thu, 21 Sep 2023 10:02:53 -0400, "Michael S. Tsirkin" <mst@redhat.com> wrote: > > On Mon, Aug 01, 2022 at 02:38:50PM +0800, Xuan Zhuo wrote: > > > Introduce new helpers to implement queue reset and get queue reset > > > status. > > > > > > https://github.com/oasis-tcs/virtio-spec/issues/124 > > > https://github.com/oasis-tcs/virtio-spec/issues/139 > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> > > > Acked-by: Jason Wang <jasowang@redhat.com> > > > --- > > > drivers/virtio/virtio_pci_modern_dev.c | 39 ++++++++++++++++++++++++++ > > > include/linux/virtio_pci_modern.h | 2 ++ > > > 2 files changed, 41 insertions(+) > > > > > > diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c > > > index fa2a9445bb18..869cb46bef96 100644 > > > --- a/drivers/virtio/virtio_pci_modern_dev.c > > > +++ b/drivers/virtio/virtio_pci_modern_dev.c > > > @@ -3,6 +3,7 @@ > > > #include <linux/virtio_pci_modern.h> > > > #include <linux/module.h> > > > #include <linux/pci.h> > > > +#include <linux/delay.h> > > > > > > /* > > > * vp_modern_map_capability - map a part of virtio pci capability > > > @@ -474,6 +475,44 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev, > > > } > > > EXPORT_SYMBOL_GPL(vp_modern_set_status); > > > > > > +/* > > > + * vp_modern_get_queue_reset - get the queue reset status > > > + * @mdev: the modern virtio-pci device > > > + * @index: queue index > > > + */ > > > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > > > +{ > > > + struct virtio_pci_modern_common_cfg __iomem *cfg; > > > + > > > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; > > > + > > > + vp_iowrite16(index, &cfg->cfg.queue_select); > > > + return vp_ioread16(&cfg->queue_reset); > > > +} > > > +EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset); > > > + > > > > Actually, this does not validate that the config structure is big > > enough. So it can access some unrelated memory. Don't know whether > > that's exploitable e.g. for CoCo but not nice, anyway. > > Need to validate the size and disable reset if it's too small. > > > static int vp_modern_disable_vq_and_reset(struct virtqueue *vq) > { > struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); > struct virtio_pci_modern_device *mdev = &vp_dev->mdev; > struct virtio_pci_vq_info *info; > unsigned long flags; > > -> if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET)) > return -ENOENT; > > vp_modern_set_queue_reset(mdev, vq->index); > > > I checked VIRTIO_F_RING_RESET before call this. Yes but the point is that virtio is used with untrusted devices (e.g. for SEV/TDX), so you can't really assume config structures are in sync with feature bits. > Do you mean, we should put the check to this function. > > > Thanks. > > > > > > > > > > +/* > > > + * vp_modern_set_queue_reset - reset the queue > > > + * @mdev: the modern virtio-pci device > > > + * @index: queue index > > > + */ > > > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > > > +{ > > > + struct virtio_pci_modern_common_cfg __iomem *cfg; > > > + > > > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; > > > + > > > + vp_iowrite16(index, &cfg->cfg.queue_select); > > > + vp_iowrite16(1, &cfg->queue_reset); > > > + > > > + while (vp_ioread16(&cfg->queue_reset)) > > > + msleep(1); > > > + > > > + while (vp_ioread16(&cfg->cfg.queue_enable)) > > > + msleep(1); > > > +} > > > +EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset); > > > + > > > /* > > > * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue > > > * @mdev: the modern virtio-pci device > > > diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h > > > index 05123b9a606f..c4eeb79b0139 100644 > > > --- a/include/linux/virtio_pci_modern.h > > > +++ b/include/linux/virtio_pci_modern.h > > > @@ -113,4 +113,6 @@ void __iomem * vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev, > > > u16 index, resource_size_t *pa); > > > int vp_modern_probe(struct virtio_pci_modern_device *mdev); > > > void vp_modern_remove(struct virtio_pci_modern_device *mdev); > > > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > > > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > > > #endif > > > -- > > > 2.31.0 > >
On Fri, 22 Sep 2023 06:46:39 -0400, "Michael S. Tsirkin" <mst@redhat.com> wrote: > On Fri, Sep 22, 2023 at 09:49:18AM +0800, Xuan Zhuo wrote: > > On Thu, 21 Sep 2023 10:02:53 -0400, "Michael S. Tsirkin" <mst@redhat.com> wrote: > > > On Mon, Aug 01, 2022 at 02:38:50PM +0800, Xuan Zhuo wrote: > > > > Introduce new helpers to implement queue reset and get queue reset > > > > status. > > > > > > > > https://github.com/oasis-tcs/virtio-spec/issues/124 > > > > https://github.com/oasis-tcs/virtio-spec/issues/139 > > > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> > > > > Acked-by: Jason Wang <jasowang@redhat.com> > > > > --- > > > > drivers/virtio/virtio_pci_modern_dev.c | 39 ++++++++++++++++++++++++++ > > > > include/linux/virtio_pci_modern.h | 2 ++ > > > > 2 files changed, 41 insertions(+) > > > > > > > > diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c > > > > index fa2a9445bb18..869cb46bef96 100644 > > > > --- a/drivers/virtio/virtio_pci_modern_dev.c > > > > +++ b/drivers/virtio/virtio_pci_modern_dev.c > > > > @@ -3,6 +3,7 @@ > > > > #include <linux/virtio_pci_modern.h> > > > > #include <linux/module.h> > > > > #include <linux/pci.h> > > > > +#include <linux/delay.h> > > > > > > > > /* > > > > * vp_modern_map_capability - map a part of virtio pci capability > > > > @@ -474,6 +475,44 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev, > > > > } > > > > EXPORT_SYMBOL_GPL(vp_modern_set_status); > > > > > > > > +/* > > > > + * vp_modern_get_queue_reset - get the queue reset status > > > > + * @mdev: the modern virtio-pci device > > > > + * @index: queue index > > > > + */ > > > > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > > > > +{ > > > > + struct virtio_pci_modern_common_cfg __iomem *cfg; > > > > + > > > > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; > > > > + > > > > + vp_iowrite16(index, &cfg->cfg.queue_select); > > > > + return vp_ioread16(&cfg->queue_reset); > > > > +} > > > > +EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset); > > > > + > > > > > > Actually, this does not validate that the config structure is big > > > enough. So it can access some unrelated memory. Don't know whether > > > that's exploitable e.g. for CoCo but not nice, anyway. > > > Need to validate the size and disable reset if it's too small. > > > > > > static int vp_modern_disable_vq_and_reset(struct virtqueue *vq) > > { > > struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); > > struct virtio_pci_modern_device *mdev = &vp_dev->mdev; > > struct virtio_pci_vq_info *info; > > unsigned long flags; > > > > -> if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET)) > > return -ENOENT; > > > > vp_modern_set_queue_reset(mdev, vq->index); > > > > > > I checked VIRTIO_F_RING_RESET before call this. > > Yes but the point is that virtio is used with untrusted devices > (e.g. for SEV/TDX), so you can't really assume config structures > are in sync with feature bits. I see. I will post a patch to check the length of the common cfg. Thanks. > > > > Do you mean, we should put the check to this function. > > > > > > Thanks. > > > > > > > > > > > > > > > > +/* > > > > + * vp_modern_set_queue_reset - reset the queue > > > > + * @mdev: the modern virtio-pci device > > > > + * @index: queue index > > > > + */ > > > > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) > > > > +{ > > > > + struct virtio_pci_modern_common_cfg __iomem *cfg; > > > > + > > > > + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; > > > > + > > > > + vp_iowrite16(index, &cfg->cfg.queue_select); > > > > + vp_iowrite16(1, &cfg->queue_reset); > > > > + > > > > + while (vp_ioread16(&cfg->queue_reset)) > > > > + msleep(1); > > > > + > > > > + while (vp_ioread16(&cfg->cfg.queue_enable)) > > > > + msleep(1); > > > > +} > > > > +EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset); > > > > + > > > > /* > > > > * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue > > > > * @mdev: the modern virtio-pci device > > > > diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h > > > > index 05123b9a606f..c4eeb79b0139 100644 > > > > --- a/include/linux/virtio_pci_modern.h > > > > +++ b/include/linux/virtio_pci_modern.h > > > > @@ -113,4 +113,6 @@ void __iomem * vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev, > > > > u16 index, resource_size_t *pa); > > > > int vp_modern_probe(struct virtio_pci_modern_device *mdev); > > > > void vp_modern_remove(struct virtio_pci_modern_device *mdev); > > > > +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > > > > +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); > > > > #endif > > > > -- > > > > 2.31.0 > > > >
diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c index fa2a9445bb18..869cb46bef96 100644 --- a/drivers/virtio/virtio_pci_modern_dev.c +++ b/drivers/virtio/virtio_pci_modern_dev.c @@ -3,6 +3,7 @@ #include <linux/virtio_pci_modern.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/delay.h> /* * vp_modern_map_capability - map a part of virtio pci capability @@ -474,6 +475,44 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev, } EXPORT_SYMBOL_GPL(vp_modern_set_status); +/* + * vp_modern_get_queue_reset - get the queue reset status + * @mdev: the modern virtio-pci device + * @index: queue index + */ +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) +{ + struct virtio_pci_modern_common_cfg __iomem *cfg; + + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; + + vp_iowrite16(index, &cfg->cfg.queue_select); + return vp_ioread16(&cfg->queue_reset); +} +EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset); + +/* + * vp_modern_set_queue_reset - reset the queue + * @mdev: the modern virtio-pci device + * @index: queue index + */ +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index) +{ + struct virtio_pci_modern_common_cfg __iomem *cfg; + + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; + + vp_iowrite16(index, &cfg->cfg.queue_select); + vp_iowrite16(1, &cfg->queue_reset); + + while (vp_ioread16(&cfg->queue_reset)) + msleep(1); + + while (vp_ioread16(&cfg->cfg.queue_enable)) + msleep(1); +} +EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset); + /* * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue * @mdev: the modern virtio-pci device diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h index 05123b9a606f..c4eeb79b0139 100644 --- a/include/linux/virtio_pci_modern.h +++ b/include/linux/virtio_pci_modern.h @@ -113,4 +113,6 @@ void __iomem * vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev, u16 index, resource_size_t *pa); int vp_modern_probe(struct virtio_pci_modern_device *mdev); void vp_modern_remove(struct virtio_pci_modern_device *mdev); +int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); +void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); #endif