Add a routine that will perform a shadow operation between a guest and host IOAT. A subsequent patch will invoke this in response to an 04 RPCIT instruction intercept. Signed-off-by: Matthew Rosato <mjrosato@xxxxxxxxxxxxx> --- arch/s390/include/asm/kvm_pci.h | 1 + arch/s390/kvm/pci.c | 31 ++++++++++++++++++++++++++++++- arch/s390/kvm/pci.h | 3 +++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/kvm_pci.h b/arch/s390/include/asm/kvm_pci.h index e27dbede723c..9578b5dafb45 100644 --- a/arch/s390/include/asm/kvm_pci.h +++ b/arch/s390/include/asm/kvm_pci.h @@ -25,6 +25,7 @@ struct kvm_zdev { struct zpci_fib fib; struct notifier_block nb; struct list_head entry; + u64 rpcit_count; }; int kvm_s390_pci_dev_open(struct zpci_dev *zdev); diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c index 1a8b82220b29..40d2fadbfbd5 100644 --- a/arch/s390/kvm/pci.c +++ b/arch/s390/kvm/pci.c @@ -8,6 +8,7 @@ */ #include <linux/kvm_host.h> +#include <linux/iommu.h> #include <linux/pci.h> #include <linux/vfio.h> #include <asm/kvm_pci.h> @@ -173,6 +174,30 @@ int kvm_s390_pci_aen_init(u8 nisc) return rc; } +int kvm_s390_pci_refresh_trans(struct kvm_vcpu *vcpu, unsigned long req, + unsigned long start, unsigned long size) +{ + struct kvm_zdev *kzdev; + u32 fh = req >> 32; + int rc; + + /* Make sure this is a valid device associated with this guest */ + kzdev = get_kzdev_by_fh(vcpu->kvm, fh); + if (!kzdev) + return -EINVAL; + + /* + * The KVM-managed IOMMU map operation will synchronize the associated + * guest IOAT tables with the host DMA tables. A physical address is + * not specified as it will be derived from pinned guest PTEs + */ + rc = iommu_map(kzdev->dom, start, 0, size, IOMMU_WRITE | IOMMU_READ); + + kzdev->rpcit_count++; + + return rc; +} + /* Modify PCI: Register floating adapter interruption forwarding */ static int kvm_zpci_set_airq(struct zpci_dev *zdev) { @@ -716,6 +741,8 @@ void kvm_s390_pci_clear_list(struct kvm *kvm) int kvm_s390_pci_init(void) { + int rc; + aift = kzalloc(sizeof(struct zpci_aift), GFP_KERNEL); if (!aift) return -ENOMEM; @@ -723,5 +750,7 @@ int kvm_s390_pci_init(void) spin_lock_init(&aift->gait_lock); mutex_init(&aift->aift_lock); - return 0; + rc = zpci_get_mdd(&aift->mdd); + + return rc; } diff --git a/arch/s390/kvm/pci.h b/arch/s390/kvm/pci.h index 867f04cae3a1..2cb1b27396c1 100644 --- a/arch/s390/kvm/pci.h +++ b/arch/s390/kvm/pci.h @@ -33,6 +33,7 @@ struct zpci_aift { 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 */ + u32 mdd; }; extern struct zpci_aift *aift; @@ -48,6 +49,8 @@ static inline struct kvm *kvm_s390_pci_si_to_kvm(struct zpci_aift *aift, int kvm_s390_pci_aen_init(u8 nisc); void kvm_s390_pci_aen_exit(void); +int kvm_s390_pci_refresh_trans(struct kvm_vcpu *vcpu, unsigned long req, + unsigned long start, unsigned long end); int kvm_s390_pci_zpci_start(struct kvm *kvm, struct zpci_dev *zdev); int kvm_s390_pci_zpci_stop(struct kvm *kvm, struct zpci_dev *zdev); -- 2.27.0