62547e
From 362fae654bbae03741003e565fb95d73d8c0025f Mon Sep 17 00:00:00 2001
62547e
From: Matthew Rosato <mjrosato@linux.ibm.com>
62547e
Date: Fri, 2 Sep 2022 13:27:34 -0400
62547e
Subject: [PATCH 09/42] s390x/pci: enable adapter event notification for
62547e
 interpreted devices
62547e
MIME-Version: 1.0
62547e
Content-Type: text/plain; charset=UTF-8
62547e
Content-Transfer-Encoding: 8bit
62547e
62547e
RH-Author: Cédric Le Goater <clg@redhat.com>
62547e
RH-MergeRequest: 226: s390: Enhanced Interpretation for PCI Functions and Secure Execution guest dump
62547e
RH-Bugzilla: 1664378 2043909
62547e
RH-Acked-by: Thomas Huth <thuth@redhat.com>
62547e
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
62547e
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
62547e
RH-Commit: [9/41] 771975c436c7cb608e0e9e40edd732ac310beb69
62547e
62547e
Use the associated kvm ioctl operation to enable adapter event notification
62547e
and forwarding for devices when requested.  This feature will be set up
62547e
with or without firmware assist based upon the 'forwarding_assist' setting.
62547e
62547e
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
62547e
Message-Id: <20220902172737.170349-6-mjrosato@linux.ibm.com>
62547e
[thuth: Rename "forwarding_assist" property to "forwarding-assist"]
62547e
Signed-off-by: Thomas Huth <thuth@redhat.com>
62547e
(cherry picked from commit d0bc7091c2013ad2fa164100cf7b17962370e8ab)
62547e
Signed-off-by: Cédric Le Goater <clg@redhat.com>
62547e
---
62547e
 hw/s390x/s390-pci-bus.c         | 20 ++++++++++++++---
62547e
 hw/s390x/s390-pci-inst.c        | 40 +++++++++++++++++++++++++++++++--
62547e
 hw/s390x/s390-pci-kvm.c         | 30 +++++++++++++++++++++++++
62547e
 include/hw/s390x/s390-pci-bus.h |  1 +
62547e
 include/hw/s390x/s390-pci-kvm.h | 14 ++++++++++++
62547e
 5 files changed, 100 insertions(+), 5 deletions(-)
62547e
62547e
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
62547e
index 07c7c155e3..cd152ce711 100644
62547e
--- a/hw/s390x/s390-pci-bus.c
62547e
+++ b/hw/s390x/s390-pci-bus.c
62547e
@@ -190,7 +190,10 @@ void s390_pci_sclp_deconfigure(SCCB *sccb)
62547e
         rc = SCLP_RC_NO_ACTION_REQUIRED;
62547e
         break;
62547e
     default:
62547e
-        if (pbdev->summary_ind) {
62547e
+        if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE)) {
62547e
+            /* Interpreted devices were using interrupt forwarding */
62547e
+            s390_pci_kvm_aif_disable(pbdev);
62547e
+        } else if (pbdev->summary_ind) {
62547e
             pci_dereg_irqs(pbdev);
62547e
         }
62547e
         if (pbdev->iommu->enabled) {
62547e
@@ -1082,6 +1085,7 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
62547e
                 } else {
62547e
                     DPRINTF("zPCI interpretation facilities missing.\n");
62547e
                     pbdev->interp = false;
62547e
+                    pbdev->forwarding_assist = false;
62547e
                 }
62547e
             }
62547e
             pbdev->iommu->dma_limit = s390_pci_start_dma_count(s, pbdev);
62547e
@@ -1090,11 +1094,13 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
62547e
             if (!pbdev->interp) {
62547e
                 /* Do vfio passthrough but intercept for I/O */
62547e
                 pbdev->fh |= FH_SHM_VFIO;
62547e
+                pbdev->forwarding_assist = false;
62547e
             }
62547e
         } else {
62547e
             pbdev->fh |= FH_SHM_EMUL;
62547e
             /* Always intercept emulated devices */
62547e
             pbdev->interp = false;
62547e
+            pbdev->forwarding_assist = false;
62547e
         }
62547e
 
62547e
         if (s390_pci_msix_init(pbdev) && !pbdev->interp) {
62547e
@@ -1244,7 +1250,10 @@ static void s390_pcihost_reset(DeviceState *dev)
62547e
     /* Process all pending unplug requests */
62547e
     QTAILQ_FOREACH_SAFE(pbdev, &s->zpci_devs, link, next) {
62547e
         if (pbdev->unplug_requested) {
62547e
-            if (pbdev->summary_ind) {
62547e
+            if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE)) {
62547e
+                /* Interpreted devices were using interrupt forwarding */
62547e
+                s390_pci_kvm_aif_disable(pbdev);
62547e
+            } else if (pbdev->summary_ind) {
62547e
                 pci_dereg_irqs(pbdev);
62547e
             }
62547e
             if (pbdev->iommu->enabled) {
62547e
@@ -1382,7 +1391,10 @@ static void s390_pci_device_reset(DeviceState *dev)
62547e
         break;
62547e
     }
62547e
 
62547e
-    if (pbdev->summary_ind) {
62547e
+    if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE)) {
62547e
+        /* Interpreted devices were using interrupt forwarding */
62547e
+        s390_pci_kvm_aif_disable(pbdev);
62547e
+    } else if (pbdev->summary_ind) {
62547e
         pci_dereg_irqs(pbdev);
62547e
     }
62547e
     if (pbdev->iommu->enabled) {
62547e
@@ -1428,6 +1440,8 @@ static Property s390_pci_device_properties[] = {
62547e
     DEFINE_PROP_S390_PCI_FID("fid", S390PCIBusDevice, fid),
62547e
     DEFINE_PROP_STRING("target", S390PCIBusDevice, target),
62547e
     DEFINE_PROP_BOOL("interpret", S390PCIBusDevice, interp, true),
62547e
+    DEFINE_PROP_BOOL("forwarding-assist", S390PCIBusDevice, forwarding_assist,
62547e
+                     true),
62547e
     DEFINE_PROP_END_OF_LIST(),
62547e
 };
62547e
 
62547e
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
62547e
index 651ec38635..20a9bcc7af 100644
62547e
--- a/hw/s390x/s390-pci-inst.c
62547e
+++ b/hw/s390x/s390-pci-inst.c
62547e
@@ -1066,6 +1066,32 @@ static void fmb_update(void *opaque)
62547e
     timer_mod(pbdev->fmb_timer, t + pbdev->pci_group->zpci_group.mui);
62547e
 }
62547e
 
62547e
+static int mpcifc_reg_int_interp(S390PCIBusDevice *pbdev, ZpciFib *fib)
62547e
+{
62547e
+    int rc;
62547e
+
62547e
+    rc = s390_pci_kvm_aif_enable(pbdev, fib, pbdev->forwarding_assist);
62547e
+    if (rc) {
62547e
+        DPRINTF("Failed to enable interrupt forwarding\n");
62547e
+        return rc;
62547e
+    }
62547e
+
62547e
+    return 0;
62547e
+}
62547e
+
62547e
+static int mpcifc_dereg_int_interp(S390PCIBusDevice *pbdev, ZpciFib *fib)
62547e
+{
62547e
+    int rc;
62547e
+
62547e
+    rc = s390_pci_kvm_aif_disable(pbdev);
62547e
+    if (rc) {
62547e
+        DPRINTF("Failed to disable interrupt forwarding\n");
62547e
+        return rc;
62547e
+    }
62547e
+
62547e
+    return 0;
62547e
+}
62547e
+
62547e
 int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
62547e
                         uintptr_t ra)
62547e
 {
62547e
@@ -1120,7 +1146,12 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
62547e
 
62547e
     switch (oc) {
62547e
     case ZPCI_MOD_FC_REG_INT:
62547e
-        if (pbdev->summary_ind) {
62547e
+        if (pbdev->interp) {
62547e
+            if (mpcifc_reg_int_interp(pbdev, &fib)) {
62547e
+                cc = ZPCI_PCI_LS_ERR;
62547e
+                s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
62547e
+            }
62547e
+        } else if (pbdev->summary_ind) {
62547e
             cc = ZPCI_PCI_LS_ERR;
62547e
             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
62547e
         } else if (reg_irqs(env, pbdev, fib)) {
62547e
@@ -1129,7 +1160,12 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
62547e
         }
62547e
         break;
62547e
     case ZPCI_MOD_FC_DEREG_INT:
62547e
-        if (!pbdev->summary_ind) {
62547e
+        if (pbdev->interp) {
62547e
+            if (mpcifc_dereg_int_interp(pbdev, &fib)) {
62547e
+                cc = ZPCI_PCI_LS_ERR;
62547e
+                s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
62547e
+            }
62547e
+        } else if (!pbdev->summary_ind) {
62547e
             cc = ZPCI_PCI_LS_ERR;
62547e
             s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
62547e
         } else {
62547e
diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c
62547e
index 0f16104a74..9134fe185f 100644
62547e
--- a/hw/s390x/s390-pci-kvm.c
62547e
+++ b/hw/s390x/s390-pci-kvm.c
62547e
@@ -11,12 +11,42 @@
62547e
 
62547e
 #include "qemu/osdep.h"
62547e
 
62547e
+#include <linux/kvm.h>
62547e
+
62547e
 #include "kvm/kvm_s390x.h"
62547e
 #include "hw/s390x/pv.h"
62547e
+#include "hw/s390x/s390-pci-bus.h"
62547e
 #include "hw/s390x/s390-pci-kvm.h"
62547e
+#include "hw/s390x/s390-pci-inst.h"
62547e
 #include "cpu_models.h"
62547e
 
62547e
 bool s390_pci_kvm_interp_allowed(void)
62547e
 {
62547e
     return kvm_s390_get_zpci_op() && !s390_is_pv();
62547e
 }
62547e
+
62547e
+int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist)
62547e
+{
62547e
+    struct kvm_s390_zpci_op args = {
62547e
+        .fh = pbdev->fh,
62547e
+        .op = KVM_S390_ZPCIOP_REG_AEN,
62547e
+        .u.reg_aen.ibv = fib->aibv,
62547e
+        .u.reg_aen.sb = fib->aisb,
62547e
+        .u.reg_aen.noi = FIB_DATA_NOI(fib->data),
62547e
+        .u.reg_aen.isc = FIB_DATA_ISC(fib->data),
62547e
+        .u.reg_aen.sbo = FIB_DATA_AISBO(fib->data),
62547e
+        .u.reg_aen.flags = (assist) ? 0 : KVM_S390_ZPCIOP_REGAEN_HOST
62547e
+    };
62547e
+
62547e
+    return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args);
62547e
+}
62547e
+
62547e
+int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev)
62547e
+{
62547e
+    struct kvm_s390_zpci_op args = {
62547e
+        .fh = pbdev->fh,
62547e
+        .op = KVM_S390_ZPCIOP_DEREG_AEN
62547e
+    };
62547e
+
62547e
+    return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args);
62547e
+}
62547e
diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h
62547e
index a9843dfe97..5b09f0cf2f 100644
62547e
--- a/include/hw/s390x/s390-pci-bus.h
62547e
+++ b/include/hw/s390x/s390-pci-bus.h
62547e
@@ -351,6 +351,7 @@ struct S390PCIBusDevice {
62547e
     bool pci_unplug_request_processed;
62547e
     bool unplug_requested;
62547e
     bool interp;
62547e
+    bool forwarding_assist;
62547e
     QTAILQ_ENTRY(S390PCIBusDevice) link;
62547e
 };
62547e
 
62547e
diff --git a/include/hw/s390x/s390-pci-kvm.h b/include/hw/s390x/s390-pci-kvm.h
62547e
index 80a2e7d0ca..933814a402 100644
62547e
--- a/include/hw/s390x/s390-pci-kvm.h
62547e
+++ b/include/hw/s390x/s390-pci-kvm.h
62547e
@@ -12,13 +12,27 @@
62547e
 #ifndef HW_S390_PCI_KVM_H
62547e
 #define HW_S390_PCI_KVM_H
62547e
 
62547e
+#include "hw/s390x/s390-pci-bus.h"
62547e
+#include "hw/s390x/s390-pci-inst.h"
62547e
+
62547e
 #ifdef CONFIG_KVM
62547e
 bool s390_pci_kvm_interp_allowed(void);
62547e
+int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist);
62547e
+int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev);
62547e
 #else
62547e
 static inline bool s390_pci_kvm_interp_allowed(void)
62547e
 {
62547e
     return false;
62547e
 }
62547e
+static inline int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib,
62547e
+                                          bool assist)
62547e
+{
62547e
+    return -EINVAL;
62547e
+}
62547e
+static inline int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev)
62547e
+{
62547e
+    return -EINVAL;
62547e
+}
62547e
 #endif
62547e
 
62547e
 #endif
62547e
-- 
62547e
2.37.3
62547e