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> 1298b1d33dSMatthew Rosato #include <asm/pci.h> 1398b1d33dSMatthew Rosato #include <asm/pci_insn.h> 14*3c5a1b6fSMatthew Rosato #include <asm/pci_io.h> 156438e307SMatthew Rosato #include "pci.h" 166438e307SMatthew Rosato 1798b1d33dSMatthew Rosato struct zpci_aift *aift; 1898b1d33dSMatthew Rosato 1998b1d33dSMatthew Rosato static inline int __set_irq_noiib(u16 ctl, u8 isc) 2098b1d33dSMatthew Rosato { 2198b1d33dSMatthew Rosato union zpci_sic_iib iib = {{0}}; 2298b1d33dSMatthew Rosato 2398b1d33dSMatthew Rosato return zpci_set_irq_ctrl(ctl, isc, &iib); 2498b1d33dSMatthew Rosato } 2598b1d33dSMatthew Rosato 2698b1d33dSMatthew Rosato void kvm_s390_pci_aen_exit(void) 2798b1d33dSMatthew Rosato { 2898b1d33dSMatthew Rosato unsigned long flags; 2998b1d33dSMatthew Rosato struct kvm_zdev **gait_kzdev; 3098b1d33dSMatthew Rosato 3198b1d33dSMatthew Rosato lockdep_assert_held(&aift->aift_lock); 3298b1d33dSMatthew Rosato 3398b1d33dSMatthew Rosato /* 3498b1d33dSMatthew Rosato * Contents of the aipb remain registered for the life of the host 3598b1d33dSMatthew Rosato * kernel, the information preserved in zpci_aipb and zpci_aif_sbv 3698b1d33dSMatthew Rosato * in case we insert the KVM module again later. Clear the AIFT 3798b1d33dSMatthew Rosato * information and free anything not registered with underlying 3898b1d33dSMatthew Rosato * firmware. 3998b1d33dSMatthew Rosato */ 4098b1d33dSMatthew Rosato spin_lock_irqsave(&aift->gait_lock, flags); 4198b1d33dSMatthew Rosato gait_kzdev = aift->kzdev; 4298b1d33dSMatthew Rosato aift->gait = NULL; 4398b1d33dSMatthew Rosato aift->sbv = NULL; 4498b1d33dSMatthew Rosato aift->kzdev = NULL; 4598b1d33dSMatthew Rosato spin_unlock_irqrestore(&aift->gait_lock, flags); 4698b1d33dSMatthew Rosato 4798b1d33dSMatthew Rosato kfree(gait_kzdev); 4898b1d33dSMatthew Rosato } 4998b1d33dSMatthew Rosato 5098b1d33dSMatthew Rosato static int zpci_setup_aipb(u8 nisc) 5198b1d33dSMatthew Rosato { 5298b1d33dSMatthew Rosato struct page *page; 5398b1d33dSMatthew Rosato int size, rc; 5498b1d33dSMatthew Rosato 5598b1d33dSMatthew Rosato zpci_aipb = kzalloc(sizeof(union zpci_sic_iib), GFP_KERNEL); 5698b1d33dSMatthew Rosato if (!zpci_aipb) 5798b1d33dSMatthew Rosato return -ENOMEM; 5898b1d33dSMatthew Rosato 5998b1d33dSMatthew Rosato aift->sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC, 0); 6098b1d33dSMatthew Rosato if (!aift->sbv) { 6198b1d33dSMatthew Rosato rc = -ENOMEM; 6298b1d33dSMatthew Rosato goto free_aipb; 6398b1d33dSMatthew Rosato } 6498b1d33dSMatthew Rosato zpci_aif_sbv = aift->sbv; 6598b1d33dSMatthew Rosato size = get_order(PAGE_ALIGN(ZPCI_NR_DEVICES * 6698b1d33dSMatthew Rosato sizeof(struct zpci_gaite))); 6798b1d33dSMatthew Rosato page = alloc_pages(GFP_KERNEL | __GFP_ZERO, size); 6898b1d33dSMatthew Rosato if (!page) { 6998b1d33dSMatthew Rosato rc = -ENOMEM; 7098b1d33dSMatthew Rosato goto free_sbv; 7198b1d33dSMatthew Rosato } 7298b1d33dSMatthew Rosato aift->gait = (struct zpci_gaite *)page_to_phys(page); 7398b1d33dSMatthew Rosato 7498b1d33dSMatthew Rosato zpci_aipb->aipb.faisb = virt_to_phys(aift->sbv->vector); 7598b1d33dSMatthew Rosato zpci_aipb->aipb.gait = virt_to_phys(aift->gait); 7698b1d33dSMatthew Rosato zpci_aipb->aipb.afi = nisc; 7798b1d33dSMatthew Rosato zpci_aipb->aipb.faal = ZPCI_NR_DEVICES; 7898b1d33dSMatthew Rosato 7998b1d33dSMatthew Rosato /* Setup Adapter Event Notification Interpretation */ 8098b1d33dSMatthew Rosato if (zpci_set_irq_ctrl(SIC_SET_AENI_CONTROLS, 0, zpci_aipb)) { 8198b1d33dSMatthew Rosato rc = -EIO; 8298b1d33dSMatthew Rosato goto free_gait; 8398b1d33dSMatthew Rosato } 8498b1d33dSMatthew Rosato 8598b1d33dSMatthew Rosato return 0; 8698b1d33dSMatthew Rosato 8798b1d33dSMatthew Rosato free_gait: 8898b1d33dSMatthew Rosato free_pages((unsigned long)aift->gait, size); 8998b1d33dSMatthew Rosato free_sbv: 9098b1d33dSMatthew Rosato airq_iv_release(aift->sbv); 9198b1d33dSMatthew Rosato zpci_aif_sbv = NULL; 9298b1d33dSMatthew Rosato free_aipb: 9398b1d33dSMatthew Rosato kfree(zpci_aipb); 9498b1d33dSMatthew Rosato zpci_aipb = NULL; 9598b1d33dSMatthew Rosato 9698b1d33dSMatthew Rosato return rc; 9798b1d33dSMatthew Rosato } 9898b1d33dSMatthew Rosato 9998b1d33dSMatthew Rosato static int zpci_reset_aipb(u8 nisc) 10098b1d33dSMatthew Rosato { 10198b1d33dSMatthew Rosato /* 10298b1d33dSMatthew Rosato * AEN registration can only happen once per system boot. If 10398b1d33dSMatthew Rosato * an aipb already exists then AEN was already registered and 10498b1d33dSMatthew Rosato * we can re-use the aipb contents. This can only happen if 10598b1d33dSMatthew Rosato * the KVM module was removed and re-inserted. However, we must 10698b1d33dSMatthew Rosato * ensure that the same forwarding ISC is used as this is assigned 10798b1d33dSMatthew Rosato * during KVM module load. 10898b1d33dSMatthew Rosato */ 10998b1d33dSMatthew Rosato if (zpci_aipb->aipb.afi != nisc) 11098b1d33dSMatthew Rosato return -EINVAL; 11198b1d33dSMatthew Rosato 11298b1d33dSMatthew Rosato aift->sbv = zpci_aif_sbv; 11398b1d33dSMatthew Rosato aift->gait = (struct zpci_gaite *)zpci_aipb->aipb.gait; 11498b1d33dSMatthew Rosato 11598b1d33dSMatthew Rosato return 0; 11698b1d33dSMatthew Rosato } 11798b1d33dSMatthew Rosato 11898b1d33dSMatthew Rosato int kvm_s390_pci_aen_init(u8 nisc) 11998b1d33dSMatthew Rosato { 12098b1d33dSMatthew Rosato int rc = 0; 12198b1d33dSMatthew Rosato 12298b1d33dSMatthew Rosato /* If already enabled for AEN, bail out now */ 12398b1d33dSMatthew Rosato if (aift->gait || aift->sbv) 12498b1d33dSMatthew Rosato return -EPERM; 12598b1d33dSMatthew Rosato 12698b1d33dSMatthew Rosato mutex_lock(&aift->aift_lock); 12798b1d33dSMatthew Rosato aift->kzdev = kcalloc(ZPCI_NR_DEVICES, sizeof(struct kvm_zdev), 12898b1d33dSMatthew Rosato GFP_KERNEL); 12998b1d33dSMatthew Rosato if (!aift->kzdev) { 13098b1d33dSMatthew Rosato rc = -ENOMEM; 13198b1d33dSMatthew Rosato goto unlock; 13298b1d33dSMatthew Rosato } 13398b1d33dSMatthew Rosato 13498b1d33dSMatthew Rosato if (!zpci_aipb) 13598b1d33dSMatthew Rosato rc = zpci_setup_aipb(nisc); 13698b1d33dSMatthew Rosato else 13798b1d33dSMatthew Rosato rc = zpci_reset_aipb(nisc); 13898b1d33dSMatthew Rosato if (rc) 13998b1d33dSMatthew Rosato goto free_zdev; 14098b1d33dSMatthew Rosato 14198b1d33dSMatthew Rosato /* Enable floating IRQs */ 14298b1d33dSMatthew Rosato if (__set_irq_noiib(SIC_IRQ_MODE_SINGLE, nisc)) { 14398b1d33dSMatthew Rosato rc = -EIO; 14498b1d33dSMatthew Rosato kvm_s390_pci_aen_exit(); 14598b1d33dSMatthew Rosato } 14698b1d33dSMatthew Rosato 14798b1d33dSMatthew Rosato goto unlock; 14898b1d33dSMatthew Rosato 14998b1d33dSMatthew Rosato free_zdev: 15098b1d33dSMatthew Rosato kfree(aift->kzdev); 15198b1d33dSMatthew Rosato unlock: 15298b1d33dSMatthew Rosato mutex_unlock(&aift->aift_lock); 15398b1d33dSMatthew Rosato return rc; 15498b1d33dSMatthew Rosato } 15598b1d33dSMatthew Rosato 156*3c5a1b6fSMatthew Rosato /* Modify PCI: Register floating adapter interruption forwarding */ 157*3c5a1b6fSMatthew Rosato static int kvm_zpci_set_airq(struct zpci_dev *zdev) 158*3c5a1b6fSMatthew Rosato { 159*3c5a1b6fSMatthew Rosato u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT); 160*3c5a1b6fSMatthew Rosato struct zpci_fib fib = {}; 161*3c5a1b6fSMatthew Rosato u8 status; 162*3c5a1b6fSMatthew Rosato 163*3c5a1b6fSMatthew Rosato fib.fmt0.isc = zdev->kzdev->fib.fmt0.isc; 164*3c5a1b6fSMatthew Rosato fib.fmt0.sum = 1; /* enable summary notifications */ 165*3c5a1b6fSMatthew Rosato fib.fmt0.noi = airq_iv_end(zdev->aibv); 166*3c5a1b6fSMatthew Rosato fib.fmt0.aibv = virt_to_phys(zdev->aibv->vector); 167*3c5a1b6fSMatthew Rosato fib.fmt0.aibvo = 0; 168*3c5a1b6fSMatthew Rosato fib.fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); 169*3c5a1b6fSMatthew Rosato fib.fmt0.aisbo = zdev->aisb & 63; 170*3c5a1b6fSMatthew Rosato fib.gd = zdev->gisa; 171*3c5a1b6fSMatthew Rosato 172*3c5a1b6fSMatthew Rosato return zpci_mod_fc(req, &fib, &status) ? -EIO : 0; 173*3c5a1b6fSMatthew Rosato } 174*3c5a1b6fSMatthew Rosato 175*3c5a1b6fSMatthew Rosato /* Modify PCI: Unregister floating adapter interruption forwarding */ 176*3c5a1b6fSMatthew Rosato static int kvm_zpci_clear_airq(struct zpci_dev *zdev) 177*3c5a1b6fSMatthew Rosato { 178*3c5a1b6fSMatthew Rosato u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_DEREG_INT); 179*3c5a1b6fSMatthew Rosato struct zpci_fib fib = {}; 180*3c5a1b6fSMatthew Rosato u8 cc, status; 181*3c5a1b6fSMatthew Rosato 182*3c5a1b6fSMatthew Rosato fib.gd = zdev->gisa; 183*3c5a1b6fSMatthew Rosato 184*3c5a1b6fSMatthew Rosato cc = zpci_mod_fc(req, &fib, &status); 185*3c5a1b6fSMatthew Rosato if (cc == 3 || (cc == 1 && status == 24)) 186*3c5a1b6fSMatthew Rosato /* Function already gone or IRQs already deregistered. */ 187*3c5a1b6fSMatthew Rosato cc = 0; 188*3c5a1b6fSMatthew Rosato 189*3c5a1b6fSMatthew Rosato return cc ? -EIO : 0; 190*3c5a1b6fSMatthew Rosato } 191*3c5a1b6fSMatthew Rosato 192*3c5a1b6fSMatthew Rosato static inline void unaccount_mem(unsigned long nr_pages) 193*3c5a1b6fSMatthew Rosato { 194*3c5a1b6fSMatthew Rosato struct user_struct *user = get_uid(current_user()); 195*3c5a1b6fSMatthew Rosato 196*3c5a1b6fSMatthew Rosato if (user) 197*3c5a1b6fSMatthew Rosato atomic_long_sub(nr_pages, &user->locked_vm); 198*3c5a1b6fSMatthew Rosato if (current->mm) 199*3c5a1b6fSMatthew Rosato atomic64_sub(nr_pages, ¤t->mm->pinned_vm); 200*3c5a1b6fSMatthew Rosato } 201*3c5a1b6fSMatthew Rosato 202*3c5a1b6fSMatthew Rosato static inline int account_mem(unsigned long nr_pages) 203*3c5a1b6fSMatthew Rosato { 204*3c5a1b6fSMatthew Rosato struct user_struct *user = get_uid(current_user()); 205*3c5a1b6fSMatthew Rosato unsigned long page_limit, cur_pages, new_pages; 206*3c5a1b6fSMatthew Rosato 207*3c5a1b6fSMatthew Rosato page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 208*3c5a1b6fSMatthew Rosato 209*3c5a1b6fSMatthew Rosato do { 210*3c5a1b6fSMatthew Rosato cur_pages = atomic_long_read(&user->locked_vm); 211*3c5a1b6fSMatthew Rosato new_pages = cur_pages + nr_pages; 212*3c5a1b6fSMatthew Rosato if (new_pages > page_limit) 213*3c5a1b6fSMatthew Rosato return -ENOMEM; 214*3c5a1b6fSMatthew Rosato } while (atomic_long_cmpxchg(&user->locked_vm, cur_pages, 215*3c5a1b6fSMatthew Rosato new_pages) != cur_pages); 216*3c5a1b6fSMatthew Rosato 217*3c5a1b6fSMatthew Rosato atomic64_add(nr_pages, ¤t->mm->pinned_vm); 218*3c5a1b6fSMatthew Rosato 219*3c5a1b6fSMatthew Rosato return 0; 220*3c5a1b6fSMatthew Rosato } 221*3c5a1b6fSMatthew Rosato 222*3c5a1b6fSMatthew Rosato static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, 223*3c5a1b6fSMatthew Rosato bool assist) 224*3c5a1b6fSMatthew Rosato { 225*3c5a1b6fSMatthew Rosato struct page *pages[1], *aibv_page, *aisb_page = NULL; 226*3c5a1b6fSMatthew Rosato unsigned int msi_vecs, idx; 227*3c5a1b6fSMatthew Rosato struct zpci_gaite *gaite; 228*3c5a1b6fSMatthew Rosato unsigned long hva, bit; 229*3c5a1b6fSMatthew Rosato struct kvm *kvm; 230*3c5a1b6fSMatthew Rosato phys_addr_t gaddr; 231*3c5a1b6fSMatthew Rosato int rc = 0, gisc, npages, pcount = 0; 232*3c5a1b6fSMatthew Rosato 233*3c5a1b6fSMatthew Rosato /* 234*3c5a1b6fSMatthew Rosato * Interrupt forwarding is only applicable if the device is already 235*3c5a1b6fSMatthew Rosato * enabled for interpretation 236*3c5a1b6fSMatthew Rosato */ 237*3c5a1b6fSMatthew Rosato if (zdev->gisa == 0) 238*3c5a1b6fSMatthew Rosato return -EINVAL; 239*3c5a1b6fSMatthew Rosato 240*3c5a1b6fSMatthew Rosato kvm = zdev->kzdev->kvm; 241*3c5a1b6fSMatthew Rosato msi_vecs = min_t(unsigned int, fib->fmt0.noi, zdev->max_msi); 242*3c5a1b6fSMatthew Rosato 243*3c5a1b6fSMatthew Rosato /* Get the associated forwarding ISC - if invalid, return the error */ 244*3c5a1b6fSMatthew Rosato gisc = kvm_s390_gisc_register(kvm, fib->fmt0.isc); 245*3c5a1b6fSMatthew Rosato if (gisc < 0) 246*3c5a1b6fSMatthew Rosato return gisc; 247*3c5a1b6fSMatthew Rosato 248*3c5a1b6fSMatthew Rosato /* Replace AIBV address */ 249*3c5a1b6fSMatthew Rosato idx = srcu_read_lock(&kvm->srcu); 250*3c5a1b6fSMatthew Rosato hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aibv)); 251*3c5a1b6fSMatthew Rosato npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, pages); 252*3c5a1b6fSMatthew Rosato srcu_read_unlock(&kvm->srcu, idx); 253*3c5a1b6fSMatthew Rosato if (npages < 1) { 254*3c5a1b6fSMatthew Rosato rc = -EIO; 255*3c5a1b6fSMatthew Rosato goto out; 256*3c5a1b6fSMatthew Rosato } 257*3c5a1b6fSMatthew Rosato aibv_page = pages[0]; 258*3c5a1b6fSMatthew Rosato pcount++; 259*3c5a1b6fSMatthew Rosato gaddr = page_to_phys(aibv_page) + (fib->fmt0.aibv & ~PAGE_MASK); 260*3c5a1b6fSMatthew Rosato fib->fmt0.aibv = gaddr; 261*3c5a1b6fSMatthew Rosato 262*3c5a1b6fSMatthew Rosato /* Pin the guest AISB if one was specified */ 263*3c5a1b6fSMatthew Rosato if (fib->fmt0.sum == 1) { 264*3c5a1b6fSMatthew Rosato idx = srcu_read_lock(&kvm->srcu); 265*3c5a1b6fSMatthew Rosato hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aisb)); 266*3c5a1b6fSMatthew Rosato npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, 267*3c5a1b6fSMatthew Rosato pages); 268*3c5a1b6fSMatthew Rosato srcu_read_unlock(&kvm->srcu, idx); 269*3c5a1b6fSMatthew Rosato if (npages < 1) { 270*3c5a1b6fSMatthew Rosato rc = -EIO; 271*3c5a1b6fSMatthew Rosato goto unpin1; 272*3c5a1b6fSMatthew Rosato } 273*3c5a1b6fSMatthew Rosato aisb_page = pages[0]; 274*3c5a1b6fSMatthew Rosato pcount++; 275*3c5a1b6fSMatthew Rosato } 276*3c5a1b6fSMatthew Rosato 277*3c5a1b6fSMatthew Rosato /* Account for pinned pages, roll back on failure */ 278*3c5a1b6fSMatthew Rosato if (account_mem(pcount)) 279*3c5a1b6fSMatthew Rosato goto unpin2; 280*3c5a1b6fSMatthew Rosato 281*3c5a1b6fSMatthew Rosato /* AISB must be allocated before we can fill in GAITE */ 282*3c5a1b6fSMatthew Rosato mutex_lock(&aift->aift_lock); 283*3c5a1b6fSMatthew Rosato bit = airq_iv_alloc_bit(aift->sbv); 284*3c5a1b6fSMatthew Rosato if (bit == -1UL) 285*3c5a1b6fSMatthew Rosato goto unlock; 286*3c5a1b6fSMatthew Rosato zdev->aisb = bit; /* store the summary bit number */ 287*3c5a1b6fSMatthew Rosato zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | 288*3c5a1b6fSMatthew Rosato AIRQ_IV_BITLOCK | 289*3c5a1b6fSMatthew Rosato AIRQ_IV_GUESTVEC, 290*3c5a1b6fSMatthew Rosato phys_to_virt(fib->fmt0.aibv)); 291*3c5a1b6fSMatthew Rosato 292*3c5a1b6fSMatthew Rosato spin_lock_irq(&aift->gait_lock); 293*3c5a1b6fSMatthew Rosato gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb * 294*3c5a1b6fSMatthew Rosato sizeof(struct zpci_gaite)); 295*3c5a1b6fSMatthew Rosato 296*3c5a1b6fSMatthew Rosato /* If assist not requested, host will get all alerts */ 297*3c5a1b6fSMatthew Rosato if (assist) 298*3c5a1b6fSMatthew Rosato gaite->gisa = (u32)virt_to_phys(&kvm->arch.sie_page2->gisa); 299*3c5a1b6fSMatthew Rosato else 300*3c5a1b6fSMatthew Rosato gaite->gisa = 0; 301*3c5a1b6fSMatthew Rosato 302*3c5a1b6fSMatthew Rosato gaite->gisc = fib->fmt0.isc; 303*3c5a1b6fSMatthew Rosato gaite->count++; 304*3c5a1b6fSMatthew Rosato gaite->aisbo = fib->fmt0.aisbo; 305*3c5a1b6fSMatthew Rosato gaite->aisb = virt_to_phys(page_address(aisb_page) + (fib->fmt0.aisb & 306*3c5a1b6fSMatthew Rosato ~PAGE_MASK)); 307*3c5a1b6fSMatthew Rosato aift->kzdev[zdev->aisb] = zdev->kzdev; 308*3c5a1b6fSMatthew Rosato spin_unlock_irq(&aift->gait_lock); 309*3c5a1b6fSMatthew Rosato 310*3c5a1b6fSMatthew Rosato /* Update guest FIB for re-issue */ 311*3c5a1b6fSMatthew Rosato fib->fmt0.aisbo = zdev->aisb & 63; 312*3c5a1b6fSMatthew Rosato fib->fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); 313*3c5a1b6fSMatthew Rosato fib->fmt0.isc = gisc; 314*3c5a1b6fSMatthew Rosato 315*3c5a1b6fSMatthew Rosato /* Save some guest fib values in the host for later use */ 316*3c5a1b6fSMatthew Rosato zdev->kzdev->fib.fmt0.isc = fib->fmt0.isc; 317*3c5a1b6fSMatthew Rosato zdev->kzdev->fib.fmt0.aibv = fib->fmt0.aibv; 318*3c5a1b6fSMatthew Rosato mutex_unlock(&aift->aift_lock); 319*3c5a1b6fSMatthew Rosato 320*3c5a1b6fSMatthew Rosato /* Issue the clp to setup the irq now */ 321*3c5a1b6fSMatthew Rosato rc = kvm_zpci_set_airq(zdev); 322*3c5a1b6fSMatthew Rosato return rc; 323*3c5a1b6fSMatthew Rosato 324*3c5a1b6fSMatthew Rosato unlock: 325*3c5a1b6fSMatthew Rosato mutex_unlock(&aift->aift_lock); 326*3c5a1b6fSMatthew Rosato unpin2: 327*3c5a1b6fSMatthew Rosato if (fib->fmt0.sum == 1) 328*3c5a1b6fSMatthew Rosato unpin_user_page(aisb_page); 329*3c5a1b6fSMatthew Rosato unpin1: 330*3c5a1b6fSMatthew Rosato unpin_user_page(aibv_page); 331*3c5a1b6fSMatthew Rosato out: 332*3c5a1b6fSMatthew Rosato return rc; 333*3c5a1b6fSMatthew Rosato } 334*3c5a1b6fSMatthew Rosato 335*3c5a1b6fSMatthew Rosato static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force) 336*3c5a1b6fSMatthew Rosato { 337*3c5a1b6fSMatthew Rosato struct kvm_zdev *kzdev = zdev->kzdev; 338*3c5a1b6fSMatthew Rosato struct zpci_gaite *gaite; 339*3c5a1b6fSMatthew Rosato struct page *vpage = NULL, *spage = NULL; 340*3c5a1b6fSMatthew Rosato int rc, pcount = 0; 341*3c5a1b6fSMatthew Rosato u8 isc; 342*3c5a1b6fSMatthew Rosato 343*3c5a1b6fSMatthew Rosato if (zdev->gisa == 0) 344*3c5a1b6fSMatthew Rosato return -EINVAL; 345*3c5a1b6fSMatthew Rosato 346*3c5a1b6fSMatthew Rosato mutex_lock(&aift->aift_lock); 347*3c5a1b6fSMatthew Rosato 348*3c5a1b6fSMatthew Rosato /* 349*3c5a1b6fSMatthew Rosato * If the clear fails due to an error, leave now unless we know this 350*3c5a1b6fSMatthew Rosato * device is about to go away (force) -- In that case clear the GAITE 351*3c5a1b6fSMatthew Rosato * regardless. 352*3c5a1b6fSMatthew Rosato */ 353*3c5a1b6fSMatthew Rosato rc = kvm_zpci_clear_airq(zdev); 354*3c5a1b6fSMatthew Rosato if (rc && !force) 355*3c5a1b6fSMatthew Rosato goto out; 356*3c5a1b6fSMatthew Rosato 357*3c5a1b6fSMatthew Rosato if (zdev->kzdev->fib.fmt0.aibv == 0) 358*3c5a1b6fSMatthew Rosato goto out; 359*3c5a1b6fSMatthew Rosato spin_lock_irq(&aift->gait_lock); 360*3c5a1b6fSMatthew Rosato gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb * 361*3c5a1b6fSMatthew Rosato sizeof(struct zpci_gaite)); 362*3c5a1b6fSMatthew Rosato isc = gaite->gisc; 363*3c5a1b6fSMatthew Rosato gaite->count--; 364*3c5a1b6fSMatthew Rosato if (gaite->count == 0) { 365*3c5a1b6fSMatthew Rosato /* Release guest AIBV and AISB */ 366*3c5a1b6fSMatthew Rosato vpage = phys_to_page(kzdev->fib.fmt0.aibv); 367*3c5a1b6fSMatthew Rosato if (gaite->aisb != 0) 368*3c5a1b6fSMatthew Rosato spage = phys_to_page(gaite->aisb); 369*3c5a1b6fSMatthew Rosato /* Clear the GAIT entry */ 370*3c5a1b6fSMatthew Rosato gaite->aisb = 0; 371*3c5a1b6fSMatthew Rosato gaite->gisc = 0; 372*3c5a1b6fSMatthew Rosato gaite->aisbo = 0; 373*3c5a1b6fSMatthew Rosato gaite->gisa = 0; 374*3c5a1b6fSMatthew Rosato aift->kzdev[zdev->aisb] = 0; 375*3c5a1b6fSMatthew Rosato /* Clear zdev info */ 376*3c5a1b6fSMatthew Rosato airq_iv_free_bit(aift->sbv, zdev->aisb); 377*3c5a1b6fSMatthew Rosato airq_iv_release(zdev->aibv); 378*3c5a1b6fSMatthew Rosato zdev->aisb = 0; 379*3c5a1b6fSMatthew Rosato zdev->aibv = NULL; 380*3c5a1b6fSMatthew Rosato } 381*3c5a1b6fSMatthew Rosato spin_unlock_irq(&aift->gait_lock); 382*3c5a1b6fSMatthew Rosato kvm_s390_gisc_unregister(kzdev->kvm, isc); 383*3c5a1b6fSMatthew Rosato kzdev->fib.fmt0.isc = 0; 384*3c5a1b6fSMatthew Rosato kzdev->fib.fmt0.aibv = 0; 385*3c5a1b6fSMatthew Rosato 386*3c5a1b6fSMatthew Rosato if (vpage) { 387*3c5a1b6fSMatthew Rosato unpin_user_page(vpage); 388*3c5a1b6fSMatthew Rosato pcount++; 389*3c5a1b6fSMatthew Rosato } 390*3c5a1b6fSMatthew Rosato if (spage) { 391*3c5a1b6fSMatthew Rosato unpin_user_page(spage); 392*3c5a1b6fSMatthew Rosato pcount++; 393*3c5a1b6fSMatthew Rosato } 394*3c5a1b6fSMatthew Rosato if (pcount > 0) 395*3c5a1b6fSMatthew Rosato unaccount_mem(pcount); 396*3c5a1b6fSMatthew Rosato out: 397*3c5a1b6fSMatthew Rosato mutex_unlock(&aift->aift_lock); 398*3c5a1b6fSMatthew Rosato 399*3c5a1b6fSMatthew Rosato return rc; 400*3c5a1b6fSMatthew Rosato } 401*3c5a1b6fSMatthew Rosato 4026438e307SMatthew Rosato static int kvm_s390_pci_dev_open(struct zpci_dev *zdev) 4036438e307SMatthew Rosato { 4046438e307SMatthew Rosato struct kvm_zdev *kzdev; 4056438e307SMatthew Rosato 4066438e307SMatthew Rosato kzdev = kzalloc(sizeof(struct kvm_zdev), GFP_KERNEL); 4076438e307SMatthew Rosato if (!kzdev) 4086438e307SMatthew Rosato return -ENOMEM; 4096438e307SMatthew Rosato 4106438e307SMatthew Rosato kzdev->zdev = zdev; 4116438e307SMatthew Rosato zdev->kzdev = kzdev; 4126438e307SMatthew Rosato 4136438e307SMatthew Rosato return 0; 4146438e307SMatthew Rosato } 4156438e307SMatthew Rosato 4166438e307SMatthew Rosato static void kvm_s390_pci_dev_release(struct zpci_dev *zdev) 4176438e307SMatthew Rosato { 4186438e307SMatthew Rosato struct kvm_zdev *kzdev; 4196438e307SMatthew Rosato 4206438e307SMatthew Rosato kzdev = zdev->kzdev; 4216438e307SMatthew Rosato WARN_ON(kzdev->zdev != zdev); 4226438e307SMatthew Rosato zdev->kzdev = NULL; 4236438e307SMatthew Rosato kfree(kzdev); 4246438e307SMatthew Rosato } 42598b1d33dSMatthew Rosato 42698b1d33dSMatthew Rosato int kvm_s390_pci_init(void) 42798b1d33dSMatthew Rosato { 42898b1d33dSMatthew Rosato aift = kzalloc(sizeof(struct zpci_aift), GFP_KERNEL); 42998b1d33dSMatthew Rosato if (!aift) 43098b1d33dSMatthew Rosato return -ENOMEM; 43198b1d33dSMatthew Rosato 43298b1d33dSMatthew Rosato spin_lock_init(&aift->gait_lock); 43398b1d33dSMatthew Rosato mutex_init(&aift->aift_lock); 43498b1d33dSMatthew Rosato 43598b1d33dSMatthew Rosato return 0; 43698b1d33dSMatthew Rosato } 43798b1d33dSMatthew Rosato 43898b1d33dSMatthew Rosato void kvm_s390_pci_exit(void) 43998b1d33dSMatthew Rosato { 44098b1d33dSMatthew Rosato mutex_destroy(&aift->aift_lock); 44198b1d33dSMatthew Rosato 44298b1d33dSMatthew Rosato kfree(aift); 44398b1d33dSMatthew Rosato } 444