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