Hi Alex,
> On July 28, 2023 1:25 AM, Alex Williamson <[email protected]> wrote:
>
> On Thu, 27 Jul 2023 03:24:09 -0400
> Jing Liu <[email protected]> wrote:
>
> > The vector_use callback is used to enable vector that is unmasked in
> > guest. The kernel used to only support static MSI-X allocation. When
> > allocating a new interrupt using "static MSI-X allocation" kernels,
> > Qemu first disables all previously allocated vectors and then
> > re-allocates all including the new one. The nr_vectors of
> > VFIOPCIDevice indicates that all vectors from 0 to nr_vectors are
> > allocated (and may be enabled), which is used to to loop all the
> > possibly used vectors When, e.g., disabling MSI-X interrupts.
> >
> > Extend the vector_use function to support dynamic MSI-X allocation
> > when host supports the capability. Qemu therefore can individually
> > allocate and enable a new interrupt without affecting others or
> > causing interrupts lost during runtime.
> >
> > Utilize nr_vectors to calculate the upper bound of enabled vectors in
> > dynamic MSI-X allocation mode since looping all msix_entries_nr is not
> > efficient and unnecessary.
> >
> > Signed-off-by: Jing Liu <[email protected]>
> > Tested-by: Reinette Chatre <[email protected]>
> > ---
> > hw/vfio/pci.c | 40 +++++++++++++++++++++++++++-------------
> > 1 file changed, 27 insertions(+), 13 deletions(-)
> >
> > diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index
> > 0c4ac0873d40..8c485636445c 100644
> > --- a/hw/vfio/pci.c
> > +++ b/hw/vfio/pci.c
> > @@ -512,12 +512,20 @@ static int vfio_msix_vector_do_use(PCIDevice
> *pdev, unsigned int nr,
> > }
> >
> > /*
> > - * We don't want to have the host allocate all possible MSI vectors
> > - * for a device if they're not in use, so we shutdown and incrementally
> > - * increase them as needed.
> > + * When dynamic allocation is not supported, we don't want to have the
> > + * host allocate all possible MSI vectors for a device if they're not
> > + * in use, so we shutdown and incrementally increase them as needed.
> > + * And nr_vectors stands for the number of vectors being allocated.
>
> "nr_vectors represents the total number of vectors allocated."
Will change.
>
> > + *
> > + * When dynamic allocation is supported, let the host only allocate
> > + * and enable a vector when it is in use in guest. nr_vectors stands
> > + * for the upper bound of vectors being enabled (but not all of the
> > + * ranges is allocated or enabled).
>
> s/stands for/represents/
Will change.
>
> > */
> > - if (vdev->nr_vectors < nr + 1) {
> > + if ((vdev->msix->irq_info_flags & VFIO_IRQ_INFO_NORESIZE) &&
>
> Testing vdev->msix->noresize would be cleaner.
>
> > + (vdev->nr_vectors < nr + 1)) {
> > vdev->nr_vectors = nr + 1;
> > +
> > if (!vdev->defer_kvm_irq_routing) {
> > vfio_disable_irqindex(&vdev->vbasedev,
> > VFIO_PCI_MSIX_IRQ_INDEX);
> > ret = vfio_enable_vectors(vdev, true); @@ -529,16 +537,22
> > @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
> > Error *err = NULL;
> > int32_t fd;
> >
> > - if (vector->virq >= 0) {
> > - fd = event_notifier_get_fd(&vector->kvm_interrupt);
> > - } else {
> > - fd = event_notifier_get_fd(&vector->interrupt);
> > - }
> > + if (!vdev->defer_kvm_irq_routing) {
> > + if (vector->virq >= 0) {
> > + fd = event_notifier_get_fd(&vector->kvm_interrupt);
> > + } else {
> > + fd = event_notifier_get_fd(&vector->interrupt);
> > + }
> >
> > - if (vfio_set_irq_signaling(&vdev->vbasedev,
> > - VFIO_PCI_MSIX_IRQ_INDEX, nr,
> > - VFIO_IRQ_SET_ACTION_TRIGGER, fd,
> > &err)) {
> > - error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
> > + if (vfio_set_irq_signaling(&vdev->vbasedev,
> > + VFIO_PCI_MSIX_IRQ_INDEX, nr,
> > + VFIO_IRQ_SET_ACTION_TRIGGER, fd,
> > &err)) {
> > + error_reportf_err(err, VFIO_MSG_PREFIX,
> > vdev->vbasedev.name);
> > + }
> > + }
> > + /* Increase for dynamic allocation case. */
> > + if (vdev->nr_vectors < nr + 1) {
> > + vdev->nr_vectors = nr + 1;
> > }
>
> We now have two branches where the bulk of the code is skipped when
> defer_kvm_irq_routing is enabled and doing effectively the same update to
> nr_vectors otherwise. This suggests we should move the
> defer_kvm_irq_routing test out and create a common place to update
> nr_vectors. Thanks,
I make a new logic as follows that moves the defer_kvm_irq_routing test out.
Since the vfio_enable_vectors() function need an updated nr_vectors value
so need first update and test the different conditions using old value,
e.g. old_nr_vec.
int old_nr_vec = vdev->nr_vectors;
...
...
if (vdev->nr_vectors < nr + 1) {
vdev->nr_vectors = nr + 1;
}
if (!vdev->defer_kvm_irq_routing) {
if (vdev->msix->noresize && (old_nr_vec < nr + 1)) {
vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
ret = vfio_enable_vectors(vdev, true); // use updated nr_vectors
...
} else {
if (vector->virq >= 0) {
fd = event_notifier_get_fd(&vector->kvm_interrupt);
} else {
fd = event_notifier_get_fd(&vector->interrupt);
}
if (vfio_set_irq_signaling(&vdev->vbasedev,
VFIO_PCI_MSIX_IRQ_INDEX, nr,
VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) {
error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
}
}
}
Thanks,
Jing
>
> Alex