Commit d41b5e01 authored by Christian Borntraeger's avatar Christian Borntraeger
Browse files

Merge tag 'kvm-s390-pci-5.20' into kernelorgnext

KVM: s390/pci: enable zPCI for interpretive execution

Add the necessary code in s390 base, pci and KVM to enable interpretion
of PCI pasthru.
parents 4b88b1a5 4ac34b94
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -5955,6 +5955,52 @@ KVM_PV_DUMP_CPU
  Provides encrypted dump data like register values.
  The length of the returned data is provided by uv_info.guest_cpu_stor_len.

4.137 KVM_S390_ZPCI_OP
--------------------

:Capability: KVM_CAP_S390_ZPCI_OP
:Architectures: s390
:Type: vm ioctl
:Parameters: struct kvm_s390_zpci_op (in)
:Returns: 0 on success, <0 on error

Used to manage hardware-assisted virtualization features for zPCI devices.

Parameters are specified via the following structure::

  struct kvm_s390_zpci_op {
	/* in */
	__u32 fh;		/* target device */
	__u8  op;		/* operation to perform */
	__u8  pad[3];
	union {
		/* for KVM_S390_ZPCIOP_REG_AEN */
		struct {
			__u64 ibv;	/* Guest addr of interrupt bit vector */
			__u64 sb;	/* Guest addr of summary bit */
			__u32 flags;
			__u32 noi;	/* Number of interrupts */
			__u8 isc;	/* Guest interrupt subclass */
			__u8 sbo;	/* Offset of guest summary bit vector */
			__u16 pad;
		} reg_aen;
		__u64 reserved[8];
	} u;
  };

The type of operation is specified in the "op" field.
KVM_S390_ZPCIOP_REG_AEN is used to register the VM for adapter event
notification interpretation, which will allow firmware delivery of adapter
events directly to the vm, with KVM providing a backup delivery mechanism;
KVM_S390_ZPCIOP_DEREG_AEN is used to subsequently disable interpretation of
adapter event notifications.

The target zPCI function must also be specified via the "fh" field.  For the
KVM_S390_ZPCIOP_REG_AEN operation, additional information to establish firmware
delivery must be provided via the "reg_aen" struct.

The "pad" and "reserved" fields may be used for future extensions and should be
set to 0s by userspace.

5. The kvm_run structure
========================
+1 −0
Original line number Diff line number Diff line
@@ -17453,6 +17453,7 @@ M: Eric Farman <farman@linux.ibm.com>
L:	linux-s390@vger.kernel.org
L:	kvm@vger.kernel.org
S:	Supported
F:	arch/s390/kvm/pci*
F:	drivers/vfio/pci/vfio_pci_zdev.c
F:	include/uapi/linux/vfio_zdev.h
+5 −2
Original line number Diff line number Diff line
@@ -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 */
@@ -46,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);
+23 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/kvm.h>
#include <linux/seqlock.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <asm/debug.h>
#include <asm/cpu.h>
#include <asm/fpu/api.h>
@@ -254,7 +255,10 @@ struct kvm_s390_sie_block {
#define ECB2_IEP	0x20
#define ECB2_PFMFI	0x08
#define ECB2_ESCA	0x04
#define ECB2_ZPCI_LSI	0x02
	__u8    ecb2;                   /* 0x0062 */
#define ECB3_AISI	0x20
#define ECB3_AISII	0x10
#define ECB3_DEA 0x08
#define ECB3_AES 0x04
#define ECB3_RI  0x01
@@ -759,6 +763,7 @@ struct kvm_vm_stat {
	u64 inject_pfault_done;
	u64 inject_service_signal;
	u64 inject_virtio;
	u64 aen_forward;
};

struct kvm_arch_memory_slot {
@@ -940,6 +945,7 @@ struct kvm_arch{
	int use_cmma;
	int use_pfmfi;
	int use_skf;
	int use_zpci_interp;
	int user_cpu_state_ctrl;
	int user_sigp;
	int user_stsi;
@@ -963,6 +969,8 @@ struct kvm_arch{
	DECLARE_BITMAP(idle_mask, KVM_MAX_VCPUS);
	struct kvm_s390_gisa_interrupt gisa_int;
	struct kvm_s390_pv pv;
	struct list_head kzdev_list;
	spinlock_t kzdev_list_lock;
};

#define KVM_HVA_ERR_BAD		(-1UL)
@@ -1013,4 +1021,19 @@ static inline void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}

#define __KVM_HAVE_ARCH_VM_FREE
void kvm_arch_free_vm(struct kvm *kvm);

#ifdef CONFIG_VFIO_PCI_ZDEV_KVM
int kvm_s390_pci_register_kvm(struct zpci_dev *zdev, struct kvm *kvm);
void kvm_s390_pci_unregister_kvm(struct zpci_dev *zdev);
#else
static inline int kvm_s390_pci_register_kvm(struct zpci_dev *dev,
					    struct kvm *kvm)
{
	return -EPERM;
}
static inline void kvm_s390_pci_unregister_kvm(struct zpci_dev *dev) {}
#endif

#endif
+11 −0
Original line number Diff line number Diff line
@@ -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
@@ -97,6 +98,7 @@ struct zpci_bar_struct {
};

struct s390_domain;
struct kvm_zdev;

#define ZPCI_FUNCTIONS_PER_BUS 256
struct zpci_bus {
@@ -123,11 +125,14 @@ struct zpci_dev {
	enum zpci_state state;
	u32		fid;		/* function ID, used by sclp */
	u32		fh;		/* function handle, used by insn's */
	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;
@@ -186,7 +191,10 @@ struct zpci_dev {

	struct dentry	*debugfs_dev;

	/* IOMMU and passthrough */
	struct s390_domain *s390_domain; /* s390 IOMMU domain data */
	struct kvm_zdev *kzdev;
	struct mutex kzdev_lock;
};

static inline bool zdev_enabled(struct zpci_dev *zdev)
@@ -198,6 +206,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
----------------------------------------------------------------------------- */
Loading