All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Hao Peng <flyingpenghao@gmail.com>
Cc: jasowangio@gmail.com, virtualization@lists.linux.dev,
	Peng Hao <flyingpeng@tencent.com>
Subject: Re: [PATCH v2] virtio_pci_modern: skip trailing zero feature dwords
Date: Tue, 29 Sep 2026 05:40:07 -0400	[thread overview]
Message-ID: <20260929053537-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <CAPm50aJzfPLvt4S+Fz7=i_B0Gi6EPET1d+-mt0bdYdq7Tk3wcQ@mail.gmail.com>

On Mon, Sep 28, 2026 at 08:31:15PM +0800, Hao Peng wrote:
> On Fri, Sep 25, 2026 at 12:05 AM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > On Thu, Sep 24, 2026 at 03:14:12PM +0800, Peng Hao wrote:
> > > Since commit 69b9461512246 ("virtio_pci_modern: allow configuring
> > > extended features"), vp_modern_set_extended_features() writes all four
> > > feature dwords on every device, even when the upper ones are zero.
> > >
> > > Feature negotiation follows a device reset, which clears the device-side
> > > driver features, so trailing zero dwords need not be written at all.
> > > finalize_features() can be called again without an intervening reset,
> > > though, when a driver's validate callback narrows the features, so also
> > > write any dword written since the last reset, to clear what the previous
> > > call had enabled.
> > >
> > > Devices negotiating nothing above bit 63 save four MMIO writes; those
> > > using the 64..95 range (e.g. the UDP tunnel GSO features) save two.
> > > Counting dwords rather than 64-bit words is what makes the latter work:
> > > with VIRTIO_F_VERSION_1 at bit 32 the second dword is set on every modern
> > > device, so a qword count never drops below two.
> > >
> > > Signed-off-by: Peng Hao <flyingpeng@tencent.com>
> >
> > So .. why does all this matter? how many exits do you save
> > during a guest boot? is it worth the complexity?
> >
> it depends on the number of modern virtio-pci devices:
>   - A device using only feature bits 0..63 previously required eight
> MMIO writes and now requires four, saving four
>     MMIO writes, normally four VM-exits.
>   - A device using bits 64..95 saves two MMIO writes/exits.
>   - Thus, for example, a guest with five ordinary modern virtio-pci
> devices saves about 20 exits during their
>     initial feature negotiation.

Out of some 10000-100000 that boot takes? Why does this matter?

> 
> > > ---
> > >  drivers/virtio/virtio_pci_modern_dev.c | 32 ++++++++++++++++++++++----
> > >  include/linux/virtio_pci_modern.h      |  3 +++
> > >  2 files changed, 31 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c
> > > index 413a8c353463..7b4da37b6ae5 100644
> > > --- a/drivers/virtio/virtio_pci_modern_dev.c
> > > +++ b/drivers/virtio/virtio_pci_modern_dev.c
> > > @@ -230,6 +230,8 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev)
> > >
> > >       check_offsets();
> > >
> > > +     mdev->driver_features_dwords = 1;
> > > +
> > >       if (mdev->device_id_check) {
> > >               devid = mdev->device_id_check(pci_dev);
> > >               if (devid < 0)
> > > @@ -437,6 +439,11 @@ vp_modern_get_driver_extended_features(struct virtio_pci_modern_device *mdev,
> > >  }
> > >  EXPORT_SYMBOL_GPL(vp_modern_get_driver_extended_features);
> > >
> > > +static u32 vp_modern_features_dword(const u64 *features, int dword)
> > > +{
> > > +     return features[dword / 2] >> (32 * (dword % 2));
> > > +}
> > > +
> > >  /*
> > >   * vp_modern_set_extended_features - set features to device
> > >   * @mdev: the modern virtio-pci device
> > > @@ -446,14 +453,27 @@ void vp_modern_set_extended_features(struct virtio_pci_modern_device *mdev,
> > >                                    const u64 *features)
> > >  {
> > >       struct virtio_pci_common_cfg __iomem *cfg = mdev->common;
> > > -     int i;
> > > +     int dwords = VIRTIO_FEATURES_BITS / 32;
> > > +     int i, write_dwords;
> > >
> > > -     for (i = 0; i < VIRTIO_FEATURES_BITS / 32; i++) {
> > > -             u32 cur = features[i >> 1] >> (32 * (i & 1));
> >
> >
> > below is arguing with previous version of code
> > instead of straight explaining what is this code doing.
> > pls rewrite this comment.
> >
> > > +     /*
> > > +      * A device reset
> >
> > what "a device reset"? who did reset and when?
> >
> > > clears the driver features, so trailing all-zero
> >
> > trailing?
> >
> > > +      * dwords need not be written out.  Include any dword written since
> > > +      * that reset,
> >
> > what "that" reset?
> >
> The reset in question is performed by the virtio core.
> register_virtio_device() calls virtio_reset_device() before
>   driver matching and feature negotiation. For modern virtio-pci,
> vp_reset() writes zero to device_status and waits
>   for the device to report zero. That reset clears all driver feature registers.
> > > though, so that a repeated finalization can clear
> > > +      * features which were enabled by the previous one.
> > > +      */
> >
> > > +     while (dwords > 1 && !vp_modern_features_dword(features, dwords - 1))
> > > +             dwords--;
> >
> dwords is the number of registers needed to represent the new feature
> set. The loop examines
>  register dwords - 1 and reduces the count while the highest register
> is zero. Register 0
>  remains part of the range.
> > what's all this > 1, - 1?
> >
> > > +
> > > +     write_dwords = max_t(int, dwords, mdev->driver_features_dwords);
> >
> > and what is this. i have a vague idea but needs a comment.
> >
> > >
> > > +     for (i = 0; i < write_dwords; i++) {
> > >               vp_iowrite32(i, &cfg->guest_feature_select);
> > > -             vp_iowrite32(cur, &cfg->guest_feature);
> > > +             vp_iowrite32(vp_modern_features_dword(features, i),
> > > +                          &cfg->guest_feature);
> > >       }
> > > +
> > > +     mdev->driver_features_dwords = dwords;
> >
> >
> > contradicts the comment near driver_features_dwords.
> >
> > >  }
> > >  EXPORT_SYMBOL_GPL(vp_modern_set_extended_features);
> > >
> > > @@ -495,6 +515,10 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev,
> > >  {
> > >       struct virtio_pci_common_cfg __iomem *cfg = mdev->common;
> > >
> > > +     /* A reset clears the device's copy of the driver features. */
> > > +     if (!status)
> > > +             mdev->driver_features_dwords = 1;
> >
> > so why 1 not 0?
> >
> Initializing driver_features_dwords to 1 after reset was unnecessarily
> confusing. The reset leaves no
> previously programmed range to clear, so the new version sets it to 0.
> > > +
> > >       /*
> > >        * Per memory-barriers.txt, wmb() is not needed to guarantee
> > >        * that the cache coherent memory writes have completed
> > > diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h
> > > index 9a3f2fc53bd6..b9f4783f0e02 100644
> > > --- a/include/linux/virtio_pci_modern.h
> > > +++ b/include/linux/virtio_pci_modern.h
> > > @@ -27,6 +27,8 @@
> > >   *               Returns the found device id or ERRNO
> > >   * @dma_mask:            Optional mask instead of the traditional DMA_BIT_MASK(64),
> > >   *               for vendor devices with DMA space address limitations
> > > + * @driver_features_dwords: Number of 32-bit driver feature words written
> > > + *               to the device since the last reset
> > >   */
> > >  struct virtio_pci_modern_device {
> > >       struct pci_dev *pci_dev;
> > > @@ -49,6 +51,7 @@ struct virtio_pci_modern_device {
> > >
> > >       int (*device_id_check)(struct pci_dev *pdev);
> > >       u64 dma_mask;
> > > +     u8 driver_features_dwords;
> > >  };
> > >
> > >  /*
> > > --
> > > 2.43.7
> >


      reply	other threads:[~2026-09-29  9:40 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-24  7:14 [PATCH v2] virtio_pci_modern: skip trailing zero feature dwords Peng Hao
2026-09-24  7:19 ` sashiko-bot
2026-09-24 16:05 ` Michael S. Tsirkin
2026-09-28 12:31   ` Hao Peng
2026-09-29  9:40     ` Michael S. Tsirkin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260929053537-mutt-send-email-mst@kernel.org \
    --to=mst@redhat.com \
    --cc=flyingpeng@tencent.com \
    --cc=flyingpenghao@gmail.com \
    --cc=jasowangio@gmail.com \
    --cc=virtualization@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.