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