2022-06-07 07:10:03

by Matthew Rosato

[permalink] [raw]
Subject: [PATCH v9 00/21] KVM: s390: enable zPCI for interpretive execution

Enable interpretive execution of zPCI instructions + adapter interruption
forwarding for s390x KVM vfio-pci. This is done by triggering a routine
when the VFIO group is associated with the KVM guest, transmitting to
firmware a special token (GISA designation) to enable that specific guest
for interpretive execution on that zPCI device. Load/store interpreation
enablement is then controlled by userspace (based upon whether or not a
SHM bit is placed in the virtual function handle). Adapter Event
Notification interpretation is controlled from userspace via a new KVM
ioctl.

By allowing intepretation of zPCI instructions and firmware delivery of
interrupts to guests, we can reduce the frequency of guest SIE exits for
zPCI.

From the perspective of guest configuration, you passthrough zPCI devices
in the same manner as before, with intepretation support being used by
default if available in kernel+qemu.

Will follow up with a link the most recent QEMU series.

Changelog v8->v9:
- Rebase on top of 5.19-rc1, adjust ioctl and capability defines
- s/kzdev = 0/kzdev = NULL/ (Alex)
- rename vfio_pci_zdev_open to vfio_pci_zdev_open_device (Jason)
- rename vfio_pci_zdev_release to vfio_pci_zdev_close_device (Jason)
- make vfio_pci_zdev_close_device return void, instead WARN_ON or ignore
errors in lower level function (kvm_s390_pci_unregister_kvm) (Jason)
- remove notifier accidentally left in struct zpci_dev + associated
include statment (Jason)
- Remove patch 'KVM: s390: introduce CPU feature for zPCI Interpretation'
based on discussion in QEMU thread.

Matthew Rosato (21):
s390/sclp: detect the zPCI load/store interpretation facility
s390/sclp: detect the AISII facility
s390/sclp: detect the AENI facility
s390/sclp: detect the AISI facility
s390/airq: pass more TPI info to airq handlers
s390/airq: allow for airq structure that uses an input vector
s390/pci: externalize the SIC operation controls and routine
s390/pci: stash associated GISA designation
s390/pci: stash dtsm and maxstbl
vfio/pci: introduce CONFIG_VFIO_PCI_ZDEV_KVM
KVM: s390: pci: add basic kvm_zdev structure
KVM: s390: pci: do initial setup for AEN interpretation
KVM: s390: pci: enable host forwarding of Adapter Event Notifications
KVM: s390: mechanism to enable guest zPCI Interpretation
KVM: s390: pci: provide routines for enabling/disabling interrupt
forwarding
KVM: s390: pci: add routines to start/stop interpretive execution
vfio-pci/zdev: add open/close device hooks
vfio-pci/zdev: add function handle to clp base capability
vfio-pci/zdev: different maxstbl for interpreted devices
KVM: s390: add KVM_S390_ZPCI_OP to manage guest zPCI devices
MAINTAINERS: additional files related kvm s390 pci passthrough

Documentation/virt/kvm/api.rst | 47 +++
MAINTAINERS | 1 +
arch/s390/include/asm/airq.h | 7 +-
arch/s390/include/asm/kvm_host.h | 23 ++
arch/s390/include/asm/pci.h | 11 +
arch/s390/include/asm/pci_clp.h | 9 +-
arch/s390/include/asm/pci_insn.h | 29 +-
arch/s390/include/asm/sclp.h | 4 +
arch/s390/include/asm/tpi.h | 13 +
arch/s390/kvm/Makefile | 1 +
arch/s390/kvm/interrupt.c | 96 ++++-
arch/s390/kvm/kvm-s390.c | 83 +++-
arch/s390/kvm/kvm-s390.h | 10 +
arch/s390/kvm/pci.c | 690 +++++++++++++++++++++++++++++++
arch/s390/kvm/pci.h | 88 ++++
arch/s390/pci/pci.c | 16 +
arch/s390/pci/pci_clp.c | 7 +
arch/s390/pci/pci_insn.c | 4 +-
arch/s390/pci/pci_irq.c | 48 ++-
drivers/s390/char/sclp_early.c | 4 +
drivers/s390/cio/airq.c | 12 +-
drivers/s390/cio/qdio_thinint.c | 6 +-
drivers/s390/crypto/ap_bus.c | 9 +-
drivers/s390/virtio/virtio_ccw.c | 6 +-
drivers/vfio/pci/Kconfig | 11 +
drivers/vfio/pci/Makefile | 2 +-
drivers/vfio/pci/vfio_pci_core.c | 10 +-
drivers/vfio/pci/vfio_pci_zdev.c | 35 +-
include/linux/sched/user.h | 3 +-
include/linux/vfio_pci_core.h | 12 +-
include/uapi/linux/kvm.h | 31 ++
include/uapi/linux/vfio_zdev.h | 7 +
32 files changed, 1279 insertions(+), 56 deletions(-)
create mode 100644 arch/s390/kvm/pci.c
create mode 100644 arch/s390/kvm/pci.h

--
2.27.0


2022-06-07 08:36:32

by Matthew Rosato

[permalink] [raw]
Subject: [PATCH v9 13/21] KVM: s390: pci: enable host forwarding of Adapter Event Notifications

In cases where interrupts are not forwarded to the guest via firmware,
KVM is responsible for ensuring delivery. When an interrupt presents
with the forwarding bit, we must process the forwarding tables until
all interrupts are delivered.

Reviewed-by: Christian Borntraeger <[email protected]>
Reviewed-by: Pierre Morel <[email protected]>
Signed-off-by: Matthew Rosato <[email protected]>
---
arch/s390/include/asm/kvm_host.h | 1 +
arch/s390/include/asm/tpi.h | 13 ++++++
arch/s390/kvm/interrupt.c | 78 +++++++++++++++++++++++++++++++-
arch/s390/kvm/kvm-s390.c | 3 +-
arch/s390/kvm/pci.h | 10 ++++
5 files changed, 103 insertions(+), 2 deletions(-)

diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 766028d54a3e..c1518a505060 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -759,6 +759,7 @@ struct kvm_vm_stat {
u64 inject_pfault_done;
u64 inject_service_signal;
u64 inject_virtio;
+ u64 aen_forward;
};

struct kvm_arch_memory_slot {
diff --git a/arch/s390/include/asm/tpi.h b/arch/s390/include/asm/tpi.h
index 1ac538b8cbf5..f76e5fdff23a 100644
--- a/arch/s390/include/asm/tpi.h
+++ b/arch/s390/include/asm/tpi.h
@@ -19,6 +19,19 @@ struct tpi_info {
u32 :12;
} __packed __aligned(4);

+/* I/O-Interruption Code as stored by TPI for an Adapter I/O */
+struct tpi_adapter_info {
+ u32 aism:8;
+ u32 :22;
+ u32 error:1;
+ u32 forward:1;
+ u32 reserved;
+ u32 adapter_IO:1;
+ u32 directed_irq:1;
+ u32 isc:3;
+ u32 :27;
+} __packed __aligned(4);
+
#endif /* __ASSEMBLY__ */

#endif /* _ASM_S390_TPI_H */
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 37ff4358121a..d8e1fce78b7c 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -3313,11 +3313,87 @@ int kvm_s390_gisc_unregister(struct kvm *kvm, u32 gisc)
}
EXPORT_SYMBOL_GPL(kvm_s390_gisc_unregister);

+static void aen_host_forward(unsigned long si)
+{
+ struct kvm_s390_gisa_interrupt *gi;
+ struct zpci_gaite *gaite;
+ struct kvm *kvm;
+
+ gaite = (struct zpci_gaite *)aift->gait +
+ (si * sizeof(struct zpci_gaite));
+ if (gaite->count == 0)
+ return;
+ if (gaite->aisb != 0)
+ set_bit_inv(gaite->aisbo, (unsigned long *)gaite->aisb);
+
+ kvm = kvm_s390_pci_si_to_kvm(aift, si);
+ if (!kvm)
+ return;
+ gi = &kvm->arch.gisa_int;
+
+ if (!(gi->origin->g1.simm & AIS_MODE_MASK(gaite->gisc)) ||
+ !(gi->origin->g1.nimm & AIS_MODE_MASK(gaite->gisc))) {
+ gisa_set_ipm_gisc(gi->origin, gaite->gisc);
+ if (hrtimer_active(&gi->timer))
+ hrtimer_cancel(&gi->timer);
+ hrtimer_start(&gi->timer, 0, HRTIMER_MODE_REL);
+ kvm->stat.aen_forward++;
+ }
+}
+
+static void aen_process_gait(u8 isc)
+{
+ bool found = false, first = true;
+ union zpci_sic_iib iib = {{0}};
+ unsigned long si, flags;
+
+ spin_lock_irqsave(&aift->gait_lock, flags);
+
+ if (!aift->gait) {
+ spin_unlock_irqrestore(&aift->gait_lock, flags);
+ return;
+ }
+
+ for (si = 0;;) {
+ /* Scan adapter summary indicator bit vector */
+ si = airq_iv_scan(aift->sbv, si, airq_iv_end(aift->sbv));
+ if (si == -1UL) {
+ if (first || found) {
+ /* Re-enable interrupts. */
+ zpci_set_irq_ctrl(SIC_IRQ_MODE_SINGLE, isc,
+ &iib);
+ first = found = false;
+ } else {
+ /* Interrupts on and all bits processed */
+ break;
+ }
+ found = false;
+ si = 0;
+ /* Scan again after re-enabling interrupts */
+ continue;
+ }
+ found = true;
+ aen_host_forward(si);
+ }
+
+ spin_unlock_irqrestore(&aift->gait_lock, flags);
+}
+
static void gib_alert_irq_handler(struct airq_struct *airq,
struct tpi_info *tpi_info)
{
+ struct tpi_adapter_info *info = (struct tpi_adapter_info *)tpi_info;
+
inc_irq_stat(IRQIO_GAL);
- process_gib_alert_list();
+
+ if ((info->forward || info->error) &&
+ IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM)) {
+ aen_process_gait(info->isc);
+ if (info->aism != 0)
+ process_gib_alert_list();
+ } else {
+ process_gib_alert_list();
+ }
}

static struct airq_struct gib_alert_irq = {
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 251eaaff9c67..d96c9be0480b 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -64,7 +64,8 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
STATS_DESC_COUNTER(VM, inject_float_mchk),
STATS_DESC_COUNTER(VM, inject_pfault_done),
STATS_DESC_COUNTER(VM, inject_service_signal),
- STATS_DESC_COUNTER(VM, inject_virtio)
+ STATS_DESC_COUNTER(VM, inject_virtio),
+ STATS_DESC_COUNTER(VM, aen_forward)
};

const struct kvm_stats_header kvm_vm_stats_header = {
diff --git a/arch/s390/kvm/pci.h b/arch/s390/kvm/pci.h
index c357d900f8b0..9f7828d97605 100644
--- a/arch/s390/kvm/pci.h
+++ b/arch/s390/kvm/pci.h
@@ -13,6 +13,7 @@
#include <linux/kvm_host.h>
#include <linux/pci.h>
#include <linux/mutex.h>
+#include <linux/kvm_host.h>
#include <asm/airq.h>
#include <asm/cpu.h>

@@ -40,6 +41,15 @@ struct zpci_aift {

extern struct zpci_aift *aift;

+static inline struct kvm *kvm_s390_pci_si_to_kvm(struct zpci_aift *aift,
+ unsigned long si)
+{
+ if (!IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) || aift->kzdev == 0 ||
+ aift->kzdev[si] == 0)
+ return 0;
+ return aift->kzdev[si]->kvm;
+};
+
int kvm_s390_pci_aen_init(u8 nisc);
void kvm_s390_pci_aen_exit(void);

--
2.27.0

2022-06-07 09:02:50

by Matthew Rosato

[permalink] [raw]
Subject: [PATCH v9 10/21] vfio/pci: introduce CONFIG_VFIO_PCI_ZDEV_KVM

The current contents of vfio-pci-zdev are today only useful in a KVM
environment; let's tie everything currently under vfio-pci-zdev to
this Kconfig statement and require KVM in this case, reducing complexity
(e.g. symbol lookups).

Signed-off-by: Matthew Rosato <[email protected]>
---
drivers/vfio/pci/Kconfig | 11 +++++++++++
drivers/vfio/pci/Makefile | 2 +-
include/linux/vfio_pci_core.h | 2 +-
3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
index 4da1914425e1..f9d0c908e738 100644
--- a/drivers/vfio/pci/Kconfig
+++ b/drivers/vfio/pci/Kconfig
@@ -44,6 +44,17 @@ config VFIO_PCI_IGD
To enable Intel IGD assignment through vfio-pci, say Y.
endif

+config VFIO_PCI_ZDEV_KVM
+ bool "VFIO PCI extensions for s390x KVM passthrough"
+ depends on S390 && KVM
+ default y
+ help
+ Support s390x-specific extensions to enable support for enhancements
+ to KVM passthrough capabilities, such as interpretive execution of
+ zPCI instructions.
+
+ To enable s390x KVM vfio-pci extensions, say Y.
+
source "drivers/vfio/pci/mlx5/Kconfig"

source "drivers/vfio/pci/hisilicon/Kconfig"
diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index 7052ebd893e0..24c524224da5 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only

vfio-pci-core-y := vfio_pci_core.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
-vfio-pci-core-$(CONFIG_S390) += vfio_pci_zdev.o
+vfio-pci-core-$(CONFIG_VFIO_PCI_ZDEV_KVM) += vfio_pci_zdev.o
obj-$(CONFIG_VFIO_PCI_CORE) += vfio-pci-core.o

vfio-pci-y := vfio_pci.o
diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
index 23c176d4b073..63af2897939c 100644
--- a/include/linux/vfio_pci_core.h
+++ b/include/linux/vfio_pci_core.h
@@ -206,7 +206,7 @@ static inline int vfio_pci_igd_init(struct vfio_pci_core_device *vdev)
}
#endif

-#ifdef CONFIG_S390
+#ifdef CONFIG_VFIO_PCI_ZDEV_KVM
extern int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
struct vfio_info_cap *caps);
#else
--
2.27.0

2022-06-07 09:16:08

by Matthew Rosato

[permalink] [raw]
Subject: [PATCH v9 12/21] KVM: s390: pci: do initial setup for AEN interpretation

Initial setup for Adapter Event Notification Interpretation for zPCI
passthrough devices. Specifically, allocate a structure for forwarding of
adapter events and pass the address of this structure to firmware.

Reviewed-by: Christian Borntraeger <[email protected]>
Signed-off-by: Matthew Rosato <[email protected]>
---
arch/s390/include/asm/pci.h | 4 +
arch/s390/include/asm/pci_insn.h | 12 +++
arch/s390/kvm/interrupt.c | 14 +++
arch/s390/kvm/kvm-s390.c | 11 +++
arch/s390/kvm/pci.c | 160 +++++++++++++++++++++++++++++++
arch/s390/kvm/pci.h | 49 ++++++++++
arch/s390/pci/pci.c | 6 ++
7 files changed, 256 insertions(+)

diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 50f1851edfbe..322060a75d9f 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -9,6 +9,7 @@
#include <asm-generic/pci.h>
#include <asm/pci_clp.h>
#include <asm/pci_debug.h>
+#include <asm/pci_insn.h>
#include <asm/sclp.h>

#define PCIBIOS_MIN_IO 0x1000
@@ -204,6 +205,9 @@ extern const struct attribute_group *zpci_attr_groups[];
extern unsigned int s390_pci_force_floating __initdata;
extern unsigned int s390_pci_no_rid;

+extern union zpci_sic_iib *zpci_aipb;
+extern struct airq_iv *zpci_aif_sbv;
+
/* -----------------------------------------------------------------------------
Prototypes
----------------------------------------------------------------------------- */
diff --git a/arch/s390/include/asm/pci_insn.h b/arch/s390/include/asm/pci_insn.h
index 5331082fa516..e5f57cfe1d45 100644
--- a/arch/s390/include/asm/pci_insn.h
+++ b/arch/s390/include/asm/pci_insn.h
@@ -101,6 +101,7 @@ struct zpci_fib {
/* Set Interruption Controls Operation Controls */
#define SIC_IRQ_MODE_ALL 0
#define SIC_IRQ_MODE_SINGLE 1
+#define SIC_SET_AENI_CONTROLS 2
#define SIC_IRQ_MODE_DIRECT 4
#define SIC_IRQ_MODE_D_ALL 16
#define SIC_IRQ_MODE_D_SINGLE 17
@@ -127,9 +128,20 @@ struct zpci_cdiib {
u64 : 64;
} __packed __aligned(8);

+/* adapter interruption parameters block */
+struct zpci_aipb {
+ u64 faisb;
+ u64 gait;
+ u16 : 13;
+ u16 afi : 3;
+ u32 : 32;
+ u16 faal;
+} __packed __aligned(8);
+
union zpci_sic_iib {
struct zpci_diib diib;
struct zpci_cdiib cdiib;
+ struct zpci_aipb aipb;
};

DECLARE_STATIC_KEY_FALSE(have_mio);
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 17ff475157d8..37ff4358121a 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -32,6 +32,7 @@
#include "kvm-s390.h"
#include "gaccess.h"
#include "trace-s390.h"
+#include "pci.h"

#define PFAULT_INIT 0x0600
#define PFAULT_DONE 0x0680
@@ -3328,6 +3329,11 @@ void kvm_s390_gib_destroy(void)
{
if (!gib)
return;
+ if (kvm_s390_pci_interp_allowed() && aift) {
+ mutex_lock(&aift->aift_lock);
+ kvm_s390_pci_aen_exit();
+ mutex_unlock(&aift->aift_lock);
+ }
chsc_sgib(0);
unregister_adapter_interrupt(&gib_alert_irq);
free_page((unsigned long)gib);
@@ -3365,6 +3371,14 @@ int kvm_s390_gib_init(u8 nisc)
goto out_unreg_gal;
}

+ if (kvm_s390_pci_interp_allowed()) {
+ if (kvm_s390_pci_aen_init(nisc)) {
+ pr_err("Initializing AEN for PCI failed\n");
+ rc = -EIO;
+ goto out_unreg_gal;
+ }
+ }
+
KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
goto out;

diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 8fcb56141689..251eaaff9c67 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -47,6 +47,7 @@
#include <asm/fpu/api.h>
#include "kvm-s390.h"
#include "gaccess.h"
+#include "pci.h"

#define CREATE_TRACE_POINTS
#include "trace.h"
@@ -502,6 +503,14 @@ int kvm_arch_init(void *opaque)
goto out;
}

+ if (kvm_s390_pci_interp_allowed()) {
+ rc = kvm_s390_pci_init();
+ if (rc) {
+ pr_err("Unable to allocate AIFT for PCI\n");
+ goto out;
+ }
+ }
+
rc = kvm_s390_gib_init(GAL_ISC);
if (rc)
goto out;
@@ -516,6 +525,8 @@ int kvm_arch_init(void *opaque)
void kvm_arch_exit(void)
{
kvm_s390_gib_destroy();
+ if (kvm_s390_pci_interp_allowed())
+ kvm_s390_pci_exit();
debug_unregister(kvm_s390_dbf);
debug_unregister(kvm_s390_dbf_uv);
}
diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c
index e27191ea27c4..d566551d3018 100644
--- a/arch/s390/kvm/pci.c
+++ b/arch/s390/kvm/pci.c
@@ -9,8 +9,149 @@

#include <linux/kvm_host.h>
#include <linux/pci.h>
+#include <asm/pci.h>
+#include <asm/pci_insn.h>
#include "pci.h"

+struct zpci_aift *aift;
+
+static inline int __set_irq_noiib(u16 ctl, u8 isc)
+{
+ union zpci_sic_iib iib = {{0}};
+
+ return zpci_set_irq_ctrl(ctl, isc, &iib);
+}
+
+void kvm_s390_pci_aen_exit(void)
+{
+ unsigned long flags;
+ struct kvm_zdev **gait_kzdev;
+
+ lockdep_assert_held(&aift->aift_lock);
+
+ /*
+ * Contents of the aipb remain registered for the life of the host
+ * kernel, the information preserved in zpci_aipb and zpci_aif_sbv
+ * in case we insert the KVM module again later. Clear the AIFT
+ * information and free anything not registered with underlying
+ * firmware.
+ */
+ spin_lock_irqsave(&aift->gait_lock, flags);
+ gait_kzdev = aift->kzdev;
+ aift->gait = NULL;
+ aift->sbv = NULL;
+ aift->kzdev = NULL;
+ spin_unlock_irqrestore(&aift->gait_lock, flags);
+
+ kfree(gait_kzdev);
+}
+
+static int zpci_setup_aipb(u8 nisc)
+{
+ struct page *page;
+ int size, rc;
+
+ zpci_aipb = kzalloc(sizeof(union zpci_sic_iib), GFP_KERNEL);
+ if (!zpci_aipb)
+ return -ENOMEM;
+
+ aift->sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC, 0);
+ if (!aift->sbv) {
+ rc = -ENOMEM;
+ goto free_aipb;
+ }
+ zpci_aif_sbv = aift->sbv;
+ size = get_order(PAGE_ALIGN(ZPCI_NR_DEVICES *
+ sizeof(struct zpci_gaite)));
+ page = alloc_pages(GFP_KERNEL | __GFP_ZERO, size);
+ if (!page) {
+ rc = -ENOMEM;
+ goto free_sbv;
+ }
+ aift->gait = (struct zpci_gaite *)page_to_phys(page);
+
+ zpci_aipb->aipb.faisb = virt_to_phys(aift->sbv->vector);
+ zpci_aipb->aipb.gait = virt_to_phys(aift->gait);
+ zpci_aipb->aipb.afi = nisc;
+ zpci_aipb->aipb.faal = ZPCI_NR_DEVICES;
+
+ /* Setup Adapter Event Notification Interpretation */
+ if (zpci_set_irq_ctrl(SIC_SET_AENI_CONTROLS, 0, zpci_aipb)) {
+ rc = -EIO;
+ goto free_gait;
+ }
+
+ return 0;
+
+free_gait:
+ free_pages((unsigned long)aift->gait, size);
+free_sbv:
+ airq_iv_release(aift->sbv);
+ zpci_aif_sbv = NULL;
+free_aipb:
+ kfree(zpci_aipb);
+ zpci_aipb = NULL;
+
+ return rc;
+}
+
+static int zpci_reset_aipb(u8 nisc)
+{
+ /*
+ * AEN registration can only happen once per system boot. If
+ * an aipb already exists then AEN was already registered and
+ * we can re-use the aipb contents. This can only happen if
+ * the KVM module was removed and re-inserted. However, we must
+ * ensure that the same forwarding ISC is used as this is assigned
+ * during KVM module load.
+ */
+ if (zpci_aipb->aipb.afi != nisc)
+ return -EINVAL;
+
+ aift->sbv = zpci_aif_sbv;
+ aift->gait = (struct zpci_gaite *)zpci_aipb->aipb.gait;
+
+ return 0;
+}
+
+int kvm_s390_pci_aen_init(u8 nisc)
+{
+ int rc = 0;
+
+ /* If already enabled for AEN, bail out now */
+ if (aift->gait || aift->sbv)
+ return -EPERM;
+
+ mutex_lock(&aift->aift_lock);
+ aift->kzdev = kcalloc(ZPCI_NR_DEVICES, sizeof(struct kvm_zdev),
+ GFP_KERNEL);
+ if (!aift->kzdev) {
+ rc = -ENOMEM;
+ goto unlock;
+ }
+
+ if (!zpci_aipb)
+ rc = zpci_setup_aipb(nisc);
+ else
+ rc = zpci_reset_aipb(nisc);
+ if (rc)
+ goto free_zdev;
+
+ /* Enable floating IRQs */
+ if (__set_irq_noiib(SIC_IRQ_MODE_SINGLE, nisc)) {
+ rc = -EIO;
+ kvm_s390_pci_aen_exit();
+ }
+
+ goto unlock;
+
+free_zdev:
+ kfree(aift->kzdev);
+unlock:
+ mutex_unlock(&aift->aift_lock);
+ return rc;
+}
+
static int kvm_s390_pci_dev_open(struct zpci_dev *zdev)
{
struct kvm_zdev *kzdev;
@@ -34,3 +175,22 @@ static void kvm_s390_pci_dev_release(struct zpci_dev *zdev)
zdev->kzdev = NULL;
kfree(kzdev);
}
+
+int kvm_s390_pci_init(void)
+{
+ aift = kzalloc(sizeof(struct zpci_aift), GFP_KERNEL);
+ if (!aift)
+ return -ENOMEM;
+
+ spin_lock_init(&aift->gait_lock);
+ mutex_init(&aift->aift_lock);
+
+ return 0;
+}
+
+void kvm_s390_pci_exit(void)
+{
+ mutex_destroy(&aift->aift_lock);
+
+ kfree(aift);
+}
diff --git a/arch/s390/kvm/pci.h b/arch/s390/kvm/pci.h
index ce93978e8913..c357d900f8b0 100644
--- a/arch/s390/kvm/pci.h
+++ b/arch/s390/kvm/pci.h
@@ -12,10 +12,59 @@

#include <linux/kvm_host.h>
#include <linux/pci.h>
+#include <linux/mutex.h>
+#include <asm/airq.h>
+#include <asm/cpu.h>

struct kvm_zdev {
struct zpci_dev *zdev;
struct kvm *kvm;
};

+struct zpci_gaite {
+ u32 gisa;
+ u8 gisc;
+ u8 count;
+ u8 reserved;
+ u8 aisbo;
+ u64 aisb;
+};
+
+struct zpci_aift {
+ struct zpci_gaite *gait;
+ struct airq_iv *sbv;
+ struct kvm_zdev **kzdev;
+ spinlock_t gait_lock; /* Protects the gait, used during AEN forward */
+ struct mutex aift_lock; /* Protects the other structures in aift */
+};
+
+extern struct zpci_aift *aift;
+
+int kvm_s390_pci_aen_init(u8 nisc);
+void kvm_s390_pci_aen_exit(void);
+
+int kvm_s390_pci_init(void);
+void kvm_s390_pci_exit(void);
+
+static inline bool kvm_s390_pci_interp_allowed(void)
+{
+ struct cpuid cpu_id;
+
+ get_cpu_id(&cpu_id);
+ switch (cpu_id.machine) {
+ case 0x2817:
+ case 0x2818:
+ case 0x2827:
+ case 0x2828:
+ case 0x2964:
+ case 0x2965:
+ /* No SHM on certain machines */
+ return false;
+ default:
+ return (IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) &&
+ sclp.has_zpci_lsi && sclp.has_aeni && sclp.has_aisi &&
+ sclp.has_aisii);
+ }
+}
+
#endif /* __KVM_S390_PCI_H */
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index c8b9d866434c..86cd4d8446b1 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -61,6 +61,12 @@ DEFINE_STATIC_KEY_FALSE(have_mio);

static struct kmem_cache *zdev_fmb_cache;

+/* AEN structures that must be preserved over KVM module re-insertion */
+union zpci_sic_iib *zpci_aipb;
+EXPORT_SYMBOL_GPL(zpci_aipb);
+struct airq_iv *zpci_aif_sbv;
+EXPORT_SYMBOL_GPL(zpci_aif_sbv);
+
struct zpci_dev *get_zdev_by_fid(u32 fid)
{
struct zpci_dev *tmp, *zdev = NULL;
--
2.27.0

2022-06-07 09:32:16

by Matthew Rosato

[permalink] [raw]
Subject: [PATCH v9 06/21] s390/airq: allow for airq structure that uses an input vector

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 <[email protected]>
Reviewed-by: Pierre Morel <[email protected]>
Reviewed-by: Claudio Imbrenda <[email protected]>
Acked-by: Cornelia Huck <[email protected]>
Signed-off-by: Matthew Rosato <[email protected]>
---
arch/s390/include/asm/airq.h | 4 +++-
arch/s390/pci/pci_irq.c | 8 ++++----
drivers/s390/cio/airq.c | 10 +++++++---
drivers/s390/virtio/virtio_ccw.c | 2 +-
4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/arch/s390/include/asm/airq.h b/arch/s390/include/asm/airq.h
index 7918a7d09028..e82e5626e139 100644
--- a/arch/s390/include/asm/airq.h
+++ b/arch/s390/include/asm/airq.h
@@ -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);
diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c
index b805c75252ed..87c7d121c255 100644
--- a/arch/s390/pci/pci_irq.c
+++ b/arch/s390/pci/pci_irq.c
@@ -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;

diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index 230eb5b5b64e..34967e67249e 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -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 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags)
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);
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index 58cca50996ee..51bef226d33f 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -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;
--
2.27.0

2022-06-07 11:47:47

by Matthew Rosato

[permalink] [raw]
Subject: Re: [PATCH v9 00/21] KVM: s390: enable zPCI for interpretive execution

On 6/6/22 4:33 PM, Matthew Rosato wrote:
> Enable interpretive execution of zPCI instructions + adapter interruption
> forwarding for s390x KVM vfio-pci. This is done by triggering a routine
> when the VFIO group is associated with the KVM guest, transmitting to
> firmware a special token (GISA designation) to enable that specific guest
> for interpretive execution on that zPCI device. Load/store interpreation
> enablement is then controlled by userspace (based upon whether or not a
> SHM bit is placed in the virtual function handle). Adapter Event
> Notification interpretation is controlled from userspace via a new KVM
> ioctl.
>
> By allowing intepretation of zPCI instructions and firmware delivery of
> interrupts to guests, we can reduce the frequency of guest SIE exits for
> zPCI.
>
> From the perspective of guest configuration, you passthrough zPCI devices
> in the same manner as before, with intepretation support being used by
> default if available in kernel+qemu.
>
> Will follow up with a link the most recent QEMU series.
>

Latest QEMU series:

https://lore.kernel.org/kvm/[email protected]/

2022-06-07 12:08:43

by Matthew Rosato

[permalink] [raw]
Subject: [PATCH v9 09/21] s390/pci: stash dtsm and maxstbl

Store information about what IOAT designation types are supported by
underlying hardware as well as the largest store block size allowed.
These values will be needed by passthrough.

Reviewed-by: Niklas Schnelle <[email protected]>
Reviewed-by: Pierre Morel <[email protected]>
Reviewed-by: Christian Borntraeger <[email protected]>
Signed-off-by: Matthew Rosato <[email protected]>
---
arch/s390/include/asm/pci.h | 2 ++
arch/s390/include/asm/pci_clp.h | 6 ++++--
arch/s390/pci/pci_clp.c | 2 ++
3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 42a4a312a6dd..4c5b8fbc2079 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -126,9 +126,11 @@ struct zpci_dev {
u32 gisa; /* GISA designation for passthrough */
u16 vfn; /* virtual function number */
u16 pchid; /* physical channel ID */
+ u16 maxstbl; /* Maximum store block size */
u8 pfgid; /* function group ID */
u8 pft; /* pci function type */
u8 port;
+ u8 dtsm; /* Supported DT mask */
u8 rid_available : 1;
u8 has_hp_slot : 1;
u8 has_resources : 1;
diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h
index f3286bc5ba6e..d6189ed14f84 100644
--- a/arch/s390/include/asm/pci_clp.h
+++ b/arch/s390/include/asm/pci_clp.h
@@ -153,9 +153,11 @@ struct clp_rsp_query_pci_grp {
u8 : 6;
u8 frame : 1;
u8 refresh : 1; /* TLB refresh mode */
- u16 reserved2;
+ u16 : 3;
+ u16 maxstbl : 13; /* Maximum store block size */
u16 mui;
- u16 : 16;
+ u8 dtsm; /* Supported DT mask */
+ u8 reserved3;
u16 maxfaal;
u16 : 4;
u16 dnoi : 12;
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c
index d058c83467ef..ee367798e388 100644
--- a/arch/s390/pci/pci_clp.c
+++ b/arch/s390/pci/pci_clp.c
@@ -106,6 +106,8 @@ static void clp_store_query_pci_fngrp(struct zpci_dev *zdev,
zdev->max_msi = response->noi;
zdev->fmb_update = response->mui;
zdev->version = response->version;
+ zdev->maxstbl = response->maxstbl;
+ zdev->dtsm = response->dtsm;

switch (response->version) {
case 1:
--
2.27.0

2022-06-07 13:23:10

by Matthew Rosato

[permalink] [raw]
Subject: [PATCH v9 18/21] vfio-pci/zdev: add function handle to clp base capability

The function handle is a system-wide unique identifier for a zPCI
device. With zPCI instruction interpretation, the host will no
longer be executing the zPCI instructions on behalf of the guest.
As a result, the guest needs to use the real function handle in
order for firmware to associate the instruction with the proper
PCI function. Let's provide that handle to the guest.

Reviewed-by: Christian Borntraeger <[email protected]>
Reviewed-by: Pierre Morel <[email protected]>
Signed-off-by: Matthew Rosato <[email protected]>
---
drivers/vfio/pci/vfio_pci_zdev.c | 5 +++--
include/uapi/linux/vfio_zdev.h | 3 +++
2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_zdev.c b/drivers/vfio/pci/vfio_pci_zdev.c
index 686f2e75e392..4f28cdd7ecd1 100644
--- a/drivers/vfio/pci/vfio_pci_zdev.c
+++ b/drivers/vfio/pci/vfio_pci_zdev.c
@@ -24,14 +24,15 @@ static int zpci_base_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
{
struct vfio_device_info_cap_zpci_base cap = {
.header.id = VFIO_DEVICE_INFO_CAP_ZPCI_BASE,
- .header.version = 1,
+ .header.version = 2,
.start_dma = zdev->start_dma,
.end_dma = zdev->end_dma,
.pchid = zdev->pchid,
.vfn = zdev->vfn,
.fmb_length = zdev->fmb_length,
.pft = zdev->pft,
- .gid = zdev->pfgid
+ .gid = zdev->pfgid,
+ .fh = zdev->fh
};

return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
diff --git a/include/uapi/linux/vfio_zdev.h b/include/uapi/linux/vfio_zdev.h
index b4309397b6b2..78c022af3d29 100644
--- a/include/uapi/linux/vfio_zdev.h
+++ b/include/uapi/linux/vfio_zdev.h
@@ -29,6 +29,9 @@ struct vfio_device_info_cap_zpci_base {
__u16 fmb_length; /* Measurement Block Length (in bytes) */
__u8 pft; /* PCI Function Type */
__u8 gid; /* PCI function group ID */
+ /* End of version 1 */
+ __u32 fh; /* PCI function handle */
+ /* End of version 2 */
};

/**
--
2.27.0

2022-06-07 17:21:29

by Matthew Rosato

[permalink] [raw]
Subject: [PATCH v9 15/21] KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding

These routines will be wired into a kvm ioctl in order to respond to
requests to enable / disable a device for Adapter Event Notifications /
Adapter Interuption Forwarding.

Reviewed-by: Christian Borntraeger <[email protected]>
Acked-by: Niklas Schnelle <[email protected]>
Signed-off-by: Matthew Rosato <[email protected]>
---
arch/s390/kvm/pci.c | 247 +++++++++++++++++++++++++++++++++++++
arch/s390/kvm/pci.h | 1 +
arch/s390/pci/pci_insn.c | 1 +
include/linux/sched/user.h | 3 +-
4 files changed, 251 insertions(+), 1 deletion(-)

diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c
index d566551d3018..b232c8cbaa81 100644
--- a/arch/s390/kvm/pci.c
+++ b/arch/s390/kvm/pci.c
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <asm/pci.h>
#include <asm/pci_insn.h>
+#include <asm/pci_io.h>
#include "pci.h"

struct zpci_aift *aift;
@@ -152,6 +153,252 @@ int kvm_s390_pci_aen_init(u8 nisc)
return rc;
}

+/* Modify PCI: Register floating adapter interruption forwarding */
+static int kvm_zpci_set_airq(struct zpci_dev *zdev)
+{
+ u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT);
+ struct zpci_fib fib = {};
+ u8 status;
+
+ fib.fmt0.isc = zdev->kzdev->fib.fmt0.isc;
+ fib.fmt0.sum = 1; /* enable summary notifications */
+ fib.fmt0.noi = airq_iv_end(zdev->aibv);
+ fib.fmt0.aibv = virt_to_phys(zdev->aibv->vector);
+ fib.fmt0.aibvo = 0;
+ fib.fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8);
+ fib.fmt0.aisbo = zdev->aisb & 63;
+ fib.gd = zdev->gisa;
+
+ return zpci_mod_fc(req, &fib, &status) ? -EIO : 0;
+}
+
+/* Modify PCI: Unregister floating adapter interruption forwarding */
+static int kvm_zpci_clear_airq(struct zpci_dev *zdev)
+{
+ u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_DEREG_INT);
+ struct zpci_fib fib = {};
+ u8 cc, status;
+
+ fib.gd = zdev->gisa;
+
+ cc = zpci_mod_fc(req, &fib, &status);
+ if (cc == 3 || (cc == 1 && status == 24))
+ /* Function already gone or IRQs already deregistered. */
+ cc = 0;
+
+ return cc ? -EIO : 0;
+}
+
+static inline void unaccount_mem(unsigned long nr_pages)
+{
+ struct user_struct *user = get_uid(current_user());
+
+ if (user)
+ atomic_long_sub(nr_pages, &user->locked_vm);
+ if (current->mm)
+ atomic64_sub(nr_pages, &current->mm->pinned_vm);
+}
+
+static inline int account_mem(unsigned long nr_pages)
+{
+ struct user_struct *user = get_uid(current_user());
+ unsigned long page_limit, cur_pages, new_pages;
+
+ page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+
+ do {
+ cur_pages = atomic_long_read(&user->locked_vm);
+ new_pages = cur_pages + nr_pages;
+ if (new_pages > page_limit)
+ return -ENOMEM;
+ } while (atomic_long_cmpxchg(&user->locked_vm, cur_pages,
+ new_pages) != cur_pages);
+
+ atomic64_add(nr_pages, &current->mm->pinned_vm);
+
+ return 0;
+}
+
+static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
+ bool assist)
+{
+ struct page *pages[1], *aibv_page, *aisb_page = NULL;
+ unsigned int msi_vecs, idx;
+ struct zpci_gaite *gaite;
+ unsigned long hva, bit;
+ struct kvm *kvm;
+ phys_addr_t gaddr;
+ int rc = 0, gisc, npages, pcount = 0;
+
+ /*
+ * Interrupt forwarding is only applicable if the device is already
+ * enabled for interpretation
+ */
+ if (zdev->gisa == 0)
+ return -EINVAL;
+
+ kvm = zdev->kzdev->kvm;
+ msi_vecs = min_t(unsigned int, fib->fmt0.noi, zdev->max_msi);
+
+ /* Get the associated forwarding ISC - if invalid, return the error */
+ gisc = kvm_s390_gisc_register(kvm, fib->fmt0.isc);
+ if (gisc < 0)
+ return gisc;
+
+ /* Replace AIBV address */
+ idx = srcu_read_lock(&kvm->srcu);
+ hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aibv));
+ npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, pages);
+ srcu_read_unlock(&kvm->srcu, idx);
+ if (npages < 1) {
+ rc = -EIO;
+ goto out;
+ }
+ aibv_page = pages[0];
+ pcount++;
+ gaddr = page_to_phys(aibv_page) + (fib->fmt0.aibv & ~PAGE_MASK);
+ fib->fmt0.aibv = gaddr;
+
+ /* Pin the guest AISB if one was specified */
+ if (fib->fmt0.sum == 1) {
+ idx = srcu_read_lock(&kvm->srcu);
+ hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aisb));
+ npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM,
+ pages);
+ srcu_read_unlock(&kvm->srcu, idx);
+ if (npages < 1) {
+ rc = -EIO;
+ goto unpin1;
+ }
+ aisb_page = pages[0];
+ pcount++;
+ }
+
+ /* Account for pinned pages, roll back on failure */
+ if (account_mem(pcount))
+ goto unpin2;
+
+ /* AISB must be allocated before we can fill in GAITE */
+ mutex_lock(&aift->aift_lock);
+ bit = airq_iv_alloc_bit(aift->sbv);
+ if (bit == -1UL)
+ goto unlock;
+ zdev->aisb = bit; /* store the summary bit number */
+ zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA |
+ AIRQ_IV_BITLOCK |
+ AIRQ_IV_GUESTVEC,
+ phys_to_virt(fib->fmt0.aibv));
+
+ spin_lock_irq(&aift->gait_lock);
+ gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb *
+ sizeof(struct zpci_gaite));
+
+ /* If assist not requested, host will get all alerts */
+ if (assist)
+ gaite->gisa = (u32)virt_to_phys(&kvm->arch.sie_page2->gisa);
+ else
+ gaite->gisa = 0;
+
+ gaite->gisc = fib->fmt0.isc;
+ gaite->count++;
+ gaite->aisbo = fib->fmt0.aisbo;
+ gaite->aisb = virt_to_phys(page_address(aisb_page) + (fib->fmt0.aisb &
+ ~PAGE_MASK));
+ aift->kzdev[zdev->aisb] = zdev->kzdev;
+ spin_unlock_irq(&aift->gait_lock);
+
+ /* Update guest FIB for re-issue */
+ fib->fmt0.aisbo = zdev->aisb & 63;
+ fib->fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8);
+ fib->fmt0.isc = gisc;
+
+ /* Save some guest fib values in the host for later use */
+ zdev->kzdev->fib.fmt0.isc = fib->fmt0.isc;
+ zdev->kzdev->fib.fmt0.aibv = fib->fmt0.aibv;
+ mutex_unlock(&aift->aift_lock);
+
+ /* Issue the clp to setup the irq now */
+ rc = kvm_zpci_set_airq(zdev);
+ return rc;
+
+unlock:
+ mutex_unlock(&aift->aift_lock);
+unpin2:
+ if (fib->fmt0.sum == 1)
+ unpin_user_page(aisb_page);
+unpin1:
+ unpin_user_page(aibv_page);
+out:
+ return rc;
+}
+
+static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force)
+{
+ struct kvm_zdev *kzdev = zdev->kzdev;
+ struct zpci_gaite *gaite;
+ struct page *vpage = NULL, *spage = NULL;
+ int rc, pcount = 0;
+ u8 isc;
+
+ if (zdev->gisa == 0)
+ return -EINVAL;
+
+ mutex_lock(&aift->aift_lock);
+
+ /*
+ * If the clear fails due to an error, leave now unless we know this
+ * device is about to go away (force) -- In that case clear the GAITE
+ * regardless.
+ */
+ rc = kvm_zpci_clear_airq(zdev);
+ if (rc && !force)
+ goto out;
+
+ if (zdev->kzdev->fib.fmt0.aibv == 0)
+ goto out;
+ spin_lock_irq(&aift->gait_lock);
+ gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb *
+ sizeof(struct zpci_gaite));
+ isc = gaite->gisc;
+ gaite->count--;
+ if (gaite->count == 0) {
+ /* Release guest AIBV and AISB */
+ vpage = phys_to_page(kzdev->fib.fmt0.aibv);
+ if (gaite->aisb != 0)
+ spage = phys_to_page(gaite->aisb);
+ /* Clear the GAIT entry */
+ gaite->aisb = 0;
+ gaite->gisc = 0;
+ gaite->aisbo = 0;
+ gaite->gisa = 0;
+ aift->kzdev[zdev->aisb] = 0;
+ /* Clear zdev info */
+ airq_iv_free_bit(aift->sbv, zdev->aisb);
+ airq_iv_release(zdev->aibv);
+ zdev->aisb = 0;
+ zdev->aibv = NULL;
+ }
+ spin_unlock_irq(&aift->gait_lock);
+ kvm_s390_gisc_unregister(kzdev->kvm, isc);
+ kzdev->fib.fmt0.isc = 0;
+ kzdev->fib.fmt0.aibv = 0;
+
+ if (vpage) {
+ unpin_user_page(vpage);
+ pcount++;
+ }
+ if (spage) {
+ unpin_user_page(spage);
+ pcount++;
+ }
+ if (pcount > 0)
+ unaccount_mem(pcount);
+out:
+ mutex_unlock(&aift->aift_lock);
+
+ return rc;
+}
+
static int kvm_s390_pci_dev_open(struct zpci_dev *zdev)
{
struct kvm_zdev *kzdev;
diff --git a/arch/s390/kvm/pci.h b/arch/s390/kvm/pci.h
index 9f7828d97605..9d091033fc02 100644
--- a/arch/s390/kvm/pci.h
+++ b/arch/s390/kvm/pci.h
@@ -20,6 +20,7 @@
struct kvm_zdev {
struct zpci_dev *zdev;
struct kvm *kvm;
+ struct zpci_fib fib;
};

struct zpci_gaite {
diff --git a/arch/s390/pci/pci_insn.c b/arch/s390/pci/pci_insn.c
index 5798178aec9d..56480be48244 100644
--- a/arch/s390/pci/pci_insn.c
+++ b/arch/s390/pci/pci_insn.c
@@ -92,6 +92,7 @@ u8 zpci_mod_fc(u64 req, struct zpci_fib *fib, u8 *status)

return cc;
}
+EXPORT_SYMBOL_GPL(zpci_mod_fc);

/* Refresh PCI Translations */
static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
diff --git a/include/linux/sched/user.h b/include/linux/sched/user.h
index 00ed419dd464..f054d0360a75 100644
--- a/include/linux/sched/user.h
+++ b/include/linux/sched/user.h
@@ -24,7 +24,8 @@ struct user_struct {
kuid_t uid;

#if defined(CONFIG_PERF_EVENTS) || defined(CONFIG_BPF_SYSCALL) || \
- defined(CONFIG_NET) || defined(CONFIG_IO_URING)
+ defined(CONFIG_NET) || defined(CONFIG_IO_URING) || \
+ defined(CONFIG_VFIO_PCI_ZDEV_KVM)
atomic_long_t locked_vm;
#endif
#ifdef CONFIG_WATCH_QUEUE
--
2.27.0

2022-06-07 17:57:22

by Matthew Rosato

[permalink] [raw]
Subject: [PATCH v9 05/21] s390/airq: pass more TPI info to airq handlers

A subsequent patch will introduce an airq handler that requires additional
TPI information beyond directed vs floating, so pass the entire tpi_info
structure via the handler. Only pci actually uses this information today,
for the other airq handlers this is effectively a no-op.

Reviewed-by: Eric Farman <[email protected]>
Reviewed-by: Claudio Imbrenda <[email protected]>
Reviewed-by: Pierre Morel <[email protected]>
Reviewed-by: Thomas Huth <[email protected]>
Acked-by: Christian Borntraeger <[email protected]>
Acked-by: Cornelia Huck <[email protected]>
Signed-off-by: Matthew Rosato <[email protected]>
---
arch/s390/include/asm/airq.h | 3 ++-
arch/s390/kvm/interrupt.c | 4 +++-
arch/s390/pci/pci_irq.c | 9 +++++++--
drivers/s390/cio/airq.c | 2 +-
drivers/s390/cio/qdio_thinint.c | 6 ++++--
drivers/s390/crypto/ap_bus.c | 9 ++++++---
drivers/s390/virtio/virtio_ccw.c | 4 +++-
7 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/arch/s390/include/asm/airq.h b/arch/s390/include/asm/airq.h
index 01936fdfaddb..7918a7d09028 100644
--- a/arch/s390/include/asm/airq.h
+++ b/arch/s390/include/asm/airq.h
@@ -12,10 +12,11 @@

#include <linux/bit_spinlock.h>
#include <linux/dma-mapping.h>
+#include <asm/tpi.h>

struct airq_struct {
struct hlist_node list; /* Handler queueing. */
- void (*handler)(struct airq_struct *airq, bool floating);
+ void (*handler)(struct airq_struct *airq, struct tpi_info *tpi_info);
u8 *lsi_ptr; /* Local-Summary-Indicator pointer */
u8 lsi_mask; /* Local-Summary-Indicator mask */
u8 isc; /* Interrupt-subclass */
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index af96dc0549a4..17ff475157d8 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -28,6 +28,7 @@
#include <asm/switch_to.h>
#include <asm/nmi.h>
#include <asm/airq.h>
+#include <asm/tpi.h>
#include "kvm-s390.h"
#include "gaccess.h"
#include "trace-s390.h"
@@ -3311,7 +3312,8 @@ int kvm_s390_gisc_unregister(struct kvm *kvm, u32 gisc)
}
EXPORT_SYMBOL_GPL(kvm_s390_gisc_unregister);

-static void gib_alert_irq_handler(struct airq_struct *airq, bool floating)
+static void gib_alert_irq_handler(struct airq_struct *airq,
+ struct tpi_info *tpi_info)
{
inc_irq_stat(IRQIO_GAL);
process_gib_alert_list();
diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c
index 500cd2dbdf53..b805c75252ed 100644
--- a/arch/s390/pci/pci_irq.c
+++ b/arch/s390/pci/pci_irq.c
@@ -11,6 +11,7 @@

#include <asm/isc.h>
#include <asm/airq.h>
+#include <asm/tpi.h>

static enum {FLOATING, DIRECTED} irq_delivery;

@@ -216,8 +217,11 @@ static void zpci_handle_fallback_irq(void)
}
}

-static void zpci_directed_irq_handler(struct airq_struct *airq, bool floating)
+static void zpci_directed_irq_handler(struct airq_struct *airq,
+ struct tpi_info *tpi_info)
{
+ bool floating = !tpi_info->directed_irq;
+
if (floating) {
inc_irq_stat(IRQIO_PCF);
zpci_handle_fallback_irq();
@@ -227,7 +231,8 @@ static void zpci_directed_irq_handler(struct airq_struct *airq, bool floating)
}
}

-static void zpci_floating_irq_handler(struct airq_struct *airq, bool floating)
+static void zpci_floating_irq_handler(struct airq_struct *airq,
+ struct tpi_info *tpi_info)
{
unsigned long si, ai;
struct airq_iv *aibv;
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index c0ed364bf446..230eb5b5b64e 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -99,7 +99,7 @@ static irqreturn_t do_airq_interrupt(int irq, void *dummy)
rcu_read_lock();
hlist_for_each_entry_rcu(airq, head, list)
if ((*airq->lsi_ptr & airq->lsi_mask) != 0)
- airq->handler(airq, !tpi_info->directed_irq);
+ airq->handler(airq, tpi_info);
rcu_read_unlock();

return IRQ_HANDLED;
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 8e09bf3a2fcd..9b9335dd06db 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -15,6 +15,7 @@
#include <asm/qdio.h>
#include <asm/airq.h>
#include <asm/isc.h>
+#include <asm/tpi.h>

#include "cio.h"
#include "ioasm.h"
@@ -93,9 +94,10 @@ static inline u32 clear_shared_ind(void)
/**
* tiqdio_thinint_handler - thin interrupt handler for qdio
* @airq: pointer to adapter interrupt descriptor
- * @floating: flag to recognize floating vs. directed interrupts (unused)
+ * @tpi_info: interrupt information (e.g. floating vs directed -- unused)
*/
-static void tiqdio_thinint_handler(struct airq_struct *airq, bool floating)
+static void tiqdio_thinint_handler(struct airq_struct *airq,
+ struct tpi_info *tpi_info)
{
u64 irq_time = S390_lowcore.int_clock;
u32 si_used = clear_shared_ind();
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 5c13d2079d96..1b85f21c151b 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -27,6 +27,7 @@
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <asm/airq.h>
+#include <asm/tpi.h>
#include <linux/atomic.h>
#include <asm/isc.h>
#include <linux/hrtimer.h>
@@ -131,7 +132,8 @@ static int ap_max_adapter_id = 63;
static struct bus_type ap_bus_type;

/* Adapter interrupt definitions */
-static void ap_interrupt_handler(struct airq_struct *airq, bool floating);
+static void ap_interrupt_handler(struct airq_struct *airq,
+ struct tpi_info *tpi_info);

static bool ap_irq_flag;

@@ -452,9 +454,10 @@ static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
/**
* ap_interrupt_handler() - Schedule ap_tasklet on interrupt
* @airq: pointer to adapter interrupt descriptor
- * @floating: ignored
+ * @tpi_info: ignored
*/
-static void ap_interrupt_handler(struct airq_struct *airq, bool floating)
+static void ap_interrupt_handler(struct airq_struct *airq,
+ struct tpi_info *tpi_info)
{
inc_irq_stat(IRQIO_APB);
tasklet_schedule(&ap_tasklet);
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index 97e51c34e6cf..58cca50996ee 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -33,6 +33,7 @@
#include <asm/virtio-ccw.h>
#include <asm/isc.h>
#include <asm/airq.h>
+#include <asm/tpi.h>

/*
* virtio related functions
@@ -204,7 +205,8 @@ static void drop_airq_indicator(struct virtqueue *vq, struct airq_info *info)
write_unlock_irqrestore(&info->lock, flags);
}

-static void virtio_airq_handler(struct airq_struct *airq, bool floating)
+static void virtio_airq_handler(struct airq_struct *airq,
+ struct tpi_info *tpi_info)
{
struct airq_info *info = container_of(airq, struct airq_info, airq);
unsigned long ai;
--
2.27.0

2022-06-08 08:35:41

by Thomas Huth

[permalink] [raw]
Subject: Re: [PATCH v9 10/21] vfio/pci: introduce CONFIG_VFIO_PCI_ZDEV_KVM

On 06/06/2022 22.33, Matthew Rosato wrote:
> The current contents of vfio-pci-zdev are today only useful in a KVM
> environment; let's tie everything currently under vfio-pci-zdev to
> this Kconfig statement and require KVM in this case, reducing complexity
> (e.g. symbol lookups).
>
> Signed-off-by: Matthew Rosato <[email protected]>
> ---
> drivers/vfio/pci/Kconfig | 11 +++++++++++
> drivers/vfio/pci/Makefile | 2 +-
> include/linux/vfio_pci_core.h | 2 +-
> 3 files changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
> index 4da1914425e1..f9d0c908e738 100644
> --- a/drivers/vfio/pci/Kconfig
> +++ b/drivers/vfio/pci/Kconfig
> @@ -44,6 +44,17 @@ config VFIO_PCI_IGD
> To enable Intel IGD assignment through vfio-pci, say Y.
> endif
>
> +config VFIO_PCI_ZDEV_KVM
> + bool "VFIO PCI extensions for s390x KVM passthrough"
> + depends on S390 && KVM
> + default y
> + help
> + Support s390x-specific extensions to enable support for enhancements
> + to KVM passthrough capabilities, such as interpretive execution of
> + zPCI instructions.
> +
> + To enable s390x KVM vfio-pci extensions, say Y.

Is it still possible to disable CONFIG_VFIO_PCI_ZDEV_KVM ? Looking at the
later patches (e.g. 20/21 where you call kvm_s390_pci_zpci_op() from
kvm-s390.c), it rather seems to me that it currently cannot be disabled
independently (as long as KVM is enabled).

So if you want to make this selectable by the user, I think you have to put
some more #ifdefs in the following patches.
But if this was not meant to be selectable by the user, I think it should
not get a help text and rather be selected by the KVM switch in
arch/s390/kvm/Kconfig instead of having a "default y".

Thomas

2022-06-08 13:41:29

by Matthew Rosato

[permalink] [raw]
Subject: Re: [PATCH v9 10/21] vfio/pci: introduce CONFIG_VFIO_PCI_ZDEV_KVM

On 6/8/22 2:19 AM, Thomas Huth wrote:
> On 06/06/2022 22.33, Matthew Rosato wrote:
>> The current contents of vfio-pci-zdev are today only useful in a KVM
>> environment; let's tie everything currently under vfio-pci-zdev to
>> this Kconfig statement and require KVM in this case, reducing complexity
>> (e.g. symbol lookups).
>>
>> Signed-off-by: Matthew Rosato <[email protected]>
>> ---
>>   drivers/vfio/pci/Kconfig      | 11 +++++++++++
>>   drivers/vfio/pci/Makefile     |  2 +-
>>   include/linux/vfio_pci_core.h |  2 +-
>>   3 files changed, 13 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
>> index 4da1914425e1..f9d0c908e738 100644
>> --- a/drivers/vfio/pci/Kconfig
>> +++ b/drivers/vfio/pci/Kconfig
>> @@ -44,6 +44,17 @@ config VFIO_PCI_IGD
>>         To enable Intel IGD assignment through vfio-pci, say Y.
>>   endif
>> +config VFIO_PCI_ZDEV_KVM
>> +    bool "VFIO PCI extensions for s390x KVM passthrough"
>> +    depends on S390 && KVM
>> +    default y
>> +    help
>> +      Support s390x-specific extensions to enable support for
>> enhancements
>> +      to KVM passthrough capabilities, such as interpretive execution of
>> +      zPCI instructions.
>> +
>> +      To enable s390x KVM vfio-pci extensions, say Y.
>
> Is it still possible to disable CONFIG_VFIO_PCI_ZDEV_KVM ? Looking at
> the later patches (e.g. 20/21 where you call kvm_s390_pci_zpci_op() from
> kvm-s390.c), it rather seems to me that it currently cannot be disabled
> independently (as long as KVM is enabled).

Yes, you can build with, for example, CONFIG_VFIO_PCI_ZDEV_KVM=n and
CONFIG_KVM=m -- I tested it again just now. The result is kvm and
vfio-pci are built and vfio-pci works, but none of the vfio-pci-zdev
extensions are available (including zPCI interpretation).

This is accomplished via the placement of some IS_ENABLED checks. Some
calls (e.g. AEN init) are fenced by
IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM). There are also some areas that
are fenced off via a call to kvm_s390_pci_interp_allowed() which also
includes an IS_ENABLED check along with checks for facility and cpu id.

Using patch 20 as an example, KVM_CAP_S390_ZPCI_OP will always be
reported as unavailable to userspace if CONFIG_VFIO_PCI_ZDEV_KVM=n due
to the call to kvm_s390_pci_interp_allowed(). If userspace sends us the
ioctl anyway, we will return -EINVAL because there is again a
IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) check before we read the ioctl args
from userspace.

>
> So if you want to make this selectable by the user, I think you have to
> put some more #ifdefs in the following patches.
> But if this was not meant to be selectable by the user, I think it
> should not get a help text and rather be selected by the KVM switch in
> arch/s390/kvm/Kconfig instead of having a "default y".
>
>  Thomas
>

2022-06-14 09:06:47

by Pierre Morel

[permalink] [raw]
Subject: Re: [PATCH v9 10/21] vfio/pci: introduce CONFIG_VFIO_PCI_ZDEV_KVM



On 6/8/22 15:15, Matthew Rosato wrote:
> On 6/8/22 2:19 AM, Thomas Huth wrote:
>> On 06/06/2022 22.33, Matthew Rosato wrote:
>>> The current contents of vfio-pci-zdev are today only useful in a KVM
>>> environment; let's tie everything currently under vfio-pci-zdev to
>>> this Kconfig statement and require KVM in this case, reducing complexity
>>> (e.g. symbol lookups).
>>>
>>> Signed-off-by: Matthew Rosato <[email protected]>

Reviewed-by: Pierre Morel <[email protected]>


>>> ---
>>>   drivers/vfio/pci/Kconfig      | 11 +++++++++++
>>>   drivers/vfio/pci/Makefile     |  2 +-
>>>   include/linux/vfio_pci_core.h |  2 +-
>>>   3 files changed, 13 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
>>> index 4da1914425e1..f9d0c908e738 100644
>>> --- a/drivers/vfio/pci/Kconfig
>>> +++ b/drivers/vfio/pci/Kconfig
>>> @@ -44,6 +44,17 @@ config VFIO_PCI_IGD
>>>         To enable Intel IGD assignment through vfio-pci, say Y.
>>>   endif
>>> +config VFIO_PCI_ZDEV_KVM
>>> +    bool "VFIO PCI extensions for s390x KVM passthrough"
>>> +    depends on S390 && KVM
>>> +    default y
>>> +    help
>>> +      Support s390x-specific extensions to enable support for
>>> enhancements
>>> +      to KVM passthrough capabilities, such as interpretive
>>> execution of
>>> +      zPCI instructions.
>>> +
>>> +      To enable s390x KVM vfio-pci extensions, say Y.
>>
>> Is it still possible to disable CONFIG_VFIO_PCI_ZDEV_KVM ? Looking at
>> the later patches (e.g. 20/21 where you call kvm_s390_pci_zpci_op()
>> from kvm-s390.c), it rather seems to me that it currently cannot be
>> disabled independently (as long as KVM is enabled).
>
> Yes, you can build with, for example, CONFIG_VFIO_PCI_ZDEV_KVM=n and
> CONFIG_KVM=m -- I tested it again just now.  The result is kvm and
> vfio-pci are built and vfio-pci works, but none of the vfio-pci-zdev
> extensions are available (including zPCI interpretation).
>
> This is accomplished via the placement of some IS_ENABLED checks.  Some
> calls (e.g. AEN init) are fenced by
> IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM).  There are also some areas that
> are fenced off via a call to kvm_s390_pci_interp_allowed() which also
> includes an IS_ENABLED check along with checks for facility and cpu id.
>
> Using patch 20 as an example, KVM_CAP_S390_ZPCI_OP will always be
> reported as unavailable to userspace if CONFIG_VFIO_PCI_ZDEV_KVM=n due
> to the call to kvm_s390_pci_interp_allowed().  If userspace sends us the
> ioctl anyway, we will return -EINVAL because there is again a
> IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) check before we read the ioctl args
> from userspace.

Yes and the code will not be generated by the compiler in patch 20 after
the break if CONFIG_VFIO_PCI_ZDEV_KVM is not enabled.

+ case KVM_S390_ZPCI_OP: {
+ struct kvm_s390_zpci_op args;
+
+ r = -EINVAL;
+ if (!IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM))
+ break;

Code not generated----v

+ if (copy_from_user(&args, argp, sizeof(args))) {
+ r = -EFAULT;
+ break;
+ }
+ r = kvm_s390_pci_zpci_op(kvm, &args);
+ break;

----------^

+ }
>
>>
>> So if you want to make this selectable by the user, I think you have
>> to put some more #ifdefs in the following patches.
>> But if this was not meant to be selectable by the user, I think it
>> should not get a help text and rather be selected by the KVM switch in
>> arch/s390/kvm/Kconfig instead of having a "default y".
>>
>>   Thomas
>>
>

--
Pierre Morel
IBM Lab Boeblingen

2022-06-17 16:27:01

by Thomas Huth

[permalink] [raw]
Subject: Re: [PATCH v9 10/21] vfio/pci: introduce CONFIG_VFIO_PCI_ZDEV_KVM

On 14/06/2022 10.56, Pierre Morel wrote:
>
>
> On 6/8/22 15:15, Matthew Rosato wrote:
>> On 6/8/22 2:19 AM, Thomas Huth wrote:
>>> On 06/06/2022 22.33, Matthew Rosato wrote:
>>>> The current contents of vfio-pci-zdev are today only useful in a KVM
>>>> environment; let's tie everything currently under vfio-pci-zdev to
>>>> this Kconfig statement and require KVM in this case, reducing complexity
>>>> (e.g. symbol lookups).
>>>>
>>>> Signed-off-by: Matthew Rosato <[email protected]>
>
> Reviewed-by: Pierre Morel <[email protected]>
>
>
>>>> ---
>>>>   drivers/vfio/pci/Kconfig      | 11 +++++++++++
>>>>   drivers/vfio/pci/Makefile     |  2 +-
>>>>   include/linux/vfio_pci_core.h |  2 +-
>>>>   3 files changed, 13 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
>>>> index 4da1914425e1..f9d0c908e738 100644
>>>> --- a/drivers/vfio/pci/Kconfig
>>>> +++ b/drivers/vfio/pci/Kconfig
>>>> @@ -44,6 +44,17 @@ config VFIO_PCI_IGD
>>>>         To enable Intel IGD assignment through vfio-pci, say Y.
>>>>   endif
>>>> +config VFIO_PCI_ZDEV_KVM
>>>> +    bool "VFIO PCI extensions for s390x KVM passthrough"
>>>> +    depends on S390 && KVM
>>>> +    default y
>>>> +    help
>>>> +      Support s390x-specific extensions to enable support for enhancements
>>>> +      to KVM passthrough capabilities, such as interpretive execution of
>>>> +      zPCI instructions.
>>>> +
>>>> +      To enable s390x KVM vfio-pci extensions, say Y.
>>>
>>> Is it still possible to disable CONFIG_VFIO_PCI_ZDEV_KVM ? Looking at the
>>> later patches (e.g. 20/21 where you call kvm_s390_pci_zpci_op() from
>>> kvm-s390.c), it rather seems to me that it currently cannot be disabled
>>> independently (as long as KVM is enabled).
>>
>> Yes, you can build with, for example, CONFIG_VFIO_PCI_ZDEV_KVM=n and
>> CONFIG_KVM=m -- I tested it again just now.  The result is kvm and
>> vfio-pci are built and vfio-pci works, but none of the vfio-pci-zdev
>> extensions are available (including zPCI interpretation).
>>
>> This is accomplished via the placement of some IS_ENABLED checks.  Some
>> calls (e.g. AEN init) are fenced by IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM).
>> There are also some areas that are fenced off via a call to
>> kvm_s390_pci_interp_allowed() which also includes an IS_ENABLED check
>> along with checks for facility and cpu id.
>>
>> Using patch 20 as an example, KVM_CAP_S390_ZPCI_OP will always be reported
>> as unavailable to userspace if CONFIG_VFIO_PCI_ZDEV_KVM=n due to the call
>> to kvm_s390_pci_interp_allowed().  If userspace sends us the ioctl anyway,
>> we will return -EINVAL because there is again a
>> IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) check before we read the ioctl args
>> from userspace.
>
> Yes and the code will not be generated by the compiler in patch 20 after the
> break if CONFIG_VFIO_PCI_ZDEV_KVM is not enabled.
>
> +    case KVM_S390_ZPCI_OP: {
> +        struct kvm_s390_zpci_op args;
> +
> +        r = -EINVAL;
> +        if (!IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM))
> +            break;
>
> Code not generated----v
>
> +        if (copy_from_user(&args, argp, sizeof(args))) {
> +            r = -EFAULT;
> +            break;
> +        }
> +        r = kvm_s390_pci_zpci_op(kvm, &args);
> +        break;
>
> ----------^

OK, good to know, thanks for the clarification!

Thomas

2022-06-27 21:10:28

by Matthew Rosato

[permalink] [raw]
Subject: Re: [PATCH v9 00/21] KVM: s390: enable zPCI for interpretive execution

On 6/6/22 4:33 PM, Matthew Rosato wrote:
> Enable interpretive execution of zPCI instructions + adapter interruption
> forwarding for s390x KVM vfio-pci. This is done by triggering a routine
> when the VFIO group is associated with the KVM guest, transmitting to
> firmware a special token (GISA designation) to enable that specific guest
> for interpretive execution on that zPCI device. Load/store interpreation
> enablement is then controlled by userspace (based upon whether or not a
> SHM bit is placed in the virtual function handle). Adapter Event
> Notification interpretation is controlled from userspace via a new KVM
> ioctl.
>
> By allowing intepretation of zPCI instructions and firmware delivery of
> interrupts to guests, we can reduce the frequency of guest SIE exits for
> zPCI.
>
> From the perspective of guest configuration, you passthrough zPCI devices
> in the same manner as before, with intepretation support being used by
> default if available in kernel+qemu.
>
> Will follow up with a link the most recent QEMU series.
>
> Changelog v8->v9:
> - Rebase on top of 5.19-rc1, adjust ioctl and capability defines
> - s/kzdev = 0/kzdev = NULL/ (Alex)
> - rename vfio_pci_zdev_open to vfio_pci_zdev_open_device (Jason)
> - rename vfio_pci_zdev_release to vfio_pci_zdev_close_device (Jason)
> - make vfio_pci_zdev_close_device return void, instead WARN_ON or ignore
> errors in lower level function (kvm_s390_pci_unregister_kvm) (Jason)
> - remove notifier accidentally left in struct zpci_dev + associated
> include statment (Jason)
> - Remove patch 'KVM: s390: introduce CPU feature for zPCI Interpretation'
> based on discussion in QEMU thread.
>

Ping -- I'm hoping this can make the next merge window, but there are
still 2 patches left without any review tag (16 & 17).

2022-06-28 12:47:50

by Christian Borntraeger

[permalink] [raw]
Subject: Re: [PATCH v9 00/21] KVM: s390: enable zPCI for interpretive execution

Am 27.06.22 um 22:57 schrieb Matthew Rosato:
> On 6/6/22 4:33 PM, Matthew Rosato wrote:
>> Enable interpretive execution of zPCI instructions + adapter interruption
>> forwarding for s390x KVM vfio-pci.  This is done by triggering a routine
>> when the VFIO group is associated with the KVM guest, transmitting to
>> firmware a special token (GISA designation) to enable that specific guest
>> for interpretive execution on that zPCI device.  Load/store interpreation
>> enablement is then controlled by userspace (based upon whether or not a
>> SHM bit is placed in the virtual function handle).  Adapter Event
>> Notification interpretation is controlled from userspace via a new KVM
>> ioctl.
>>
>> By allowing intepretation of zPCI instructions and firmware delivery of
>> interrupts to guests, we can reduce the frequency of guest SIE exits for
>> zPCI.
>>
>>  From the perspective of guest configuration, you passthrough zPCI devices
>> in the same manner as before, with intepretation support being used by
>> default if available in kernel+qemu.
>>
>> Will follow up with a link the most recent QEMU series.
>>
>> Changelog v8->v9:
>> - Rebase on top of 5.19-rc1, adjust ioctl and capability defines
>> - s/kzdev = 0/kzdev = NULL/ (Alex)
>> - rename vfio_pci_zdev_open to vfio_pci_zdev_open_device (Jason)
>> - rename vfio_pci_zdev_release to vfio_pci_zdev_close_device (Jason)
>> - make vfio_pci_zdev_close_device return void, instead WARN_ON or ignore
>>    errors in lower level function (kvm_s390_pci_unregister_kvm) (Jason)
>> - remove notifier accidentally left in struct zpci_dev + associated
>>    include statment (Jason)
>> - Remove patch 'KVM: s390: introduce CPU feature for zPCI Interpretation'
>>    based on discussion in QEMU thread.
>>
>
> Ping -- I'm hoping this can make the next merge window, but there are still 2 patches left without any review tag (16 & 17).

Yes, I will queue this (as is). Ideally you would rebase this on top of kvm/next but I can also do while applying.
Let me know if you want to respin with the Nits from Pierre.

2022-06-28 13:57:22

by Matthew Rosato

[permalink] [raw]
Subject: Re: [PATCH v9 00/21] KVM: s390: enable zPCI for interpretive execution

On 6/28/22 8:35 AM, Christian Borntraeger wrote:
> Am 27.06.22 um 22:57 schrieb Matthew Rosato:
>> On 6/6/22 4:33 PM, Matthew Rosato wrote:
>>> Enable interpretive execution of zPCI instructions + adapter
>>> interruption
>>> forwarding for s390x KVM vfio-pci.  This is done by triggering a routine
>>> when the VFIO group is associated with the KVM guest, transmitting to
>>> firmware a special token (GISA designation) to enable that specific
>>> guest
>>> for interpretive execution on that zPCI device.  Load/store
>>> interpreation
>>> enablement is then controlled by userspace (based upon whether or not a
>>> SHM bit is placed in the virtual function handle).  Adapter Event
>>> Notification interpretation is controlled from userspace via a new KVM
>>> ioctl.
>>>
>>> By allowing intepretation of zPCI instructions and firmware delivery of
>>> interrupts to guests, we can reduce the frequency of guest SIE exits for
>>> zPCI.
>>>
>>>  From the perspective of guest configuration, you passthrough zPCI
>>> devices
>>> in the same manner as before, with intepretation support being used by
>>> default if available in kernel+qemu.
>>>
>>> Will follow up with a link the most recent QEMU series.
>>>
>>> Changelog v8->v9:
>>> - Rebase on top of 5.19-rc1, adjust ioctl and capability defines
>>> - s/kzdev = 0/kzdev = NULL/ (Alex)
>>> - rename vfio_pci_zdev_open to vfio_pci_zdev_open_device (Jason)
>>> - rename vfio_pci_zdev_release to vfio_pci_zdev_close_device (Jason)
>>> - make vfio_pci_zdev_close_device return void, instead WARN_ON or ignore
>>>    errors in lower level function (kvm_s390_pci_unregister_kvm) (Jason)
>>> - remove notifier accidentally left in struct zpci_dev + associated
>>>    include statment (Jason)
>>> - Remove patch 'KVM: s390: introduce CPU feature for zPCI
>>> Interpretation'
>>>    based on discussion in QEMU thread.
>>>
>>
>> Ping -- I'm hoping this can make the next merge window, but there are
>> still 2 patches left without any review tag (16 & 17).
>
> Yes, I will queue this (as is). Ideally you would rebase this on top of
> kvm/next but I can also do while applying.
> Let me know if you want to respin with the Nits from Pierre.

Ah, sorry -- I assume you mean Paolo's kvm/next? I tried now and see
some conflicts with the ioctl patch.

Why don't I rebase on top of kvm/next along with these couple of changes
from Pierre and send this as a v10 for you to queue.

While at it, there's one other issue to be aware of -- There will also
be small merge conflicts with a patch that just hit vfio-next, "vfio:
de-extern-ify function prototypes" - My series already avoids adding
externs to new prototypes, but adjacent code changes will cause a
conflict with patches 10 and 17.

Not sure what the best way to proceed there is.

https://lore.kernel.org/kvm/[email protected]/

2022-06-28 14:19:12

by Christian Borntraeger

[permalink] [raw]
Subject: Re: [PATCH v9 00/21] KVM: s390: enable zPCI for interpretive execution



Am 28.06.22 um 15:40 schrieb Matthew Rosato:
> On 6/28/22 8:35 AM, Christian Borntraeger wrote:
>> Am 27.06.22 um 22:57 schrieb Matthew Rosato:
>>> On 6/6/22 4:33 PM, Matthew Rosato wrote:
>>>> Enable interpretive execution of zPCI instructions + adapter interruption
>>>> forwarding for s390x KVM vfio-pci.  This is done by triggering a routine
>>>> when the VFIO group is associated with the KVM guest, transmitting to
>>>> firmware a special token (GISA designation) to enable that specific guest
>>>> for interpretive execution on that zPCI device.  Load/store interpreation
>>>> enablement is then controlled by userspace (based upon whether or not a
>>>> SHM bit is placed in the virtual function handle).  Adapter Event
>>>> Notification interpretation is controlled from userspace via a new KVM
>>>> ioctl.
>>>>
>>>> By allowing intepretation of zPCI instructions and firmware delivery of
>>>> interrupts to guests, we can reduce the frequency of guest SIE exits for
>>>> zPCI.
>>>>
>>>>  From the perspective of guest configuration, you passthrough zPCI devices
>>>> in the same manner as before, with intepretation support being used by
>>>> default if available in kernel+qemu.
>>>>
>>>> Will follow up with a link the most recent QEMU series.
>>>>
>>>> Changelog v8->v9:
>>>> - Rebase on top of 5.19-rc1, adjust ioctl and capability defines
>>>> - s/kzdev = 0/kzdev = NULL/ (Alex)
>>>> - rename vfio_pci_zdev_open to vfio_pci_zdev_open_device (Jason)
>>>> - rename vfio_pci_zdev_release to vfio_pci_zdev_close_device (Jason)
>>>> - make vfio_pci_zdev_close_device return void, instead WARN_ON or ignore
>>>>    errors in lower level function (kvm_s390_pci_unregister_kvm) (Jason)
>>>> - remove notifier accidentally left in struct zpci_dev + associated
>>>>    include statment (Jason)
>>>> - Remove patch 'KVM: s390: introduce CPU feature for zPCI Interpretation'
>>>>    based on discussion in QEMU thread.
>>>>
>>>
>>> Ping -- I'm hoping this can make the next merge window, but there are still 2 patches left without any review tag (16 & 17).
>>
>> Yes, I will queue this (as is). Ideally you would rebase this on top of kvm/next but I can also do while applying.
>> Let me know if you want to respin with the Nits from Pierre.
>
> Ah, sorry -- I assume you mean Paolo's kvm/next?  I tried now and see some conflicts with the ioctl patch.
>
> Why don't I rebase on top of kvm/next along with these couple of changes from Pierre and send this as a v10 for you to queue.
>
> While at it, there's one other issue to be aware of -- There will also be small merge conflicts with a patch that just hit vfio-next, "vfio: de-extern-ify function prototypes" - My series already avoids adding externs to new prototypes, but adjacent code changes will cause a conflict with patches 10 and 17.
>
> Not sure what the best way to proceed there is.
>
> https://lore.kernel.org/kvm/[email protected]/

I think Linus can sort out if the conflicts are trivial. As an alternative Alex could carry these patches, but then we have a merge conflict between him and KVM.
Alex/Paolo, shall I do a topic branch that you both can merge?

2022-06-28 14:34:11

by Jason Gunthorpe

[permalink] [raw]
Subject: Re: [PATCH v9 00/21] KVM: s390: enable zPCI for interpretive execution

On Tue, Jun 28, 2022 at 09:40:01AM -0400, Matthew Rosato wrote:
> On 6/28/22 8:35 AM, Christian Borntraeger wrote:
> > Am 27.06.22 um 22:57 schrieb Matthew Rosato:
> > > On 6/6/22 4:33 PM, Matthew Rosato wrote:
> > > > Enable interpretive execution of zPCI instructions + adapter
> > > > interruption
> > > > forwarding for s390x KVM vfio-pci.  This is done by triggering a routine
> > > > when the VFIO group is associated with the KVM guest, transmitting to
> > > > firmware a special token (GISA designation) to enable that
> > > > specific guest
> > > > for interpretive execution on that zPCI device.  Load/store
> > > > interpreation
> > > > enablement is then controlled by userspace (based upon whether or not a
> > > > SHM bit is placed in the virtual function handle).  Adapter Event
> > > > Notification interpretation is controlled from userspace via a new KVM
> > > > ioctl.
> > > >
> > > > By allowing intepretation of zPCI instructions and firmware delivery of
> > > > interrupts to guests, we can reduce the frequency of guest SIE exits for
> > > > zPCI.
> > > >
> > > >  From the perspective of guest configuration, you passthrough
> > > > zPCI devices
> > > > in the same manner as before, with intepretation support being used by
> > > > default if available in kernel+qemu.
> > > >
> > > > Will follow up with a link the most recent QEMU series.
> > > >
> > > > Changelog v8->v9:
> > > > - Rebase on top of 5.19-rc1, adjust ioctl and capability defines
> > > > - s/kzdev = 0/kzdev = NULL/ (Alex)
> > > > - rename vfio_pci_zdev_open to vfio_pci_zdev_open_device (Jason)
> > > > - rename vfio_pci_zdev_release to vfio_pci_zdev_close_device (Jason)
> > > > - make vfio_pci_zdev_close_device return void, instead WARN_ON or ignore
> > > >    errors in lower level function (kvm_s390_pci_unregister_kvm) (Jason)
> > > > - remove notifier accidentally left in struct zpci_dev + associated
> > > >    include statment (Jason)
> > > > - Remove patch 'KVM: s390: introduce CPU feature for zPCI
> > > > Interpretation'
> > > >    based on discussion in QEMU thread.
> > > >
> > >
> > > Ping -- I'm hoping this can make the next merge window, but there
> > > are still 2 patches left without any review tag (16 & 17).
> >
> > Yes, I will queue this (as is). Ideally you would rebase this on top of
> > kvm/next but I can also do while applying.
> > Let me know if you want to respin with the Nits from Pierre.
>
> Ah, sorry -- I assume you mean Paolo's kvm/next? I tried now and see some
> conflicts with the ioctl patch.
>
> Why don't I rebase on top of kvm/next along with these couple of changes
> from Pierre and send this as a v10 for you to queue.
>
> While at it, there's one other issue to be aware of -- There will also be
> small merge conflicts with a patch that just hit vfio-next, "vfio:
> de-extern-ify function prototypes" - My series already avoids adding externs
> to new prototypes, but adjacent code changes will cause a conflict with
> patches 10 and 17.
>
> Not sure what the best way to proceed there is.

You should use a branch based on vfio-next and send a Git PR to Christian
and Alex

Jason

2022-06-28 15:03:59

by Alex Williamson

[permalink] [raw]
Subject: Re: [PATCH v9 10/21] vfio/pci: introduce CONFIG_VFIO_PCI_ZDEV_KVM

On Mon, 6 Jun 2022 16:33:14 -0400
Matthew Rosato <[email protected]> wrote:

> The current contents of vfio-pci-zdev are today only useful in a KVM
> environment; let's tie everything currently under vfio-pci-zdev to
> this Kconfig statement and require KVM in this case, reducing complexity
> (e.g. symbol lookups).
>
> Signed-off-by: Matthew Rosato <[email protected]>
> ---
> drivers/vfio/pci/Kconfig | 11 +++++++++++
> drivers/vfio/pci/Makefile | 2 +-
> include/linux/vfio_pci_core.h | 2 +-
> 3 files changed, 13 insertions(+), 2 deletions(-)


Acked-by: Alex Williamson <[email protected]>


> diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
> index 4da1914425e1..f9d0c908e738 100644
> --- a/drivers/vfio/pci/Kconfig
> +++ b/drivers/vfio/pci/Kconfig
> @@ -44,6 +44,17 @@ config VFIO_PCI_IGD
> To enable Intel IGD assignment through vfio-pci, say Y.
> endif
>
> +config VFIO_PCI_ZDEV_KVM
> + bool "VFIO PCI extensions for s390x KVM passthrough"
> + depends on S390 && KVM
> + default y
> + help
> + Support s390x-specific extensions to enable support for enhancements
> + to KVM passthrough capabilities, such as interpretive execution of
> + zPCI instructions.
> +
> + To enable s390x KVM vfio-pci extensions, say Y.
> +
> source "drivers/vfio/pci/mlx5/Kconfig"
>
> source "drivers/vfio/pci/hisilicon/Kconfig"
> diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
> index 7052ebd893e0..24c524224da5 100644
> --- a/drivers/vfio/pci/Makefile
> +++ b/drivers/vfio/pci/Makefile
> @@ -1,7 +1,7 @@
> # SPDX-License-Identifier: GPL-2.0-only
>
> vfio-pci-core-y := vfio_pci_core.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
> -vfio-pci-core-$(CONFIG_S390) += vfio_pci_zdev.o
> +vfio-pci-core-$(CONFIG_VFIO_PCI_ZDEV_KVM) += vfio_pci_zdev.o
> obj-$(CONFIG_VFIO_PCI_CORE) += vfio-pci-core.o
>
> vfio-pci-y := vfio_pci.o
> diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
> index 23c176d4b073..63af2897939c 100644
> --- a/include/linux/vfio_pci_core.h
> +++ b/include/linux/vfio_pci_core.h
> @@ -206,7 +206,7 @@ static inline int vfio_pci_igd_init(struct vfio_pci_core_device *vdev)
> }
> #endif
>
> -#ifdef CONFIG_S390
> +#ifdef CONFIG_VFIO_PCI_ZDEV_KVM
> extern int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
> struct vfio_info_cap *caps);
> #else

2022-06-28 15:04:52

by Alex Williamson

[permalink] [raw]
Subject: Re: [PATCH v9 18/21] vfio-pci/zdev: add function handle to clp base capability

On Mon, 6 Jun 2022 16:33:22 -0400
Matthew Rosato <[email protected]> wrote:

> The function handle is a system-wide unique identifier for a zPCI
> device. With zPCI instruction interpretation, the host will no
> longer be executing the zPCI instructions on behalf of the guest.
> As a result, the guest needs to use the real function handle in
> order for firmware to associate the instruction with the proper
> PCI function. Let's provide that handle to the guest.
>
> Reviewed-by: Christian Borntraeger <[email protected]>
> Reviewed-by: Pierre Morel <[email protected]>
> Signed-off-by: Matthew Rosato <[email protected]>
> ---
> drivers/vfio/pci/vfio_pci_zdev.c | 5 +++--
> include/uapi/linux/vfio_zdev.h | 3 +++
> 2 files changed, 6 insertions(+), 2 deletions(-)


Acked-by: Alex Williamson <[email protected]>


> diff --git a/drivers/vfio/pci/vfio_pci_zdev.c b/drivers/vfio/pci/vfio_pci_zdev.c
> index 686f2e75e392..4f28cdd7ecd1 100644
> --- a/drivers/vfio/pci/vfio_pci_zdev.c
> +++ b/drivers/vfio/pci/vfio_pci_zdev.c
> @@ -24,14 +24,15 @@ static int zpci_base_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
> {
> struct vfio_device_info_cap_zpci_base cap = {
> .header.id = VFIO_DEVICE_INFO_CAP_ZPCI_BASE,
> - .header.version = 1,
> + .header.version = 2,
> .start_dma = zdev->start_dma,
> .end_dma = zdev->end_dma,
> .pchid = zdev->pchid,
> .vfn = zdev->vfn,
> .fmb_length = zdev->fmb_length,
> .pft = zdev->pft,
> - .gid = zdev->pfgid
> + .gid = zdev->pfgid,
> + .fh = zdev->fh
> };
>
> return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
> diff --git a/include/uapi/linux/vfio_zdev.h b/include/uapi/linux/vfio_zdev.h
> index b4309397b6b2..78c022af3d29 100644
> --- a/include/uapi/linux/vfio_zdev.h
> +++ b/include/uapi/linux/vfio_zdev.h
> @@ -29,6 +29,9 @@ struct vfio_device_info_cap_zpci_base {
> __u16 fmb_length; /* Measurement Block Length (in bytes) */
> __u8 pft; /* PCI Function Type */
> __u8 gid; /* PCI function group ID */
> + /* End of version 1 */
> + __u32 fh; /* PCI function handle */
> + /* End of version 2 */
> };
>
> /**

2022-07-08 11:45:14

by Christian Borntraeger

[permalink] [raw]
Subject: Re: [PATCH v9 00/21] KVM: s390: enable zPCI for interpretive execution


Am 06.06.22 um 22:33 schrieb Matthew Rosato:
> Enable interpretive execution of zPCI instructions + adapter interruption
> forwarding for s390x KVM vfio-pci. This is done by triggering a routine
> when the VFIO group is associated with the KVM guest, transmitting to
> firmware a special token (GISA designation) to enable that specific guest
> for interpretive execution on that zPCI device. Load/store interpreation
> enablement is then controlled by userspace (based upon whether or not a
> SHM bit is placed in the virtual function handle). Adapter Event
> Notification interpretation is controlled from userspace via a new KVM
> ioctl.
>
> By allowing intepretation of zPCI instructions and firmware delivery of
> interrupts to guests, we can reduce the frequency of guest SIE exits for
> zPCI.
>
> From the perspective of guest configuration, you passthrough zPCI devices
> in the same manner as before, with intepretation support being used by
> default if available in kernel+qemu.
>
> Will follow up with a link the most recent QEMU series.
>
> Changelog v8->v9:
> - Rebase on top of 5.19-rc1, adjust ioctl and capability defines
> - s/kzdev = 0/kzdev = NULL/ (Alex)
> - rename vfio_pci_zdev_open to vfio_pci_zdev_open_device (Jason)
> - rename vfio_pci_zdev_release to vfio_pci_zdev_close_device (Jason)
> - make vfio_pci_zdev_close_device return void, instead WARN_ON or ignore
> errors in lower level function (kvm_s390_pci_unregister_kvm) (Jason)
> - remove notifier accidentally left in struct zpci_dev + associated
> include statment (Jason)
> - Remove patch 'KVM: s390: introduce CPU feature for zPCI Interpretation'
> based on discussion in QEMU thread.
>
> Matthew Rosato (21):
> s390/sclp: detect the zPCI load/store interpretation facility
> s390/sclp: detect the AISII facility
> s390/sclp: detect the AENI facility
> s390/sclp: detect the AISI facility
> s390/airq: pass more TPI info to airq handlers
> s390/airq: allow for airq structure that uses an input vector
> s390/pci: externalize the SIC operation controls and routine
> s390/pci: stash associated GISA designation
> s390/pci: stash dtsm and maxstbl
> vfio/pci: introduce CONFIG_VFIO_PCI_ZDEV_KVM
> KVM: s390: pci: add basic kvm_zdev structure
> KVM: s390: pci: do initial setup for AEN interpretation
> KVM: s390: pci: enable host forwarding of Adapter Event Notifications
> KVM: s390: mechanism to enable guest zPCI Interpretation
> KVM: s390: pci: provide routines for enabling/disabling interrupt
> forwarding
> KVM: s390: pci: add routines to start/stop interpretive execution
> vfio-pci/zdev: add open/close device hooks
> vfio-pci/zdev: add function handle to clp base capability
> vfio-pci/zdev: different maxstbl for interpreted devices
> KVM: s390: add KVM_S390_ZPCI_OP to manage guest zPCI devices
> MAINTAINERS: additional files related kvm s390 pci passthrough
>
> Documentation/virt/kvm/api.rst | 47 +++
> MAINTAINERS | 1 +
> arch/s390/include/asm/airq.h | 7 +-
> arch/s390/include/asm/kvm_host.h | 23 ++
> arch/s390/include/asm/pci.h | 11 +
> arch/s390/include/asm/pci_clp.h | 9 +-
> arch/s390/include/asm/pci_insn.h | 29 +-
> arch/s390/include/asm/sclp.h | 4 +
> arch/s390/include/asm/tpi.h | 13 +
> arch/s390/kvm/Makefile | 1 +
> arch/s390/kvm/interrupt.c | 96 ++++-
> arch/s390/kvm/kvm-s390.c | 83 +++-
> arch/s390/kvm/kvm-s390.h | 10 +
> arch/s390/kvm/pci.c | 690 +++++++++++++++++++++++++++++++
> arch/s390/kvm/pci.h | 88 ++++
> arch/s390/pci/pci.c | 16 +
> arch/s390/pci/pci_clp.c | 7 +
> arch/s390/pci/pci_insn.c | 4 +-
> arch/s390/pci/pci_irq.c | 48 ++-
> drivers/s390/char/sclp_early.c | 4 +
> drivers/s390/cio/airq.c | 12 +-
> drivers/s390/cio/qdio_thinint.c | 6 +-
> drivers/s390/crypto/ap_bus.c | 9 +-
> drivers/s390/virtio/virtio_ccw.c | 6 +-
> drivers/vfio/pci/Kconfig | 11 +
> drivers/vfio/pci/Makefile | 2 +-
> drivers/vfio/pci/vfio_pci_core.c | 10 +-
> drivers/vfio/pci/vfio_pci_zdev.c | 35 +-
> include/linux/sched/user.h | 3 +-
> include/linux/vfio_pci_core.h | 12 +-
> include/uapi/linux/kvm.h | 31 ++
> include/uapi/linux/vfio_zdev.h | 7 +
> 32 files changed, 1279 insertions(+), 56 deletions(-)
> create mode 100644 arch/s390/kvm/pci.c
> create mode 100644 arch/s390/kvm/pci.h

So I pulled this into a topic branch and will merge that into kvms390/next. We can
merge this topic branch into vfio-next and/or s390-next when the conflicts get
to complicated.

While pulling I fixed up the numbers for the capability to

#define KVM_CAP_S390_ZPCI_OP 221

and the doc number to

4.137 KVM_S390_ZPCI_OP

to minize struggle when doing backports.