Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <borntraeger@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/r/20220606203325.110625-13-mjrosato@linux.ibm.com
Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>

authored by

Matthew Rosato and committed by
Christian Borntraeger
98b1d33d 6438e307

+256
+4
arch/s390/include/asm/pci.h
··· 9 9 #include <asm-generic/pci.h> 10 10 #include <asm/pci_clp.h> 11 11 #include <asm/pci_debug.h> 12 + #include <asm/pci_insn.h> 12 13 #include <asm/sclp.h> 13 14 14 15 #define PCIBIOS_MIN_IO 0x1000 ··· 204 203 extern const struct attribute_group *zpci_attr_groups[]; 205 204 extern unsigned int s390_pci_force_floating __initdata; 206 205 extern unsigned int s390_pci_no_rid; 206 + 207 + extern union zpci_sic_iib *zpci_aipb; 208 + extern struct airq_iv *zpci_aif_sbv; 207 209 208 210 /* ----------------------------------------------------------------------------- 209 211 Prototypes
+12
arch/s390/include/asm/pci_insn.h
··· 101 101 /* Set Interruption Controls Operation Controls */ 102 102 #define SIC_IRQ_MODE_ALL 0 103 103 #define SIC_IRQ_MODE_SINGLE 1 104 + #define SIC_SET_AENI_CONTROLS 2 104 105 #define SIC_IRQ_MODE_DIRECT 4 105 106 #define SIC_IRQ_MODE_D_ALL 16 106 107 #define SIC_IRQ_MODE_D_SINGLE 17 ··· 128 127 u64 : 64; 129 128 } __packed __aligned(8); 130 129 130 + /* adapter interruption parameters block */ 131 + struct zpci_aipb { 132 + u64 faisb; 133 + u64 gait; 134 + u16 : 13; 135 + u16 afi : 3; 136 + u32 : 32; 137 + u16 faal; 138 + } __packed __aligned(8); 139 + 131 140 union zpci_sic_iib { 132 141 struct zpci_diib diib; 133 142 struct zpci_cdiib cdiib; 143 + struct zpci_aipb aipb; 134 144 }; 135 145 136 146 DECLARE_STATIC_KEY_FALSE(have_mio);
+14
arch/s390/kvm/interrupt.c
··· 32 32 #include "kvm-s390.h" 33 33 #include "gaccess.h" 34 34 #include "trace-s390.h" 35 + #include "pci.h" 35 36 36 37 #define PFAULT_INIT 0x0600 37 38 #define PFAULT_DONE 0x0680 ··· 3329 3328 { 3330 3329 if (!gib) 3331 3330 return; 3331 + if (kvm_s390_pci_interp_allowed() && aift) { 3332 + mutex_lock(&aift->aift_lock); 3333 + kvm_s390_pci_aen_exit(); 3334 + mutex_unlock(&aift->aift_lock); 3335 + } 3332 3336 chsc_sgib(0); 3333 3337 unregister_adapter_interrupt(&gib_alert_irq); 3334 3338 free_page((unsigned long)gib); ··· 3369 3363 gib = NULL; 3370 3364 rc = -EIO; 3371 3365 goto out_unreg_gal; 3366 + } 3367 + 3368 + if (kvm_s390_pci_interp_allowed()) { 3369 + if (kvm_s390_pci_aen_init(nisc)) { 3370 + pr_err("Initializing AEN for PCI failed\n"); 3371 + rc = -EIO; 3372 + goto out_unreg_gal; 3373 + } 3372 3374 } 3373 3375 3374 3376 KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
+11
arch/s390/kvm/kvm-s390.c
··· 47 47 #include <asm/fpu/api.h> 48 48 #include "kvm-s390.h" 49 49 #include "gaccess.h" 50 + #include "pci.h" 50 51 51 52 #define CREATE_TRACE_POINTS 52 53 #include "trace.h" ··· 503 502 goto out; 504 503 } 505 504 505 + if (kvm_s390_pci_interp_allowed()) { 506 + rc = kvm_s390_pci_init(); 507 + if (rc) { 508 + pr_err("Unable to allocate AIFT for PCI\n"); 509 + goto out; 510 + } 511 + } 512 + 506 513 rc = kvm_s390_gib_init(GAL_ISC); 507 514 if (rc) 508 515 goto out; ··· 525 516 void kvm_arch_exit(void) 526 517 { 527 518 kvm_s390_gib_destroy(); 519 + if (kvm_s390_pci_interp_allowed()) 520 + kvm_s390_pci_exit(); 528 521 debug_unregister(kvm_s390_dbf); 529 522 debug_unregister(kvm_s390_dbf_uv); 530 523 }
+160
arch/s390/kvm/pci.c
··· 9 9 10 10 #include <linux/kvm_host.h> 11 11 #include <linux/pci.h> 12 + #include <asm/pci.h> 13 + #include <asm/pci_insn.h> 12 14 #include "pci.h" 15 + 16 + struct zpci_aift *aift; 17 + 18 + static inline int __set_irq_noiib(u16 ctl, u8 isc) 19 + { 20 + union zpci_sic_iib iib = {{0}}; 21 + 22 + return zpci_set_irq_ctrl(ctl, isc, &iib); 23 + } 24 + 25 + void kvm_s390_pci_aen_exit(void) 26 + { 27 + unsigned long flags; 28 + struct kvm_zdev **gait_kzdev; 29 + 30 + lockdep_assert_held(&aift->aift_lock); 31 + 32 + /* 33 + * Contents of the aipb remain registered for the life of the host 34 + * kernel, the information preserved in zpci_aipb and zpci_aif_sbv 35 + * in case we insert the KVM module again later. Clear the AIFT 36 + * information and free anything not registered with underlying 37 + * firmware. 38 + */ 39 + spin_lock_irqsave(&aift->gait_lock, flags); 40 + gait_kzdev = aift->kzdev; 41 + aift->gait = NULL; 42 + aift->sbv = NULL; 43 + aift->kzdev = NULL; 44 + spin_unlock_irqrestore(&aift->gait_lock, flags); 45 + 46 + kfree(gait_kzdev); 47 + } 48 + 49 + static int zpci_setup_aipb(u8 nisc) 50 + { 51 + struct page *page; 52 + int size, rc; 53 + 54 + zpci_aipb = kzalloc(sizeof(union zpci_sic_iib), GFP_KERNEL); 55 + if (!zpci_aipb) 56 + return -ENOMEM; 57 + 58 + aift->sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC, 0); 59 + if (!aift->sbv) { 60 + rc = -ENOMEM; 61 + goto free_aipb; 62 + } 63 + zpci_aif_sbv = aift->sbv; 64 + size = get_order(PAGE_ALIGN(ZPCI_NR_DEVICES * 65 + sizeof(struct zpci_gaite))); 66 + page = alloc_pages(GFP_KERNEL | __GFP_ZERO, size); 67 + if (!page) { 68 + rc = -ENOMEM; 69 + goto free_sbv; 70 + } 71 + aift->gait = (struct zpci_gaite *)page_to_phys(page); 72 + 73 + zpci_aipb->aipb.faisb = virt_to_phys(aift->sbv->vector); 74 + zpci_aipb->aipb.gait = virt_to_phys(aift->gait); 75 + zpci_aipb->aipb.afi = nisc; 76 + zpci_aipb->aipb.faal = ZPCI_NR_DEVICES; 77 + 78 + /* Setup Adapter Event Notification Interpretation */ 79 + if (zpci_set_irq_ctrl(SIC_SET_AENI_CONTROLS, 0, zpci_aipb)) { 80 + rc = -EIO; 81 + goto free_gait; 82 + } 83 + 84 + return 0; 85 + 86 + free_gait: 87 + free_pages((unsigned long)aift->gait, size); 88 + free_sbv: 89 + airq_iv_release(aift->sbv); 90 + zpci_aif_sbv = NULL; 91 + free_aipb: 92 + kfree(zpci_aipb); 93 + zpci_aipb = NULL; 94 + 95 + return rc; 96 + } 97 + 98 + static int zpci_reset_aipb(u8 nisc) 99 + { 100 + /* 101 + * AEN registration can only happen once per system boot. If 102 + * an aipb already exists then AEN was already registered and 103 + * we can re-use the aipb contents. This can only happen if 104 + * the KVM module was removed and re-inserted. However, we must 105 + * ensure that the same forwarding ISC is used as this is assigned 106 + * during KVM module load. 107 + */ 108 + if (zpci_aipb->aipb.afi != nisc) 109 + return -EINVAL; 110 + 111 + aift->sbv = zpci_aif_sbv; 112 + aift->gait = (struct zpci_gaite *)zpci_aipb->aipb.gait; 113 + 114 + return 0; 115 + } 116 + 117 + int kvm_s390_pci_aen_init(u8 nisc) 118 + { 119 + int rc = 0; 120 + 121 + /* If already enabled for AEN, bail out now */ 122 + if (aift->gait || aift->sbv) 123 + return -EPERM; 124 + 125 + mutex_lock(&aift->aift_lock); 126 + aift->kzdev = kcalloc(ZPCI_NR_DEVICES, sizeof(struct kvm_zdev), 127 + GFP_KERNEL); 128 + if (!aift->kzdev) { 129 + rc = -ENOMEM; 130 + goto unlock; 131 + } 132 + 133 + if (!zpci_aipb) 134 + rc = zpci_setup_aipb(nisc); 135 + else 136 + rc = zpci_reset_aipb(nisc); 137 + if (rc) 138 + goto free_zdev; 139 + 140 + /* Enable floating IRQs */ 141 + if (__set_irq_noiib(SIC_IRQ_MODE_SINGLE, nisc)) { 142 + rc = -EIO; 143 + kvm_s390_pci_aen_exit(); 144 + } 145 + 146 + goto unlock; 147 + 148 + free_zdev: 149 + kfree(aift->kzdev); 150 + unlock: 151 + mutex_unlock(&aift->aift_lock); 152 + return rc; 153 + } 13 154 14 155 static int kvm_s390_pci_dev_open(struct zpci_dev *zdev) 15 156 { ··· 174 33 WARN_ON(kzdev->zdev != zdev); 175 34 zdev->kzdev = NULL; 176 35 kfree(kzdev); 36 + } 37 + 38 + int kvm_s390_pci_init(void) 39 + { 40 + aift = kzalloc(sizeof(struct zpci_aift), GFP_KERNEL); 41 + if (!aift) 42 + return -ENOMEM; 43 + 44 + spin_lock_init(&aift->gait_lock); 45 + mutex_init(&aift->aift_lock); 46 + 47 + return 0; 48 + } 49 + 50 + void kvm_s390_pci_exit(void) 51 + { 52 + mutex_destroy(&aift->aift_lock); 53 + 54 + kfree(aift); 177 55 }
+49
arch/s390/kvm/pci.h
··· 12 12 13 13 #include <linux/kvm_host.h> 14 14 #include <linux/pci.h> 15 + #include <linux/mutex.h> 16 + #include <asm/airq.h> 17 + #include <asm/cpu.h> 15 18 16 19 struct kvm_zdev { 17 20 struct zpci_dev *zdev; 18 21 struct kvm *kvm; 19 22 }; 23 + 24 + struct zpci_gaite { 25 + u32 gisa; 26 + u8 gisc; 27 + u8 count; 28 + u8 reserved; 29 + u8 aisbo; 30 + u64 aisb; 31 + }; 32 + 33 + struct zpci_aift { 34 + struct zpci_gaite *gait; 35 + struct airq_iv *sbv; 36 + struct kvm_zdev **kzdev; 37 + spinlock_t gait_lock; /* Protects the gait, used during AEN forward */ 38 + struct mutex aift_lock; /* Protects the other structures in aift */ 39 + }; 40 + 41 + extern struct zpci_aift *aift; 42 + 43 + int kvm_s390_pci_aen_init(u8 nisc); 44 + void kvm_s390_pci_aen_exit(void); 45 + 46 + int kvm_s390_pci_init(void); 47 + void kvm_s390_pci_exit(void); 48 + 49 + static inline bool kvm_s390_pci_interp_allowed(void) 50 + { 51 + struct cpuid cpu_id; 52 + 53 + get_cpu_id(&cpu_id); 54 + switch (cpu_id.machine) { 55 + case 0x2817: 56 + case 0x2818: 57 + case 0x2827: 58 + case 0x2828: 59 + case 0x2964: 60 + case 0x2965: 61 + /* No SHM on certain machines */ 62 + return false; 63 + default: 64 + return (IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) && 65 + sclp.has_zpci_lsi && sclp.has_aeni && sclp.has_aisi && 66 + sclp.has_aisii); 67 + } 68 + } 20 69 21 70 #endif /* __KVM_S390_PCI_H */
+6
arch/s390/pci/pci.c
··· 61 61 62 62 static struct kmem_cache *zdev_fmb_cache; 63 63 64 + /* AEN structures that must be preserved over KVM module re-insertion */ 65 + union zpci_sic_iib *zpci_aipb; 66 + EXPORT_SYMBOL_GPL(zpci_aipb); 67 + struct airq_iv *zpci_aif_sbv; 68 + EXPORT_SYMBOL_GPL(zpci_aif_sbv); 69 + 64 70 struct zpci_dev *get_zdev_by_fid(u32 fid) 65 71 { 66 72 struct zpci_dev *tmp, *zdev = NULL;