s390/airq: allow for airq structure that uses an input vector
authorMatthew Rosato <mjrosato@linux.ibm.com>
Mon, 6 Jun 2022 20:33:10 +0000 (16:33 -0400)
committerChristian Borntraeger <borntraeger@linux.ibm.com>
Mon, 11 Jul 2022 07:54:15 +0000 (09:54 +0200)
When doing device passthrough where interrupts are being forwarded from
host to guest, we wish to use a pinned section of guest memory as the
vector (the same memory used by the guest as the vector). To accomplish
this, add a new parameter for airq_iv_create which allows passing an
existing vector to be used instead of allocating a new one. The caller
is responsible for ensuring the vector is pinned in memory as well as for
unpinning the memory when the vector is no longer needed.

A subsequent patch will use this new parameter for zPCI interpretation.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Pierre Morel <pmorel@linux.ibm.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/r/20220606203325.110625-7-mjrosato@linux.ibm.com
Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
arch/s390/include/asm/airq.h
arch/s390/pci/pci_irq.c
drivers/s390/cio/airq.c
drivers/s390/virtio/virtio_ccw.c

index 7918a7d..e82e562 100644 (file)
@@ -47,8 +47,10 @@ struct airq_iv {
 #define AIRQ_IV_PTR            4       /* Allocate the ptr array */
 #define AIRQ_IV_DATA           8       /* Allocate the data array */
 #define AIRQ_IV_CACHELINE      16      /* Cacheline alignment for the vector */
+#define AIRQ_IV_GUESTVEC       32      /* Vector is a pinned guest page */
 
-struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags);
+struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags,
+                              unsigned long *vec);
 void airq_iv_release(struct airq_iv *iv);
 unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num);
 void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num);
index b805c75..87c7d12 100644 (file)
@@ -296,7 +296,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                zdev->aisb = bit;
 
                /* Create adapter interrupt vector */
-               zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK);
+               zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK, NULL);
                if (!zdev->aibv)
                        return -ENOMEM;
 
@@ -419,7 +419,7 @@ static int __init zpci_directed_irq_init(void)
        union zpci_sic_iib iib = {{0}};
        unsigned int cpu;
 
-       zpci_sbv = airq_iv_create(num_possible_cpus(), 0);
+       zpci_sbv = airq_iv_create(num_possible_cpus(), 0, NULL);
        if (!zpci_sbv)
                return -ENOMEM;
 
@@ -441,7 +441,7 @@ static int __init zpci_directed_irq_init(void)
                zpci_ibv[cpu] = airq_iv_create(cache_line_size() * BITS_PER_BYTE,
                                               AIRQ_IV_DATA |
                                               AIRQ_IV_CACHELINE |
-                                              (!cpu ? AIRQ_IV_ALLOC : 0));
+                                              (!cpu ? AIRQ_IV_ALLOC : 0), NULL);
                if (!zpci_ibv[cpu])
                        return -ENOMEM;
        }
@@ -458,7 +458,7 @@ static int __init zpci_floating_irq_init(void)
        if (!zpci_ibv)
                return -ENOMEM;
 
-       zpci_sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC);
+       zpci_sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC, NULL);
        if (!zpci_sbv)
                goto out_free;
 
index 230eb5b..34967e6 100644 (file)
@@ -122,10 +122,12 @@ static inline unsigned long iv_size(unsigned long bits)
  * airq_iv_create - create an interrupt vector
  * @bits: number of bits in the interrupt vector
  * @flags: allocation flags
+ * @vec: pointer to pinned guest memory if AIRQ_IV_GUESTVEC
  *
  * Returns a pointer to an interrupt vector structure
  */
-struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags)
+struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags,
+                              unsigned long *vec)
 {
        struct airq_iv *iv;
        unsigned long size;
@@ -146,6 +148,8 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags)
                                             &iv->vector_dma);
                if (!iv->vector)
                        goto out_free;
+       } else if (flags & AIRQ_IV_GUESTVEC) {
+               iv->vector = vec;
        } else {
                iv->vector = cio_dma_zalloc(size);
                if (!iv->vector)
@@ -185,7 +189,7 @@ out_free:
        kfree(iv->avail);
        if (iv->flags & AIRQ_IV_CACHELINE && iv->vector)
                dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma);
-       else
+       else if (!(iv->flags & AIRQ_IV_GUESTVEC))
                cio_dma_free(iv->vector, size);
        kfree(iv);
 out:
@@ -204,7 +208,7 @@ void airq_iv_release(struct airq_iv *iv)
        kfree(iv->bitlock);
        if (iv->flags & AIRQ_IV_CACHELINE)
                dma_pool_free(airq_iv_cache, iv->vector, iv->vector_dma);
-       else
+       else if (!(iv->flags & AIRQ_IV_GUESTVEC))
                cio_dma_free(iv->vector, iv_size(iv->bits));
        kfree(iv->avail);
        kfree(iv);
index 58cca50..51bef22 100644 (file)
@@ -242,7 +242,7 @@ static struct airq_info *new_airq_info(int index)
                return NULL;
        rwlock_init(&info->lock);
        info->aiv = airq_iv_create(VIRTIO_IV_BITS, AIRQ_IV_ALLOC | AIRQ_IV_PTR
-                                  | AIRQ_IV_CACHELINE);
+                                  | AIRQ_IV_CACHELINE, NULL);
        if (!info->aiv) {
                kfree(info);
                return NULL;