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> 143c5a1b6fSMatthew Rosato #include <asm/pci_io.h> 1509340b2fSMatthew Rosato #include <asm/sclp.h> 166438e307SMatthew Rosato #include "pci.h" 1709340b2fSMatthew Rosato #include "kvm-s390.h" 186438e307SMatthew Rosato 1998b1d33dSMatthew Rosato struct zpci_aift *aift; 2098b1d33dSMatthew Rosato 2198b1d33dSMatthew Rosato static inline int __set_irq_noiib(u16 ctl, u8 isc) 2298b1d33dSMatthew Rosato { 2398b1d33dSMatthew Rosato union zpci_sic_iib iib = {{0}}; 2498b1d33dSMatthew Rosato 2598b1d33dSMatthew Rosato return zpci_set_irq_ctrl(ctl, isc, &iib); 2698b1d33dSMatthew Rosato } 2798b1d33dSMatthew Rosato 2898b1d33dSMatthew Rosato void kvm_s390_pci_aen_exit(void) 2998b1d33dSMatthew Rosato { 3098b1d33dSMatthew Rosato unsigned long flags; 3198b1d33dSMatthew Rosato struct kvm_zdev **gait_kzdev; 3298b1d33dSMatthew Rosato 3398b1d33dSMatthew Rosato lockdep_assert_held(&aift->aift_lock); 3498b1d33dSMatthew Rosato 3598b1d33dSMatthew Rosato /* 3698b1d33dSMatthew Rosato * Contents of the aipb remain registered for the life of the host 3798b1d33dSMatthew Rosato * kernel, the information preserved in zpci_aipb and zpci_aif_sbv 3898b1d33dSMatthew Rosato * in case we insert the KVM module again later. Clear the AIFT 3998b1d33dSMatthew Rosato * information and free anything not registered with underlying 4098b1d33dSMatthew Rosato * firmware. 4198b1d33dSMatthew Rosato */ 4298b1d33dSMatthew Rosato spin_lock_irqsave(&aift->gait_lock, flags); 4398b1d33dSMatthew Rosato gait_kzdev = aift->kzdev; 4498b1d33dSMatthew Rosato aift->gait = NULL; 4598b1d33dSMatthew Rosato aift->sbv = NULL; 4698b1d33dSMatthew Rosato aift->kzdev = NULL; 4798b1d33dSMatthew Rosato spin_unlock_irqrestore(&aift->gait_lock, flags); 4898b1d33dSMatthew Rosato 4998b1d33dSMatthew Rosato kfree(gait_kzdev); 5098b1d33dSMatthew Rosato } 5198b1d33dSMatthew Rosato 5298b1d33dSMatthew Rosato static int zpci_setup_aipb(u8 nisc) 5398b1d33dSMatthew Rosato { 5498b1d33dSMatthew Rosato struct page *page; 5598b1d33dSMatthew Rosato int size, rc; 5698b1d33dSMatthew Rosato 5798b1d33dSMatthew Rosato zpci_aipb = kzalloc(sizeof(union zpci_sic_iib), GFP_KERNEL); 5898b1d33dSMatthew Rosato if (!zpci_aipb) 5998b1d33dSMatthew Rosato return -ENOMEM; 6098b1d33dSMatthew Rosato 61e8c924a4SMatthew Rosato aift->sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC, NULL); 6298b1d33dSMatthew Rosato if (!aift->sbv) { 6398b1d33dSMatthew Rosato rc = -ENOMEM; 6498b1d33dSMatthew Rosato goto free_aipb; 6598b1d33dSMatthew Rosato } 6698b1d33dSMatthew Rosato zpci_aif_sbv = aift->sbv; 6798b1d33dSMatthew Rosato size = get_order(PAGE_ALIGN(ZPCI_NR_DEVICES * 6898b1d33dSMatthew Rosato sizeof(struct zpci_gaite))); 6998b1d33dSMatthew Rosato page = alloc_pages(GFP_KERNEL | __GFP_ZERO, size); 7098b1d33dSMatthew Rosato if (!page) { 7198b1d33dSMatthew Rosato rc = -ENOMEM; 7298b1d33dSMatthew Rosato goto free_sbv; 7398b1d33dSMatthew Rosato } 74*70ba8faeSMatthew Rosato aift->gait = (struct zpci_gaite *)page_to_virt(page); 7598b1d33dSMatthew Rosato 7698b1d33dSMatthew Rosato zpci_aipb->aipb.faisb = virt_to_phys(aift->sbv->vector); 7798b1d33dSMatthew Rosato zpci_aipb->aipb.gait = virt_to_phys(aift->gait); 7898b1d33dSMatthew Rosato zpci_aipb->aipb.afi = nisc; 7998b1d33dSMatthew Rosato zpci_aipb->aipb.faal = ZPCI_NR_DEVICES; 8098b1d33dSMatthew Rosato 8198b1d33dSMatthew Rosato /* Setup Adapter Event Notification Interpretation */ 8298b1d33dSMatthew Rosato if (zpci_set_irq_ctrl(SIC_SET_AENI_CONTROLS, 0, zpci_aipb)) { 8398b1d33dSMatthew Rosato rc = -EIO; 8498b1d33dSMatthew Rosato goto free_gait; 8598b1d33dSMatthew Rosato } 8698b1d33dSMatthew Rosato 8798b1d33dSMatthew Rosato return 0; 8898b1d33dSMatthew Rosato 8998b1d33dSMatthew Rosato free_gait: 9098b1d33dSMatthew Rosato free_pages((unsigned long)aift->gait, size); 9198b1d33dSMatthew Rosato free_sbv: 9298b1d33dSMatthew Rosato airq_iv_release(aift->sbv); 9398b1d33dSMatthew Rosato zpci_aif_sbv = NULL; 9498b1d33dSMatthew Rosato free_aipb: 9598b1d33dSMatthew Rosato kfree(zpci_aipb); 9698b1d33dSMatthew Rosato zpci_aipb = NULL; 9798b1d33dSMatthew Rosato 9898b1d33dSMatthew Rosato return rc; 9998b1d33dSMatthew Rosato } 10098b1d33dSMatthew Rosato 10198b1d33dSMatthew Rosato static int zpci_reset_aipb(u8 nisc) 10298b1d33dSMatthew Rosato { 10398b1d33dSMatthew Rosato /* 10498b1d33dSMatthew Rosato * AEN registration can only happen once per system boot. If 10598b1d33dSMatthew Rosato * an aipb already exists then AEN was already registered and 10698b1d33dSMatthew Rosato * we can re-use the aipb contents. This can only happen if 10798b1d33dSMatthew Rosato * the KVM module was removed and re-inserted. However, we must 10898b1d33dSMatthew Rosato * ensure that the same forwarding ISC is used as this is assigned 10998b1d33dSMatthew Rosato * during KVM module load. 11098b1d33dSMatthew Rosato */ 11198b1d33dSMatthew Rosato if (zpci_aipb->aipb.afi != nisc) 11298b1d33dSMatthew Rosato return -EINVAL; 11398b1d33dSMatthew Rosato 11498b1d33dSMatthew Rosato aift->sbv = zpci_aif_sbv; 11598b1d33dSMatthew Rosato aift->gait = (struct zpci_gaite *)zpci_aipb->aipb.gait; 11698b1d33dSMatthew Rosato 11798b1d33dSMatthew Rosato return 0; 11898b1d33dSMatthew Rosato } 11998b1d33dSMatthew Rosato 12098b1d33dSMatthew Rosato int kvm_s390_pci_aen_init(u8 nisc) 12198b1d33dSMatthew Rosato { 12298b1d33dSMatthew Rosato int rc = 0; 12398b1d33dSMatthew Rosato 12498b1d33dSMatthew Rosato /* If already enabled for AEN, bail out now */ 12598b1d33dSMatthew Rosato if (aift->gait || aift->sbv) 12698b1d33dSMatthew Rosato return -EPERM; 12798b1d33dSMatthew Rosato 12898b1d33dSMatthew Rosato mutex_lock(&aift->aift_lock); 12998b1d33dSMatthew Rosato aift->kzdev = kcalloc(ZPCI_NR_DEVICES, sizeof(struct kvm_zdev), 13098b1d33dSMatthew Rosato GFP_KERNEL); 13198b1d33dSMatthew Rosato if (!aift->kzdev) { 13298b1d33dSMatthew Rosato rc = -ENOMEM; 13398b1d33dSMatthew Rosato goto unlock; 13498b1d33dSMatthew Rosato } 13598b1d33dSMatthew Rosato 13698b1d33dSMatthew Rosato if (!zpci_aipb) 13798b1d33dSMatthew Rosato rc = zpci_setup_aipb(nisc); 13898b1d33dSMatthew Rosato else 13998b1d33dSMatthew Rosato rc = zpci_reset_aipb(nisc); 14098b1d33dSMatthew Rosato if (rc) 14198b1d33dSMatthew Rosato goto free_zdev; 14298b1d33dSMatthew Rosato 14398b1d33dSMatthew Rosato /* Enable floating IRQs */ 14498b1d33dSMatthew Rosato if (__set_irq_noiib(SIC_IRQ_MODE_SINGLE, nisc)) { 14598b1d33dSMatthew Rosato rc = -EIO; 14698b1d33dSMatthew Rosato kvm_s390_pci_aen_exit(); 14798b1d33dSMatthew Rosato } 14898b1d33dSMatthew Rosato 14998b1d33dSMatthew Rosato goto unlock; 15098b1d33dSMatthew Rosato 15198b1d33dSMatthew Rosato free_zdev: 15298b1d33dSMatthew Rosato kfree(aift->kzdev); 15398b1d33dSMatthew Rosato unlock: 15498b1d33dSMatthew Rosato mutex_unlock(&aift->aift_lock); 15598b1d33dSMatthew Rosato return rc; 15698b1d33dSMatthew Rosato } 15798b1d33dSMatthew Rosato 1583c5a1b6fSMatthew Rosato /* Modify PCI: Register floating adapter interruption forwarding */ 1593c5a1b6fSMatthew Rosato static int kvm_zpci_set_airq(struct zpci_dev *zdev) 1603c5a1b6fSMatthew Rosato { 1613c5a1b6fSMatthew Rosato u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT); 1623c5a1b6fSMatthew Rosato struct zpci_fib fib = {}; 1633c5a1b6fSMatthew Rosato u8 status; 1643c5a1b6fSMatthew Rosato 1653c5a1b6fSMatthew Rosato fib.fmt0.isc = zdev->kzdev->fib.fmt0.isc; 1663c5a1b6fSMatthew Rosato fib.fmt0.sum = 1; /* enable summary notifications */ 1673c5a1b6fSMatthew Rosato fib.fmt0.noi = airq_iv_end(zdev->aibv); 1683c5a1b6fSMatthew Rosato fib.fmt0.aibv = virt_to_phys(zdev->aibv->vector); 1693c5a1b6fSMatthew Rosato fib.fmt0.aibvo = 0; 1703c5a1b6fSMatthew Rosato fib.fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); 1713c5a1b6fSMatthew Rosato fib.fmt0.aisbo = zdev->aisb & 63; 1723c5a1b6fSMatthew Rosato fib.gd = zdev->gisa; 1733c5a1b6fSMatthew Rosato 1743c5a1b6fSMatthew Rosato return zpci_mod_fc(req, &fib, &status) ? -EIO : 0; 1753c5a1b6fSMatthew Rosato } 1763c5a1b6fSMatthew Rosato 1773c5a1b6fSMatthew Rosato /* Modify PCI: Unregister floating adapter interruption forwarding */ 1783c5a1b6fSMatthew Rosato static int kvm_zpci_clear_airq(struct zpci_dev *zdev) 1793c5a1b6fSMatthew Rosato { 1803c5a1b6fSMatthew Rosato u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_DEREG_INT); 1813c5a1b6fSMatthew Rosato struct zpci_fib fib = {}; 1823c5a1b6fSMatthew Rosato u8 cc, status; 1833c5a1b6fSMatthew Rosato 1843c5a1b6fSMatthew Rosato fib.gd = zdev->gisa; 1853c5a1b6fSMatthew Rosato 1863c5a1b6fSMatthew Rosato cc = zpci_mod_fc(req, &fib, &status); 1873c5a1b6fSMatthew Rosato if (cc == 3 || (cc == 1 && status == 24)) 1883c5a1b6fSMatthew Rosato /* Function already gone or IRQs already deregistered. */ 1893c5a1b6fSMatthew Rosato cc = 0; 1903c5a1b6fSMatthew Rosato 1913c5a1b6fSMatthew Rosato return cc ? -EIO : 0; 1923c5a1b6fSMatthew Rosato } 1933c5a1b6fSMatthew Rosato 1943c5a1b6fSMatthew Rosato static inline void unaccount_mem(unsigned long nr_pages) 1953c5a1b6fSMatthew Rosato { 1963c5a1b6fSMatthew Rosato struct user_struct *user = get_uid(current_user()); 1973c5a1b6fSMatthew Rosato 1983c5a1b6fSMatthew Rosato if (user) 1993c5a1b6fSMatthew Rosato atomic_long_sub(nr_pages, &user->locked_vm); 2003c5a1b6fSMatthew Rosato if (current->mm) 2013c5a1b6fSMatthew Rosato atomic64_sub(nr_pages, ¤t->mm->pinned_vm); 2023c5a1b6fSMatthew Rosato } 2033c5a1b6fSMatthew Rosato 2043c5a1b6fSMatthew Rosato static inline int account_mem(unsigned long nr_pages) 2053c5a1b6fSMatthew Rosato { 2063c5a1b6fSMatthew Rosato struct user_struct *user = get_uid(current_user()); 2073c5a1b6fSMatthew Rosato unsigned long page_limit, cur_pages, new_pages; 2083c5a1b6fSMatthew Rosato 2093c5a1b6fSMatthew Rosato page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 2103c5a1b6fSMatthew Rosato 2113c5a1b6fSMatthew Rosato do { 2123c5a1b6fSMatthew Rosato cur_pages = atomic_long_read(&user->locked_vm); 2133c5a1b6fSMatthew Rosato new_pages = cur_pages + nr_pages; 2143c5a1b6fSMatthew Rosato if (new_pages > page_limit) 2153c5a1b6fSMatthew Rosato return -ENOMEM; 2163c5a1b6fSMatthew Rosato } while (atomic_long_cmpxchg(&user->locked_vm, cur_pages, 2173c5a1b6fSMatthew Rosato new_pages) != cur_pages); 2183c5a1b6fSMatthew Rosato 2193c5a1b6fSMatthew Rosato atomic64_add(nr_pages, ¤t->mm->pinned_vm); 2203c5a1b6fSMatthew Rosato 2213c5a1b6fSMatthew Rosato return 0; 2223c5a1b6fSMatthew Rosato } 2233c5a1b6fSMatthew Rosato 2243c5a1b6fSMatthew Rosato static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, 2253c5a1b6fSMatthew Rosato bool assist) 2263c5a1b6fSMatthew Rosato { 2273c5a1b6fSMatthew Rosato struct page *pages[1], *aibv_page, *aisb_page = NULL; 2283c5a1b6fSMatthew Rosato unsigned int msi_vecs, idx; 2293c5a1b6fSMatthew Rosato struct zpci_gaite *gaite; 2303c5a1b6fSMatthew Rosato unsigned long hva, bit; 2313c5a1b6fSMatthew Rosato struct kvm *kvm; 2323c5a1b6fSMatthew Rosato phys_addr_t gaddr; 2333c5a1b6fSMatthew Rosato int rc = 0, gisc, npages, pcount = 0; 2343c5a1b6fSMatthew Rosato 2353c5a1b6fSMatthew Rosato /* 2363c5a1b6fSMatthew Rosato * Interrupt forwarding is only applicable if the device is already 2373c5a1b6fSMatthew Rosato * enabled for interpretation 2383c5a1b6fSMatthew Rosato */ 2393c5a1b6fSMatthew Rosato if (zdev->gisa == 0) 2403c5a1b6fSMatthew Rosato return -EINVAL; 2413c5a1b6fSMatthew Rosato 2423c5a1b6fSMatthew Rosato kvm = zdev->kzdev->kvm; 2433c5a1b6fSMatthew Rosato msi_vecs = min_t(unsigned int, fib->fmt0.noi, zdev->max_msi); 2443c5a1b6fSMatthew Rosato 2453c5a1b6fSMatthew Rosato /* Get the associated forwarding ISC - if invalid, return the error */ 2463c5a1b6fSMatthew Rosato gisc = kvm_s390_gisc_register(kvm, fib->fmt0.isc); 2473c5a1b6fSMatthew Rosato if (gisc < 0) 2483c5a1b6fSMatthew Rosato return gisc; 2493c5a1b6fSMatthew Rosato 2503c5a1b6fSMatthew Rosato /* Replace AIBV address */ 2513c5a1b6fSMatthew Rosato idx = srcu_read_lock(&kvm->srcu); 2523c5a1b6fSMatthew Rosato hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aibv)); 2533c5a1b6fSMatthew Rosato npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, pages); 2543c5a1b6fSMatthew Rosato srcu_read_unlock(&kvm->srcu, idx); 2553c5a1b6fSMatthew Rosato if (npages < 1) { 2563c5a1b6fSMatthew Rosato rc = -EIO; 2573c5a1b6fSMatthew Rosato goto out; 2583c5a1b6fSMatthew Rosato } 2593c5a1b6fSMatthew Rosato aibv_page = pages[0]; 2603c5a1b6fSMatthew Rosato pcount++; 2613c5a1b6fSMatthew Rosato gaddr = page_to_phys(aibv_page) + (fib->fmt0.aibv & ~PAGE_MASK); 2623c5a1b6fSMatthew Rosato fib->fmt0.aibv = gaddr; 2633c5a1b6fSMatthew Rosato 2643c5a1b6fSMatthew Rosato /* Pin the guest AISB if one was specified */ 2653c5a1b6fSMatthew Rosato if (fib->fmt0.sum == 1) { 2663c5a1b6fSMatthew Rosato idx = srcu_read_lock(&kvm->srcu); 2673c5a1b6fSMatthew Rosato hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aisb)); 2683c5a1b6fSMatthew Rosato npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, 2693c5a1b6fSMatthew Rosato pages); 2703c5a1b6fSMatthew Rosato srcu_read_unlock(&kvm->srcu, idx); 2713c5a1b6fSMatthew Rosato if (npages < 1) { 2723c5a1b6fSMatthew Rosato rc = -EIO; 2733c5a1b6fSMatthew Rosato goto unpin1; 2743c5a1b6fSMatthew Rosato } 2753c5a1b6fSMatthew Rosato aisb_page = pages[0]; 2763c5a1b6fSMatthew Rosato pcount++; 2773c5a1b6fSMatthew Rosato } 2783c5a1b6fSMatthew Rosato 2793c5a1b6fSMatthew Rosato /* Account for pinned pages, roll back on failure */ 2803c5a1b6fSMatthew Rosato if (account_mem(pcount)) 2813c5a1b6fSMatthew Rosato goto unpin2; 2823c5a1b6fSMatthew Rosato 2833c5a1b6fSMatthew Rosato /* AISB must be allocated before we can fill in GAITE */ 2843c5a1b6fSMatthew Rosato mutex_lock(&aift->aift_lock); 2853c5a1b6fSMatthew Rosato bit = airq_iv_alloc_bit(aift->sbv); 2863c5a1b6fSMatthew Rosato if (bit == -1UL) 2873c5a1b6fSMatthew Rosato goto unlock; 2883c5a1b6fSMatthew Rosato zdev->aisb = bit; /* store the summary bit number */ 2893c5a1b6fSMatthew Rosato zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | 2903c5a1b6fSMatthew Rosato AIRQ_IV_BITLOCK | 2913c5a1b6fSMatthew Rosato AIRQ_IV_GUESTVEC, 2923c5a1b6fSMatthew Rosato phys_to_virt(fib->fmt0.aibv)); 2933c5a1b6fSMatthew Rosato 2943c5a1b6fSMatthew Rosato spin_lock_irq(&aift->gait_lock); 2953c5a1b6fSMatthew Rosato gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb * 2963c5a1b6fSMatthew Rosato sizeof(struct zpci_gaite)); 2973c5a1b6fSMatthew Rosato 2983c5a1b6fSMatthew Rosato /* If assist not requested, host will get all alerts */ 2993c5a1b6fSMatthew Rosato if (assist) 3003c5a1b6fSMatthew Rosato gaite->gisa = (u32)virt_to_phys(&kvm->arch.sie_page2->gisa); 3013c5a1b6fSMatthew Rosato else 3023c5a1b6fSMatthew Rosato gaite->gisa = 0; 3033c5a1b6fSMatthew Rosato 3043c5a1b6fSMatthew Rosato gaite->gisc = fib->fmt0.isc; 3053c5a1b6fSMatthew Rosato gaite->count++; 3063c5a1b6fSMatthew Rosato gaite->aisbo = fib->fmt0.aisbo; 3073c5a1b6fSMatthew Rosato gaite->aisb = virt_to_phys(page_address(aisb_page) + (fib->fmt0.aisb & 3083c5a1b6fSMatthew Rosato ~PAGE_MASK)); 3093c5a1b6fSMatthew Rosato aift->kzdev[zdev->aisb] = zdev->kzdev; 3103c5a1b6fSMatthew Rosato spin_unlock_irq(&aift->gait_lock); 3113c5a1b6fSMatthew Rosato 3123c5a1b6fSMatthew Rosato /* Update guest FIB for re-issue */ 3133c5a1b6fSMatthew Rosato fib->fmt0.aisbo = zdev->aisb & 63; 3143c5a1b6fSMatthew Rosato fib->fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8); 3153c5a1b6fSMatthew Rosato fib->fmt0.isc = gisc; 3163c5a1b6fSMatthew Rosato 3173c5a1b6fSMatthew Rosato /* Save some guest fib values in the host for later use */ 3183c5a1b6fSMatthew Rosato zdev->kzdev->fib.fmt0.isc = fib->fmt0.isc; 3193c5a1b6fSMatthew Rosato zdev->kzdev->fib.fmt0.aibv = fib->fmt0.aibv; 3203c5a1b6fSMatthew Rosato mutex_unlock(&aift->aift_lock); 3213c5a1b6fSMatthew Rosato 3223c5a1b6fSMatthew Rosato /* Issue the clp to setup the irq now */ 3233c5a1b6fSMatthew Rosato rc = kvm_zpci_set_airq(zdev); 3243c5a1b6fSMatthew Rosato return rc; 3253c5a1b6fSMatthew Rosato 3263c5a1b6fSMatthew Rosato unlock: 3273c5a1b6fSMatthew Rosato mutex_unlock(&aift->aift_lock); 3283c5a1b6fSMatthew Rosato unpin2: 3293c5a1b6fSMatthew Rosato if (fib->fmt0.sum == 1) 3303c5a1b6fSMatthew Rosato unpin_user_page(aisb_page); 3313c5a1b6fSMatthew Rosato unpin1: 3323c5a1b6fSMatthew Rosato unpin_user_page(aibv_page); 3333c5a1b6fSMatthew Rosato out: 3343c5a1b6fSMatthew Rosato return rc; 3353c5a1b6fSMatthew Rosato } 3363c5a1b6fSMatthew Rosato 3373c5a1b6fSMatthew Rosato static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force) 3383c5a1b6fSMatthew Rosato { 3393c5a1b6fSMatthew Rosato struct kvm_zdev *kzdev = zdev->kzdev; 3403c5a1b6fSMatthew Rosato struct zpci_gaite *gaite; 3413c5a1b6fSMatthew Rosato struct page *vpage = NULL, *spage = NULL; 3423c5a1b6fSMatthew Rosato int rc, pcount = 0; 3433c5a1b6fSMatthew Rosato u8 isc; 3443c5a1b6fSMatthew Rosato 3453c5a1b6fSMatthew Rosato if (zdev->gisa == 0) 3463c5a1b6fSMatthew Rosato return -EINVAL; 3473c5a1b6fSMatthew Rosato 3483c5a1b6fSMatthew Rosato mutex_lock(&aift->aift_lock); 3493c5a1b6fSMatthew Rosato 3503c5a1b6fSMatthew Rosato /* 3513c5a1b6fSMatthew Rosato * If the clear fails due to an error, leave now unless we know this 3523c5a1b6fSMatthew Rosato * device is about to go away (force) -- In that case clear the GAITE 3533c5a1b6fSMatthew Rosato * regardless. 3543c5a1b6fSMatthew Rosato */ 3553c5a1b6fSMatthew Rosato rc = kvm_zpci_clear_airq(zdev); 3563c5a1b6fSMatthew Rosato if (rc && !force) 3573c5a1b6fSMatthew Rosato goto out; 3583c5a1b6fSMatthew Rosato 3593c5a1b6fSMatthew Rosato if (zdev->kzdev->fib.fmt0.aibv == 0) 3603c5a1b6fSMatthew Rosato goto out; 3613c5a1b6fSMatthew Rosato spin_lock_irq(&aift->gait_lock); 3623c5a1b6fSMatthew Rosato gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb * 3633c5a1b6fSMatthew Rosato sizeof(struct zpci_gaite)); 3643c5a1b6fSMatthew Rosato isc = gaite->gisc; 3653c5a1b6fSMatthew Rosato gaite->count--; 3663c5a1b6fSMatthew Rosato if (gaite->count == 0) { 3673c5a1b6fSMatthew Rosato /* Release guest AIBV and AISB */ 3683c5a1b6fSMatthew Rosato vpage = phys_to_page(kzdev->fib.fmt0.aibv); 3693c5a1b6fSMatthew Rosato if (gaite->aisb != 0) 3703c5a1b6fSMatthew Rosato spage = phys_to_page(gaite->aisb); 3713c5a1b6fSMatthew Rosato /* Clear the GAIT entry */ 3723c5a1b6fSMatthew Rosato gaite->aisb = 0; 3733c5a1b6fSMatthew Rosato gaite->gisc = 0; 3743c5a1b6fSMatthew Rosato gaite->aisbo = 0; 3753c5a1b6fSMatthew Rosato gaite->gisa = 0; 376e8c924a4SMatthew Rosato aift->kzdev[zdev->aisb] = NULL; 3773c5a1b6fSMatthew Rosato /* Clear zdev info */ 3783c5a1b6fSMatthew Rosato airq_iv_free_bit(aift->sbv, zdev->aisb); 3793c5a1b6fSMatthew Rosato airq_iv_release(zdev->aibv); 3803c5a1b6fSMatthew Rosato zdev->aisb = 0; 3813c5a1b6fSMatthew Rosato zdev->aibv = NULL; 3823c5a1b6fSMatthew Rosato } 3833c5a1b6fSMatthew Rosato spin_unlock_irq(&aift->gait_lock); 3843c5a1b6fSMatthew Rosato kvm_s390_gisc_unregister(kzdev->kvm, isc); 3853c5a1b6fSMatthew Rosato kzdev->fib.fmt0.isc = 0; 3863c5a1b6fSMatthew Rosato kzdev->fib.fmt0.aibv = 0; 3873c5a1b6fSMatthew Rosato 3883c5a1b6fSMatthew Rosato if (vpage) { 3893c5a1b6fSMatthew Rosato unpin_user_page(vpage); 3903c5a1b6fSMatthew Rosato pcount++; 3913c5a1b6fSMatthew Rosato } 3923c5a1b6fSMatthew Rosato if (spage) { 3933c5a1b6fSMatthew Rosato unpin_user_page(spage); 3943c5a1b6fSMatthew Rosato pcount++; 3953c5a1b6fSMatthew Rosato } 3963c5a1b6fSMatthew Rosato if (pcount > 0) 3973c5a1b6fSMatthew Rosato unaccount_mem(pcount); 3983c5a1b6fSMatthew Rosato out: 3993c5a1b6fSMatthew Rosato mutex_unlock(&aift->aift_lock); 4003c5a1b6fSMatthew Rosato 4013c5a1b6fSMatthew Rosato return rc; 4023c5a1b6fSMatthew Rosato } 4033c5a1b6fSMatthew Rosato 4046438e307SMatthew Rosato static int kvm_s390_pci_dev_open(struct zpci_dev *zdev) 4056438e307SMatthew Rosato { 4066438e307SMatthew Rosato struct kvm_zdev *kzdev; 4076438e307SMatthew Rosato 4086438e307SMatthew Rosato kzdev = kzalloc(sizeof(struct kvm_zdev), GFP_KERNEL); 4096438e307SMatthew Rosato if (!kzdev) 4106438e307SMatthew Rosato return -ENOMEM; 4116438e307SMatthew Rosato 4126438e307SMatthew Rosato kzdev->zdev = zdev; 4136438e307SMatthew Rosato zdev->kzdev = kzdev; 4146438e307SMatthew Rosato 4156438e307SMatthew Rosato return 0; 4166438e307SMatthew Rosato } 4176438e307SMatthew Rosato 4186438e307SMatthew Rosato static void kvm_s390_pci_dev_release(struct zpci_dev *zdev) 4196438e307SMatthew Rosato { 4206438e307SMatthew Rosato struct kvm_zdev *kzdev; 4216438e307SMatthew Rosato 4226438e307SMatthew Rosato kzdev = zdev->kzdev; 4236438e307SMatthew Rosato WARN_ON(kzdev->zdev != zdev); 4246438e307SMatthew Rosato zdev->kzdev = NULL; 4256438e307SMatthew Rosato kfree(kzdev); 4266438e307SMatthew Rosato } 42798b1d33dSMatthew Rosato 42809340b2fSMatthew Rosato 42909340b2fSMatthew Rosato /* 43009340b2fSMatthew Rosato * Register device with the specified KVM. If interpetation facilities are 43109340b2fSMatthew Rosato * available, enable them and let userspace indicate whether or not they will 43209340b2fSMatthew Rosato * be used (specify SHM bit to disable). 43309340b2fSMatthew Rosato */ 434ca922fecSPierre Morel static int kvm_s390_pci_register_kvm(void *opaque, struct kvm *kvm) 43509340b2fSMatthew Rosato { 436ca922fecSPierre Morel struct zpci_dev *zdev = opaque; 43709340b2fSMatthew Rosato int rc; 43809340b2fSMatthew Rosato 43909340b2fSMatthew Rosato if (!zdev) 44009340b2fSMatthew Rosato return -EINVAL; 44109340b2fSMatthew Rosato 44209340b2fSMatthew Rosato mutex_lock(&zdev->kzdev_lock); 44309340b2fSMatthew Rosato 44409340b2fSMatthew Rosato if (zdev->kzdev || zdev->gisa != 0 || !kvm) { 44509340b2fSMatthew Rosato mutex_unlock(&zdev->kzdev_lock); 44609340b2fSMatthew Rosato return -EINVAL; 44709340b2fSMatthew Rosato } 44809340b2fSMatthew Rosato 44909340b2fSMatthew Rosato kvm_get_kvm(kvm); 45009340b2fSMatthew Rosato 45109340b2fSMatthew Rosato mutex_lock(&kvm->lock); 45209340b2fSMatthew Rosato 45309340b2fSMatthew Rosato rc = kvm_s390_pci_dev_open(zdev); 45409340b2fSMatthew Rosato if (rc) 45509340b2fSMatthew Rosato goto err; 45609340b2fSMatthew Rosato 45709340b2fSMatthew Rosato /* 45809340b2fSMatthew Rosato * If interpretation facilities aren't available, add the device to 45909340b2fSMatthew Rosato * the kzdev list but don't enable for interpretation. 46009340b2fSMatthew Rosato */ 46109340b2fSMatthew Rosato if (!kvm_s390_pci_interp_allowed()) 46209340b2fSMatthew Rosato goto out; 46309340b2fSMatthew Rosato 46409340b2fSMatthew Rosato /* 46509340b2fSMatthew Rosato * If this is the first request to use an interpreted device, make the 46609340b2fSMatthew Rosato * necessary vcpu changes 46709340b2fSMatthew Rosato */ 46809340b2fSMatthew Rosato if (!kvm->arch.use_zpci_interp) 46909340b2fSMatthew Rosato kvm_s390_vcpu_pci_enable_interp(kvm); 47009340b2fSMatthew Rosato 47109340b2fSMatthew Rosato if (zdev_enabled(zdev)) { 47209340b2fSMatthew Rosato rc = zpci_disable_device(zdev); 47309340b2fSMatthew Rosato if (rc) 47409340b2fSMatthew Rosato goto err; 47509340b2fSMatthew Rosato } 47609340b2fSMatthew Rosato 47709340b2fSMatthew Rosato /* 47809340b2fSMatthew Rosato * Store information about the identity of the kvm guest allowed to 47909340b2fSMatthew Rosato * access this device via interpretation to be used by host CLP 48009340b2fSMatthew Rosato */ 48109340b2fSMatthew Rosato zdev->gisa = (u32)virt_to_phys(&kvm->arch.sie_page2->gisa); 48209340b2fSMatthew Rosato 48309340b2fSMatthew Rosato rc = zpci_enable_device(zdev); 48409340b2fSMatthew Rosato if (rc) 48509340b2fSMatthew Rosato goto clear_gisa; 48609340b2fSMatthew Rosato 48709340b2fSMatthew Rosato /* Re-register the IOMMU that was already created */ 48809340b2fSMatthew Rosato rc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, 48909340b2fSMatthew Rosato virt_to_phys(zdev->dma_table)); 49009340b2fSMatthew Rosato if (rc) 49109340b2fSMatthew Rosato goto clear_gisa; 49209340b2fSMatthew Rosato 49309340b2fSMatthew Rosato out: 49409340b2fSMatthew Rosato zdev->kzdev->kvm = kvm; 49509340b2fSMatthew Rosato 49609340b2fSMatthew Rosato spin_lock(&kvm->arch.kzdev_list_lock); 49709340b2fSMatthew Rosato list_add_tail(&zdev->kzdev->entry, &kvm->arch.kzdev_list); 49809340b2fSMatthew Rosato spin_unlock(&kvm->arch.kzdev_list_lock); 49909340b2fSMatthew Rosato 50009340b2fSMatthew Rosato mutex_unlock(&kvm->lock); 50109340b2fSMatthew Rosato mutex_unlock(&zdev->kzdev_lock); 50209340b2fSMatthew Rosato return 0; 50309340b2fSMatthew Rosato 50409340b2fSMatthew Rosato clear_gisa: 50509340b2fSMatthew Rosato zdev->gisa = 0; 50609340b2fSMatthew Rosato err: 50709340b2fSMatthew Rosato if (zdev->kzdev) 50809340b2fSMatthew Rosato kvm_s390_pci_dev_release(zdev); 50909340b2fSMatthew Rosato mutex_unlock(&kvm->lock); 51009340b2fSMatthew Rosato mutex_unlock(&zdev->kzdev_lock); 51109340b2fSMatthew Rosato kvm_put_kvm(kvm); 51209340b2fSMatthew Rosato return rc; 51309340b2fSMatthew Rosato } 51409340b2fSMatthew Rosato 515ca922fecSPierre Morel static void kvm_s390_pci_unregister_kvm(void *opaque) 51609340b2fSMatthew Rosato { 517ca922fecSPierre Morel struct zpci_dev *zdev = opaque; 51809340b2fSMatthew Rosato struct kvm *kvm; 51909340b2fSMatthew Rosato 52009340b2fSMatthew Rosato if (!zdev) 52109340b2fSMatthew Rosato return; 52209340b2fSMatthew Rosato 52309340b2fSMatthew Rosato mutex_lock(&zdev->kzdev_lock); 52409340b2fSMatthew Rosato 52509340b2fSMatthew Rosato if (WARN_ON(!zdev->kzdev)) { 52609340b2fSMatthew Rosato mutex_unlock(&zdev->kzdev_lock); 52709340b2fSMatthew Rosato return; 52809340b2fSMatthew Rosato } 52909340b2fSMatthew Rosato 53009340b2fSMatthew Rosato kvm = zdev->kzdev->kvm; 53109340b2fSMatthew Rosato mutex_lock(&kvm->lock); 53209340b2fSMatthew Rosato 53309340b2fSMatthew Rosato /* 53409340b2fSMatthew Rosato * A 0 gisa means interpretation was never enabled, just remove the 53509340b2fSMatthew Rosato * device from the list. 53609340b2fSMatthew Rosato */ 53709340b2fSMatthew Rosato if (zdev->gisa == 0) 53809340b2fSMatthew Rosato goto out; 53909340b2fSMatthew Rosato 54009340b2fSMatthew Rosato /* Forwarding must be turned off before interpretation */ 54109340b2fSMatthew Rosato if (zdev->kzdev->fib.fmt0.aibv != 0) 54209340b2fSMatthew Rosato kvm_s390_pci_aif_disable(zdev, true); 54309340b2fSMatthew Rosato 54409340b2fSMatthew Rosato /* Remove the host CLP guest designation */ 54509340b2fSMatthew Rosato zdev->gisa = 0; 54609340b2fSMatthew Rosato 54709340b2fSMatthew Rosato if (zdev_enabled(zdev)) { 54809340b2fSMatthew Rosato if (zpci_disable_device(zdev)) 54909340b2fSMatthew Rosato goto out; 55009340b2fSMatthew Rosato } 55109340b2fSMatthew Rosato 55209340b2fSMatthew Rosato if (zpci_enable_device(zdev)) 55309340b2fSMatthew Rosato goto out; 55409340b2fSMatthew Rosato 55509340b2fSMatthew Rosato /* Re-register the IOMMU that was already created */ 55609340b2fSMatthew Rosato zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, 55709340b2fSMatthew Rosato virt_to_phys(zdev->dma_table)); 55809340b2fSMatthew Rosato 55909340b2fSMatthew Rosato out: 56009340b2fSMatthew Rosato spin_lock(&kvm->arch.kzdev_list_lock); 56109340b2fSMatthew Rosato list_del(&zdev->kzdev->entry); 56209340b2fSMatthew Rosato spin_unlock(&kvm->arch.kzdev_list_lock); 56309340b2fSMatthew Rosato kvm_s390_pci_dev_release(zdev); 56409340b2fSMatthew Rosato 56509340b2fSMatthew Rosato mutex_unlock(&kvm->lock); 56609340b2fSMatthew Rosato mutex_unlock(&zdev->kzdev_lock); 56709340b2fSMatthew Rosato 56809340b2fSMatthew Rosato kvm_put_kvm(kvm); 56909340b2fSMatthew Rosato } 57009340b2fSMatthew Rosato 57109340b2fSMatthew Rosato void kvm_s390_pci_init_list(struct kvm *kvm) 57209340b2fSMatthew Rosato { 57309340b2fSMatthew Rosato spin_lock_init(&kvm->arch.kzdev_list_lock); 57409340b2fSMatthew Rosato INIT_LIST_HEAD(&kvm->arch.kzdev_list); 57509340b2fSMatthew Rosato } 57609340b2fSMatthew Rosato 57709340b2fSMatthew Rosato void kvm_s390_pci_clear_list(struct kvm *kvm) 57809340b2fSMatthew Rosato { 57909340b2fSMatthew Rosato /* 58009340b2fSMatthew Rosato * This list should already be empty, either via vfio device closures 58109340b2fSMatthew Rosato * or kvm fd cleanup. 58209340b2fSMatthew Rosato */ 58309340b2fSMatthew Rosato spin_lock(&kvm->arch.kzdev_list_lock); 58409340b2fSMatthew Rosato WARN_ON_ONCE(!list_empty(&kvm->arch.kzdev_list)); 58509340b2fSMatthew Rosato spin_unlock(&kvm->arch.kzdev_list_lock); 58609340b2fSMatthew Rosato } 58709340b2fSMatthew Rosato 588db1c875eSMatthew Rosato static struct zpci_dev *get_zdev_from_kvm_by_fh(struct kvm *kvm, u32 fh) 589db1c875eSMatthew Rosato { 590db1c875eSMatthew Rosato struct zpci_dev *zdev = NULL; 591db1c875eSMatthew Rosato struct kvm_zdev *kzdev; 592db1c875eSMatthew Rosato 593db1c875eSMatthew Rosato spin_lock(&kvm->arch.kzdev_list_lock); 594db1c875eSMatthew Rosato list_for_each_entry(kzdev, &kvm->arch.kzdev_list, entry) { 595db1c875eSMatthew Rosato if (kzdev->zdev->fh == fh) { 596db1c875eSMatthew Rosato zdev = kzdev->zdev; 597db1c875eSMatthew Rosato break; 598db1c875eSMatthew Rosato } 599db1c875eSMatthew Rosato } 600db1c875eSMatthew Rosato spin_unlock(&kvm->arch.kzdev_list_lock); 601db1c875eSMatthew Rosato 602db1c875eSMatthew Rosato return zdev; 603db1c875eSMatthew Rosato } 604db1c875eSMatthew Rosato 605db1c875eSMatthew Rosato static int kvm_s390_pci_zpci_reg_aen(struct zpci_dev *zdev, 606db1c875eSMatthew Rosato struct kvm_s390_zpci_op *args) 607db1c875eSMatthew Rosato { 608db1c875eSMatthew Rosato struct zpci_fib fib = {}; 609db1c875eSMatthew Rosato bool hostflag; 610db1c875eSMatthew Rosato 611db1c875eSMatthew Rosato fib.fmt0.aibv = args->u.reg_aen.ibv; 612db1c875eSMatthew Rosato fib.fmt0.isc = args->u.reg_aen.isc; 613db1c875eSMatthew Rosato fib.fmt0.noi = args->u.reg_aen.noi; 614db1c875eSMatthew Rosato if (args->u.reg_aen.sb != 0) { 615db1c875eSMatthew Rosato fib.fmt0.aisb = args->u.reg_aen.sb; 616db1c875eSMatthew Rosato fib.fmt0.aisbo = args->u.reg_aen.sbo; 617db1c875eSMatthew Rosato fib.fmt0.sum = 1; 618db1c875eSMatthew Rosato } else { 619db1c875eSMatthew Rosato fib.fmt0.aisb = 0; 620db1c875eSMatthew Rosato fib.fmt0.aisbo = 0; 621db1c875eSMatthew Rosato fib.fmt0.sum = 0; 622db1c875eSMatthew Rosato } 623db1c875eSMatthew Rosato 624db1c875eSMatthew Rosato hostflag = !(args->u.reg_aen.flags & KVM_S390_ZPCIOP_REGAEN_HOST); 625db1c875eSMatthew Rosato return kvm_s390_pci_aif_enable(zdev, &fib, hostflag); 626db1c875eSMatthew Rosato } 627db1c875eSMatthew Rosato 628db1c875eSMatthew Rosato int kvm_s390_pci_zpci_op(struct kvm *kvm, struct kvm_s390_zpci_op *args) 629db1c875eSMatthew Rosato { 630db1c875eSMatthew Rosato struct kvm_zdev *kzdev; 631db1c875eSMatthew Rosato struct zpci_dev *zdev; 632db1c875eSMatthew Rosato int r; 633db1c875eSMatthew Rosato 634db1c875eSMatthew Rosato zdev = get_zdev_from_kvm_by_fh(kvm, args->fh); 635db1c875eSMatthew Rosato if (!zdev) 636db1c875eSMatthew Rosato return -ENODEV; 637db1c875eSMatthew Rosato 638db1c875eSMatthew Rosato mutex_lock(&zdev->kzdev_lock); 639db1c875eSMatthew Rosato mutex_lock(&kvm->lock); 640db1c875eSMatthew Rosato 641db1c875eSMatthew Rosato kzdev = zdev->kzdev; 642db1c875eSMatthew Rosato if (!kzdev) { 643db1c875eSMatthew Rosato r = -ENODEV; 644db1c875eSMatthew Rosato goto out; 645db1c875eSMatthew Rosato } 646db1c875eSMatthew Rosato if (kzdev->kvm != kvm) { 647db1c875eSMatthew Rosato r = -EPERM; 648db1c875eSMatthew Rosato goto out; 649db1c875eSMatthew Rosato } 650db1c875eSMatthew Rosato 651db1c875eSMatthew Rosato switch (args->op) { 652db1c875eSMatthew Rosato case KVM_S390_ZPCIOP_REG_AEN: 653db1c875eSMatthew Rosato /* Fail on unknown flags */ 654db1c875eSMatthew Rosato if (args->u.reg_aen.flags & ~KVM_S390_ZPCIOP_REGAEN_HOST) { 655db1c875eSMatthew Rosato r = -EINVAL; 656db1c875eSMatthew Rosato break; 657db1c875eSMatthew Rosato } 658db1c875eSMatthew Rosato r = kvm_s390_pci_zpci_reg_aen(zdev, args); 659db1c875eSMatthew Rosato break; 660db1c875eSMatthew Rosato case KVM_S390_ZPCIOP_DEREG_AEN: 661db1c875eSMatthew Rosato r = kvm_s390_pci_aif_disable(zdev, false); 662db1c875eSMatthew Rosato break; 663db1c875eSMatthew Rosato default: 664db1c875eSMatthew Rosato r = -EINVAL; 665db1c875eSMatthew Rosato } 666db1c875eSMatthew Rosato 667db1c875eSMatthew Rosato out: 668db1c875eSMatthew Rosato mutex_unlock(&kvm->lock); 669db1c875eSMatthew Rosato mutex_unlock(&zdev->kzdev_lock); 670db1c875eSMatthew Rosato return r; 671db1c875eSMatthew Rosato } 672db1c875eSMatthew Rosato 67398b1d33dSMatthew Rosato int kvm_s390_pci_init(void) 67498b1d33dSMatthew Rosato { 67598b1d33dSMatthew Rosato aift = kzalloc(sizeof(struct zpci_aift), GFP_KERNEL); 67698b1d33dSMatthew Rosato if (!aift) 67798b1d33dSMatthew Rosato return -ENOMEM; 67898b1d33dSMatthew Rosato 67998b1d33dSMatthew Rosato spin_lock_init(&aift->gait_lock); 68098b1d33dSMatthew Rosato mutex_init(&aift->aift_lock); 681ca922fecSPierre Morel zpci_kvm_hook.kvm_register = kvm_s390_pci_register_kvm; 682ca922fecSPierre Morel zpci_kvm_hook.kvm_unregister = kvm_s390_pci_unregister_kvm; 68398b1d33dSMatthew Rosato 68498b1d33dSMatthew Rosato return 0; 68598b1d33dSMatthew Rosato } 68698b1d33dSMatthew Rosato 68798b1d33dSMatthew Rosato void kvm_s390_pci_exit(void) 68898b1d33dSMatthew Rosato { 68998b1d33dSMatthew Rosato mutex_destroy(&aift->aift_lock); 690ca922fecSPierre Morel zpci_kvm_hook.kvm_register = NULL; 691ca922fecSPierre Morel zpci_kvm_hook.kvm_unregister = NULL; 69298b1d33dSMatthew Rosato 69398b1d33dSMatthew Rosato kfree(aift); 69498b1d33dSMatthew Rosato } 695