16438e307SMatthew Rosato // SPDX-License-Identifier: GPL-2.0 26438e307SMatthew Rosato /* 36438e307SMatthew Rosato * s390 kvm PCI passthrough support 46438e307SMatthew Rosato * 56438e307SMatthew Rosato * Copyright IBM Corp. 2022 66438e307SMatthew Rosato * 76438e307SMatthew Rosato * Author(s): Matthew Rosato <mjrosato@linux.ibm.com> 86438e307SMatthew Rosato */ 96438e307SMatthew Rosato 106438e307SMatthew Rosato #include <linux/kvm_host.h> 116438e307SMatthew Rosato #include <linux/pci.h> 12*98b1d33dSMatthew Rosato #include <asm/pci.h> 13*98b1d33dSMatthew Rosato #include <asm/pci_insn.h> 146438e307SMatthew Rosato #include "pci.h" 156438e307SMatthew Rosato 16*98b1d33dSMatthew Rosato struct zpci_aift *aift; 17*98b1d33dSMatthew Rosato 18*98b1d33dSMatthew Rosato static inline int __set_irq_noiib(u16 ctl, u8 isc) 19*98b1d33dSMatthew Rosato { 20*98b1d33dSMatthew Rosato union zpci_sic_iib iib = {{0}}; 21*98b1d33dSMatthew Rosato 22*98b1d33dSMatthew Rosato return zpci_set_irq_ctrl(ctl, isc, &iib); 23*98b1d33dSMatthew Rosato } 24*98b1d33dSMatthew Rosato 25*98b1d33dSMatthew Rosato void kvm_s390_pci_aen_exit(void) 26*98b1d33dSMatthew Rosato { 27*98b1d33dSMatthew Rosato unsigned long flags; 28*98b1d33dSMatthew Rosato struct kvm_zdev **gait_kzdev; 29*98b1d33dSMatthew Rosato 30*98b1d33dSMatthew Rosato lockdep_assert_held(&aift->aift_lock); 31*98b1d33dSMatthew Rosato 32*98b1d33dSMatthew Rosato /* 33*98b1d33dSMatthew Rosato * Contents of the aipb remain registered for the life of the host 34*98b1d33dSMatthew Rosato * kernel, the information preserved in zpci_aipb and zpci_aif_sbv 35*98b1d33dSMatthew Rosato * in case we insert the KVM module again later. Clear the AIFT 36*98b1d33dSMatthew Rosato * information and free anything not registered with underlying 37*98b1d33dSMatthew Rosato * firmware. 38*98b1d33dSMatthew Rosato */ 39*98b1d33dSMatthew Rosato spin_lock_irqsave(&aift->gait_lock, flags); 40*98b1d33dSMatthew Rosato gait_kzdev = aift->kzdev; 41*98b1d33dSMatthew Rosato aift->gait = NULL; 42*98b1d33dSMatthew Rosato aift->sbv = NULL; 43*98b1d33dSMatthew Rosato aift->kzdev = NULL; 44*98b1d33dSMatthew Rosato spin_unlock_irqrestore(&aift->gait_lock, flags); 45*98b1d33dSMatthew Rosato 46*98b1d33dSMatthew Rosato kfree(gait_kzdev); 47*98b1d33dSMatthew Rosato } 48*98b1d33dSMatthew Rosato 49*98b1d33dSMatthew Rosato static int zpci_setup_aipb(u8 nisc) 50*98b1d33dSMatthew Rosato { 51*98b1d33dSMatthew Rosato struct page *page; 52*98b1d33dSMatthew Rosato int size, rc; 53*98b1d33dSMatthew Rosato 54*98b1d33dSMatthew Rosato zpci_aipb = kzalloc(sizeof(union zpci_sic_iib), GFP_KERNEL); 55*98b1d33dSMatthew Rosato if (!zpci_aipb) 56*98b1d33dSMatthew Rosato return -ENOMEM; 57*98b1d33dSMatthew Rosato 58*98b1d33dSMatthew Rosato aift->sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC, 0); 59*98b1d33dSMatthew Rosato if (!aift->sbv) { 60*98b1d33dSMatthew Rosato rc = -ENOMEM; 61*98b1d33dSMatthew Rosato goto free_aipb; 62*98b1d33dSMatthew Rosato } 63*98b1d33dSMatthew Rosato zpci_aif_sbv = aift->sbv; 64*98b1d33dSMatthew Rosato size = get_order(PAGE_ALIGN(ZPCI_NR_DEVICES * 65*98b1d33dSMatthew Rosato sizeof(struct zpci_gaite))); 66*98b1d33dSMatthew Rosato page = alloc_pages(GFP_KERNEL | __GFP_ZERO, size); 67*98b1d33dSMatthew Rosato if (!page) { 68*98b1d33dSMatthew Rosato rc = -ENOMEM; 69*98b1d33dSMatthew Rosato goto free_sbv; 70*98b1d33dSMatthew Rosato } 71*98b1d33dSMatthew Rosato aift->gait = (struct zpci_gaite *)page_to_phys(page); 72*98b1d33dSMatthew Rosato 73*98b1d33dSMatthew Rosato zpci_aipb->aipb.faisb = virt_to_phys(aift->sbv->vector); 74*98b1d33dSMatthew Rosato zpci_aipb->aipb.gait = virt_to_phys(aift->gait); 75*98b1d33dSMatthew Rosato zpci_aipb->aipb.afi = nisc; 76*98b1d33dSMatthew Rosato zpci_aipb->aipb.faal = ZPCI_NR_DEVICES; 77*98b1d33dSMatthew Rosato 78*98b1d33dSMatthew Rosato /* Setup Adapter Event Notification Interpretation */ 79*98b1d33dSMatthew Rosato if (zpci_set_irq_ctrl(SIC_SET_AENI_CONTROLS, 0, zpci_aipb)) { 80*98b1d33dSMatthew Rosato rc = -EIO; 81*98b1d33dSMatthew Rosato goto free_gait; 82*98b1d33dSMatthew Rosato } 83*98b1d33dSMatthew Rosato 84*98b1d33dSMatthew Rosato return 0; 85*98b1d33dSMatthew Rosato 86*98b1d33dSMatthew Rosato free_gait: 87*98b1d33dSMatthew Rosato free_pages((unsigned long)aift->gait, size); 88*98b1d33dSMatthew Rosato free_sbv: 89*98b1d33dSMatthew Rosato airq_iv_release(aift->sbv); 90*98b1d33dSMatthew Rosato zpci_aif_sbv = NULL; 91*98b1d33dSMatthew Rosato free_aipb: 92*98b1d33dSMatthew Rosato kfree(zpci_aipb); 93*98b1d33dSMatthew Rosato zpci_aipb = NULL; 94*98b1d33dSMatthew Rosato 95*98b1d33dSMatthew Rosato return rc; 96*98b1d33dSMatthew Rosato } 97*98b1d33dSMatthew Rosato 98*98b1d33dSMatthew Rosato static int zpci_reset_aipb(u8 nisc) 99*98b1d33dSMatthew Rosato { 100*98b1d33dSMatthew Rosato /* 101*98b1d33dSMatthew Rosato * AEN registration can only happen once per system boot. If 102*98b1d33dSMatthew Rosato * an aipb already exists then AEN was already registered and 103*98b1d33dSMatthew Rosato * we can re-use the aipb contents. This can only happen if 104*98b1d33dSMatthew Rosato * the KVM module was removed and re-inserted. However, we must 105*98b1d33dSMatthew Rosato * ensure that the same forwarding ISC is used as this is assigned 106*98b1d33dSMatthew Rosato * during KVM module load. 107*98b1d33dSMatthew Rosato */ 108*98b1d33dSMatthew Rosato if (zpci_aipb->aipb.afi != nisc) 109*98b1d33dSMatthew Rosato return -EINVAL; 110*98b1d33dSMatthew Rosato 111*98b1d33dSMatthew Rosato aift->sbv = zpci_aif_sbv; 112*98b1d33dSMatthew Rosato aift->gait = (struct zpci_gaite *)zpci_aipb->aipb.gait; 113*98b1d33dSMatthew Rosato 114*98b1d33dSMatthew Rosato return 0; 115*98b1d33dSMatthew Rosato } 116*98b1d33dSMatthew Rosato 117*98b1d33dSMatthew Rosato int kvm_s390_pci_aen_init(u8 nisc) 118*98b1d33dSMatthew Rosato { 119*98b1d33dSMatthew Rosato int rc = 0; 120*98b1d33dSMatthew Rosato 121*98b1d33dSMatthew Rosato /* If already enabled for AEN, bail out now */ 122*98b1d33dSMatthew Rosato if (aift->gait || aift->sbv) 123*98b1d33dSMatthew Rosato return -EPERM; 124*98b1d33dSMatthew Rosato 125*98b1d33dSMatthew Rosato mutex_lock(&aift->aift_lock); 126*98b1d33dSMatthew Rosato aift->kzdev = kcalloc(ZPCI_NR_DEVICES, sizeof(struct kvm_zdev), 127*98b1d33dSMatthew Rosato GFP_KERNEL); 128*98b1d33dSMatthew Rosato if (!aift->kzdev) { 129*98b1d33dSMatthew Rosato rc = -ENOMEM; 130*98b1d33dSMatthew Rosato goto unlock; 131*98b1d33dSMatthew Rosato } 132*98b1d33dSMatthew Rosato 133*98b1d33dSMatthew Rosato if (!zpci_aipb) 134*98b1d33dSMatthew Rosato rc = zpci_setup_aipb(nisc); 135*98b1d33dSMatthew Rosato else 136*98b1d33dSMatthew Rosato rc = zpci_reset_aipb(nisc); 137*98b1d33dSMatthew Rosato if (rc) 138*98b1d33dSMatthew Rosato goto free_zdev; 139*98b1d33dSMatthew Rosato 140*98b1d33dSMatthew Rosato /* Enable floating IRQs */ 141*98b1d33dSMatthew Rosato if (__set_irq_noiib(SIC_IRQ_MODE_SINGLE, nisc)) { 142*98b1d33dSMatthew Rosato rc = -EIO; 143*98b1d33dSMatthew Rosato kvm_s390_pci_aen_exit(); 144*98b1d33dSMatthew Rosato } 145*98b1d33dSMatthew Rosato 146*98b1d33dSMatthew Rosato goto unlock; 147*98b1d33dSMatthew Rosato 148*98b1d33dSMatthew Rosato free_zdev: 149*98b1d33dSMatthew Rosato kfree(aift->kzdev); 150*98b1d33dSMatthew Rosato unlock: 151*98b1d33dSMatthew Rosato mutex_unlock(&aift->aift_lock); 152*98b1d33dSMatthew Rosato return rc; 153*98b1d33dSMatthew Rosato } 154*98b1d33dSMatthew Rosato 1556438e307SMatthew Rosato static int kvm_s390_pci_dev_open(struct zpci_dev *zdev) 1566438e307SMatthew Rosato { 1576438e307SMatthew Rosato struct kvm_zdev *kzdev; 1586438e307SMatthew Rosato 1596438e307SMatthew Rosato kzdev = kzalloc(sizeof(struct kvm_zdev), GFP_KERNEL); 1606438e307SMatthew Rosato if (!kzdev) 1616438e307SMatthew Rosato return -ENOMEM; 1626438e307SMatthew Rosato 1636438e307SMatthew Rosato kzdev->zdev = zdev; 1646438e307SMatthew Rosato zdev->kzdev = kzdev; 1656438e307SMatthew Rosato 1666438e307SMatthew Rosato return 0; 1676438e307SMatthew Rosato } 1686438e307SMatthew Rosato 1696438e307SMatthew Rosato static void kvm_s390_pci_dev_release(struct zpci_dev *zdev) 1706438e307SMatthew Rosato { 1716438e307SMatthew Rosato struct kvm_zdev *kzdev; 1726438e307SMatthew Rosato 1736438e307SMatthew Rosato kzdev = zdev->kzdev; 1746438e307SMatthew Rosato WARN_ON(kzdev->zdev != zdev); 1756438e307SMatthew Rosato zdev->kzdev = NULL; 1766438e307SMatthew Rosato kfree(kzdev); 1776438e307SMatthew Rosato } 178*98b1d33dSMatthew Rosato 179*98b1d33dSMatthew Rosato int kvm_s390_pci_init(void) 180*98b1d33dSMatthew Rosato { 181*98b1d33dSMatthew Rosato aift = kzalloc(sizeof(struct zpci_aift), GFP_KERNEL); 182*98b1d33dSMatthew Rosato if (!aift) 183*98b1d33dSMatthew Rosato return -ENOMEM; 184*98b1d33dSMatthew Rosato 185*98b1d33dSMatthew Rosato spin_lock_init(&aift->gait_lock); 186*98b1d33dSMatthew Rosato mutex_init(&aift->aift_lock); 187*98b1d33dSMatthew Rosato 188*98b1d33dSMatthew Rosato return 0; 189*98b1d33dSMatthew Rosato } 190*98b1d33dSMatthew Rosato 191*98b1d33dSMatthew Rosato void kvm_s390_pci_exit(void) 192*98b1d33dSMatthew Rosato { 193*98b1d33dSMatthew Rosato mutex_destroy(&aift->aift_lock); 194*98b1d33dSMatthew Rosato 195*98b1d33dSMatthew Rosato kfree(aift); 196*98b1d33dSMatthew Rosato } 197