162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * channel program interfaces 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright IBM Corp. 2017 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> 862306a36Sopenharmony_ci * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/ratelimit.h> 1262306a36Sopenharmony_ci#include <linux/mm.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/highmem.h> 1562306a36Sopenharmony_ci#include <linux/iommu.h> 1662306a36Sopenharmony_ci#include <linux/vfio.h> 1762306a36Sopenharmony_ci#include <asm/idals.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "vfio_ccw_cp.h" 2062306a36Sopenharmony_ci#include "vfio_ccw_private.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistruct page_array { 2362306a36Sopenharmony_ci /* Array that stores pages need to pin. */ 2462306a36Sopenharmony_ci dma_addr_t *pa_iova; 2562306a36Sopenharmony_ci /* Array that receives the pinned pages. */ 2662306a36Sopenharmony_ci struct page **pa_page; 2762306a36Sopenharmony_ci /* Number of pages pinned from @pa_iova. */ 2862306a36Sopenharmony_ci int pa_nr; 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistruct ccwchain { 3262306a36Sopenharmony_ci struct list_head next; 3362306a36Sopenharmony_ci struct ccw1 *ch_ccw; 3462306a36Sopenharmony_ci /* Guest physical address of the current chain. */ 3562306a36Sopenharmony_ci u64 ch_iova; 3662306a36Sopenharmony_ci /* Count of the valid ccws in chain. */ 3762306a36Sopenharmony_ci int ch_len; 3862306a36Sopenharmony_ci /* Pinned PAGEs for the original data. */ 3962306a36Sopenharmony_ci struct page_array *ch_pa; 4062306a36Sopenharmony_ci}; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* 4362306a36Sopenharmony_ci * page_array_alloc() - alloc memory for page array 4462306a36Sopenharmony_ci * @pa: page_array on which to perform the operation 4562306a36Sopenharmony_ci * @len: number of pages that should be pinned from @iova 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * Attempt to allocate memory for page array. 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * Usage of page_array: 5062306a36Sopenharmony_ci * We expect (pa_nr == 0) and (pa_iova == NULL), any field in 5162306a36Sopenharmony_ci * this structure will be filled in by this function. 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * Returns: 5462306a36Sopenharmony_ci * 0 if page array is allocated 5562306a36Sopenharmony_ci * -EINVAL if pa->pa_nr is not initially zero, or pa->pa_iova is not NULL 5662306a36Sopenharmony_ci * -ENOMEM if alloc failed 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_cistatic int page_array_alloc(struct page_array *pa, unsigned int len) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci if (pa->pa_nr || pa->pa_iova) 6162306a36Sopenharmony_ci return -EINVAL; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (len == 0) 6462306a36Sopenharmony_ci return -EINVAL; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci pa->pa_nr = len; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci pa->pa_iova = kcalloc(len, sizeof(*pa->pa_iova), GFP_KERNEL); 6962306a36Sopenharmony_ci if (!pa->pa_iova) 7062306a36Sopenharmony_ci return -ENOMEM; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci pa->pa_page = kcalloc(len, sizeof(*pa->pa_page), GFP_KERNEL); 7362306a36Sopenharmony_ci if (!pa->pa_page) { 7462306a36Sopenharmony_ci kfree(pa->pa_iova); 7562306a36Sopenharmony_ci return -ENOMEM; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return 0; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* 8262306a36Sopenharmony_ci * page_array_unpin() - Unpin user pages in memory 8362306a36Sopenharmony_ci * @pa: page_array on which to perform the operation 8462306a36Sopenharmony_ci * @vdev: the vfio device to perform the operation 8562306a36Sopenharmony_ci * @pa_nr: number of user pages to unpin 8662306a36Sopenharmony_ci * @unaligned: were pages unaligned on the pin request 8762306a36Sopenharmony_ci * 8862306a36Sopenharmony_ci * Only unpin if any pages were pinned to begin with, i.e. pa_nr > 0, 8962306a36Sopenharmony_ci * otherwise only clear pa->pa_nr 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_cistatic void page_array_unpin(struct page_array *pa, 9262306a36Sopenharmony_ci struct vfio_device *vdev, int pa_nr, bool unaligned) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci int unpinned = 0, npage = 1; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci while (unpinned < pa_nr) { 9762306a36Sopenharmony_ci dma_addr_t *first = &pa->pa_iova[unpinned]; 9862306a36Sopenharmony_ci dma_addr_t *last = &first[npage]; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci if (unpinned + npage < pa_nr && 10162306a36Sopenharmony_ci *first + npage * PAGE_SIZE == *last && 10262306a36Sopenharmony_ci !unaligned) { 10362306a36Sopenharmony_ci npage++; 10462306a36Sopenharmony_ci continue; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci vfio_unpin_pages(vdev, *first, npage); 10862306a36Sopenharmony_ci unpinned += npage; 10962306a36Sopenharmony_ci npage = 1; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci pa->pa_nr = 0; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* 11662306a36Sopenharmony_ci * page_array_pin() - Pin user pages in memory 11762306a36Sopenharmony_ci * @pa: page_array on which to perform the operation 11862306a36Sopenharmony_ci * @vdev: the vfio device to perform pin operations 11962306a36Sopenharmony_ci * @unaligned: are pages aligned to 4K boundary? 12062306a36Sopenharmony_ci * 12162306a36Sopenharmony_ci * Returns number of pages pinned upon success. 12262306a36Sopenharmony_ci * If the pin request partially succeeds, or fails completely, 12362306a36Sopenharmony_ci * all pages are left unpinned and a negative error value is returned. 12462306a36Sopenharmony_ci * 12562306a36Sopenharmony_ci * Requests to pin "aligned" pages can be coalesced into a single 12662306a36Sopenharmony_ci * vfio_pin_pages request for the sake of efficiency, based on the 12762306a36Sopenharmony_ci * expectation of 4K page requests. Unaligned requests are probably 12862306a36Sopenharmony_ci * dealing with 2K "pages", and cannot be coalesced without 12962306a36Sopenharmony_ci * reworking this logic to incorporate that math. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_cistatic int page_array_pin(struct page_array *pa, struct vfio_device *vdev, bool unaligned) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci int pinned = 0, npage = 1; 13462306a36Sopenharmony_ci int ret = 0; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci while (pinned < pa->pa_nr) { 13762306a36Sopenharmony_ci dma_addr_t *first = &pa->pa_iova[pinned]; 13862306a36Sopenharmony_ci dma_addr_t *last = &first[npage]; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (pinned + npage < pa->pa_nr && 14162306a36Sopenharmony_ci *first + npage * PAGE_SIZE == *last && 14262306a36Sopenharmony_ci !unaligned) { 14362306a36Sopenharmony_ci npage++; 14462306a36Sopenharmony_ci continue; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci ret = vfio_pin_pages(vdev, *first, npage, 14862306a36Sopenharmony_ci IOMMU_READ | IOMMU_WRITE, 14962306a36Sopenharmony_ci &pa->pa_page[pinned]); 15062306a36Sopenharmony_ci if (ret < 0) { 15162306a36Sopenharmony_ci goto err_out; 15262306a36Sopenharmony_ci } else if (ret > 0 && ret != npage) { 15362306a36Sopenharmony_ci pinned += ret; 15462306a36Sopenharmony_ci ret = -EINVAL; 15562306a36Sopenharmony_ci goto err_out; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci pinned += npage; 15862306a36Sopenharmony_ci npage = 1; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci return ret; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cierr_out: 16462306a36Sopenharmony_ci page_array_unpin(pa, vdev, pinned, unaligned); 16562306a36Sopenharmony_ci return ret; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci/* Unpin the pages before releasing the memory. */ 16962306a36Sopenharmony_cistatic void page_array_unpin_free(struct page_array *pa, struct vfio_device *vdev, bool unaligned) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci page_array_unpin(pa, vdev, pa->pa_nr, unaligned); 17262306a36Sopenharmony_ci kfree(pa->pa_page); 17362306a36Sopenharmony_ci kfree(pa->pa_iova); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic bool page_array_iova_pinned(struct page_array *pa, u64 iova, u64 length) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci u64 iova_pfn_start = iova >> PAGE_SHIFT; 17962306a36Sopenharmony_ci u64 iova_pfn_end = (iova + length - 1) >> PAGE_SHIFT; 18062306a36Sopenharmony_ci u64 pfn; 18162306a36Sopenharmony_ci int i; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci for (i = 0; i < pa->pa_nr; i++) { 18462306a36Sopenharmony_ci pfn = pa->pa_iova[i] >> PAGE_SHIFT; 18562306a36Sopenharmony_ci if (pfn >= iova_pfn_start && pfn <= iova_pfn_end) 18662306a36Sopenharmony_ci return true; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci return false; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci/* Create the list of IDAL words for a page_array. */ 19262306a36Sopenharmony_cistatic inline void page_array_idal_create_words(struct page_array *pa, 19362306a36Sopenharmony_ci unsigned long *idaws) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci int i; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* 19862306a36Sopenharmony_ci * Idal words (execept the first one) rely on the memory being 4k 19962306a36Sopenharmony_ci * aligned. If a user virtual address is 4K aligned, then it's 20062306a36Sopenharmony_ci * corresponding kernel physical address will also be 4K aligned. Thus 20162306a36Sopenharmony_ci * there will be no problem here to simply use the phys to create an 20262306a36Sopenharmony_ci * idaw. 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci for (i = 0; i < pa->pa_nr; i++) { 20662306a36Sopenharmony_ci idaws[i] = page_to_phys(pa->pa_page[i]); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* Incorporate any offset from each starting address */ 20962306a36Sopenharmony_ci idaws[i] += pa->pa_iova[i] & (PAGE_SIZE - 1); 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistatic void convert_ccw0_to_ccw1(struct ccw1 *source, unsigned long len) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci struct ccw0 ccw0; 21662306a36Sopenharmony_ci struct ccw1 *pccw1 = source; 21762306a36Sopenharmony_ci int i; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci for (i = 0; i < len; i++) { 22062306a36Sopenharmony_ci ccw0 = *(struct ccw0 *)pccw1; 22162306a36Sopenharmony_ci if ((pccw1->cmd_code & 0x0f) == CCW_CMD_TIC) { 22262306a36Sopenharmony_ci pccw1->cmd_code = CCW_CMD_TIC; 22362306a36Sopenharmony_ci pccw1->flags = 0; 22462306a36Sopenharmony_ci pccw1->count = 0; 22562306a36Sopenharmony_ci } else { 22662306a36Sopenharmony_ci pccw1->cmd_code = ccw0.cmd_code; 22762306a36Sopenharmony_ci pccw1->flags = ccw0.flags; 22862306a36Sopenharmony_ci pccw1->count = ccw0.count; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci pccw1->cda = ccw0.cda; 23162306a36Sopenharmony_ci pccw1++; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci#define idal_is_2k(_cp) (!(_cp)->orb.cmd.c64 || (_cp)->orb.cmd.i2k) 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/* 23862306a36Sopenharmony_ci * Helpers to operate ccwchain. 23962306a36Sopenharmony_ci */ 24062306a36Sopenharmony_ci#define ccw_is_read(_ccw) (((_ccw)->cmd_code & 0x03) == 0x02) 24162306a36Sopenharmony_ci#define ccw_is_read_backward(_ccw) (((_ccw)->cmd_code & 0x0F) == 0x0C) 24262306a36Sopenharmony_ci#define ccw_is_sense(_ccw) (((_ccw)->cmd_code & 0x0F) == CCW_CMD_BASIC_SENSE) 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci#define ccw_is_noop(_ccw) ((_ccw)->cmd_code == CCW_CMD_NOOP) 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci#define ccw_is_tic(_ccw) ((_ccw)->cmd_code == CCW_CMD_TIC) 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci#define ccw_is_idal(_ccw) ((_ccw)->flags & CCW_FLAG_IDA) 24962306a36Sopenharmony_ci#define ccw_is_skip(_ccw) ((_ccw)->flags & CCW_FLAG_SKIP) 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci#define ccw_is_chain(_ccw) ((_ccw)->flags & (CCW_FLAG_CC | CCW_FLAG_DC)) 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci/* 25462306a36Sopenharmony_ci * ccw_does_data_transfer() 25562306a36Sopenharmony_ci * 25662306a36Sopenharmony_ci * Determine whether a CCW will move any data, such that the guest pages 25762306a36Sopenharmony_ci * would need to be pinned before performing the I/O. 25862306a36Sopenharmony_ci * 25962306a36Sopenharmony_ci * Returns 1 if yes, 0 if no. 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_cistatic inline int ccw_does_data_transfer(struct ccw1 *ccw) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci /* If the count field is zero, then no data will be transferred */ 26462306a36Sopenharmony_ci if (ccw->count == 0) 26562306a36Sopenharmony_ci return 0; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* If the command is a NOP, then no data will be transferred */ 26862306a36Sopenharmony_ci if (ccw_is_noop(ccw)) 26962306a36Sopenharmony_ci return 0; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* If the skip flag is off, then data will be transferred */ 27262306a36Sopenharmony_ci if (!ccw_is_skip(ccw)) 27362306a36Sopenharmony_ci return 1; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* 27662306a36Sopenharmony_ci * If the skip flag is on, it is only meaningful if the command 27762306a36Sopenharmony_ci * code is a read, read backward, sense, or sense ID. In those 27862306a36Sopenharmony_ci * cases, no data will be transferred. 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_ci if (ccw_is_read(ccw) || ccw_is_read_backward(ccw)) 28162306a36Sopenharmony_ci return 0; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (ccw_is_sense(ccw)) 28462306a36Sopenharmony_ci return 0; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* The skip flag is on, but it is ignored for this command code. */ 28762306a36Sopenharmony_ci return 1; 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci/* 29162306a36Sopenharmony_ci * is_cpa_within_range() 29262306a36Sopenharmony_ci * 29362306a36Sopenharmony_ci * @cpa: channel program address being questioned 29462306a36Sopenharmony_ci * @head: address of the beginning of a CCW chain 29562306a36Sopenharmony_ci * @len: number of CCWs within the chain 29662306a36Sopenharmony_ci * 29762306a36Sopenharmony_ci * Determine whether the address of a CCW (whether a new chain, 29862306a36Sopenharmony_ci * or the target of a TIC) falls within a range (including the end points). 29962306a36Sopenharmony_ci * 30062306a36Sopenharmony_ci * Returns 1 if yes, 0 if no. 30162306a36Sopenharmony_ci */ 30262306a36Sopenharmony_cistatic inline int is_cpa_within_range(u32 cpa, u32 head, int len) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci u32 tail = head + (len - 1) * sizeof(struct ccw1); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci return (head <= cpa && cpa <= tail); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic inline int is_tic_within_range(struct ccw1 *ccw, u32 head, int len) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci if (!ccw_is_tic(ccw)) 31262306a36Sopenharmony_ci return 0; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci return is_cpa_within_range(ccw->cda, head, len); 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci struct ccwchain *chain; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci chain = kzalloc(sizeof(*chain), GFP_KERNEL); 32262306a36Sopenharmony_ci if (!chain) 32362306a36Sopenharmony_ci return NULL; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci chain->ch_ccw = kcalloc(len, sizeof(*chain->ch_ccw), GFP_DMA | GFP_KERNEL); 32662306a36Sopenharmony_ci if (!chain->ch_ccw) 32762306a36Sopenharmony_ci goto out_err; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci chain->ch_pa = kcalloc(len, sizeof(*chain->ch_pa), GFP_KERNEL); 33062306a36Sopenharmony_ci if (!chain->ch_pa) 33162306a36Sopenharmony_ci goto out_err; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci list_add_tail(&chain->next, &cp->ccwchain_list); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci return chain; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ciout_err: 33862306a36Sopenharmony_ci kfree(chain->ch_ccw); 33962306a36Sopenharmony_ci kfree(chain); 34062306a36Sopenharmony_ci return NULL; 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cistatic void ccwchain_free(struct ccwchain *chain) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci list_del(&chain->next); 34662306a36Sopenharmony_ci kfree(chain->ch_pa); 34762306a36Sopenharmony_ci kfree(chain->ch_ccw); 34862306a36Sopenharmony_ci kfree(chain); 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/* Free resource for a ccw that allocated memory for its cda. */ 35262306a36Sopenharmony_cistatic void ccwchain_cda_free(struct ccwchain *chain, int idx) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci struct ccw1 *ccw = &chain->ch_ccw[idx]; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (ccw_is_tic(ccw)) 35762306a36Sopenharmony_ci return; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci kfree(phys_to_virt(ccw->cda)); 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci/** 36362306a36Sopenharmony_ci * ccwchain_calc_length - calculate the length of the ccw chain. 36462306a36Sopenharmony_ci * @iova: guest physical address of the target ccw chain 36562306a36Sopenharmony_ci * @cp: channel_program on which to perform the operation 36662306a36Sopenharmony_ci * 36762306a36Sopenharmony_ci * This is the chain length not considering any TICs. 36862306a36Sopenharmony_ci * You need to do a new round for each TIC target. 36962306a36Sopenharmony_ci * 37062306a36Sopenharmony_ci * The program is also validated for absence of not yet supported 37162306a36Sopenharmony_ci * indirect data addressing scenarios. 37262306a36Sopenharmony_ci * 37362306a36Sopenharmony_ci * Returns: the length of the ccw chain or -errno. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_cistatic int ccwchain_calc_length(u64 iova, struct channel_program *cp) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci struct ccw1 *ccw = cp->guest_cp; 37862306a36Sopenharmony_ci int cnt = 0; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci do { 38162306a36Sopenharmony_ci cnt++; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* 38462306a36Sopenharmony_ci * We want to keep counting if the current CCW has the 38562306a36Sopenharmony_ci * command-chaining flag enabled, or if it is a TIC CCW 38662306a36Sopenharmony_ci * that loops back into the current chain. The latter 38762306a36Sopenharmony_ci * is used for device orientation, where the CCW PRIOR to 38862306a36Sopenharmony_ci * the TIC can either jump to the TIC or a CCW immediately 38962306a36Sopenharmony_ci * after the TIC, depending on the results of its operation. 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_ci if (!ccw_is_chain(ccw) && !is_tic_within_range(ccw, iova, cnt)) 39262306a36Sopenharmony_ci break; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci ccw++; 39562306a36Sopenharmony_ci } while (cnt < CCWCHAIN_LEN_MAX + 1); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci if (cnt == CCWCHAIN_LEN_MAX + 1) 39862306a36Sopenharmony_ci cnt = -EINVAL; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci return cnt; 40162306a36Sopenharmony_ci} 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_cistatic int tic_target_chain_exists(struct ccw1 *tic, struct channel_program *cp) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci struct ccwchain *chain; 40662306a36Sopenharmony_ci u32 ccw_head; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci list_for_each_entry(chain, &cp->ccwchain_list, next) { 40962306a36Sopenharmony_ci ccw_head = chain->ch_iova; 41062306a36Sopenharmony_ci if (is_cpa_within_range(tic->cda, ccw_head, chain->ch_len)) 41162306a36Sopenharmony_ci return 1; 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci return 0; 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic int ccwchain_loop_tic(struct ccwchain *chain, 41862306a36Sopenharmony_ci struct channel_program *cp); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic int ccwchain_handle_ccw(u32 cda, struct channel_program *cp) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci struct vfio_device *vdev = 42362306a36Sopenharmony_ci &container_of(cp, struct vfio_ccw_private, cp)->vdev; 42462306a36Sopenharmony_ci struct ccwchain *chain; 42562306a36Sopenharmony_ci int len, ret; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* Copy 2K (the most we support today) of possible CCWs */ 42862306a36Sopenharmony_ci ret = vfio_dma_rw(vdev, cda, cp->guest_cp, CCWCHAIN_LEN_MAX * sizeof(struct ccw1), false); 42962306a36Sopenharmony_ci if (ret) 43062306a36Sopenharmony_ci return ret; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci /* Convert any Format-0 CCWs to Format-1 */ 43362306a36Sopenharmony_ci if (!cp->orb.cmd.fmt) 43462306a36Sopenharmony_ci convert_ccw0_to_ccw1(cp->guest_cp, CCWCHAIN_LEN_MAX); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci /* Count the CCWs in the current chain */ 43762306a36Sopenharmony_ci len = ccwchain_calc_length(cda, cp); 43862306a36Sopenharmony_ci if (len < 0) 43962306a36Sopenharmony_ci return len; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci /* Need alloc a new chain for this one. */ 44262306a36Sopenharmony_ci chain = ccwchain_alloc(cp, len); 44362306a36Sopenharmony_ci if (!chain) 44462306a36Sopenharmony_ci return -ENOMEM; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci chain->ch_len = len; 44762306a36Sopenharmony_ci chain->ch_iova = cda; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* Copy the actual CCWs into the new chain */ 45062306a36Sopenharmony_ci memcpy(chain->ch_ccw, cp->guest_cp, len * sizeof(struct ccw1)); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci /* Loop for tics on this new chain. */ 45362306a36Sopenharmony_ci ret = ccwchain_loop_tic(chain, cp); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (ret) 45662306a36Sopenharmony_ci ccwchain_free(chain); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci return ret; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci/* Loop for TICs. */ 46262306a36Sopenharmony_cistatic int ccwchain_loop_tic(struct ccwchain *chain, struct channel_program *cp) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci struct ccw1 *tic; 46562306a36Sopenharmony_ci int i, ret; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci for (i = 0; i < chain->ch_len; i++) { 46862306a36Sopenharmony_ci tic = &chain->ch_ccw[i]; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci if (!ccw_is_tic(tic)) 47162306a36Sopenharmony_ci continue; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci /* May transfer to an existing chain. */ 47462306a36Sopenharmony_ci if (tic_target_chain_exists(tic, cp)) 47562306a36Sopenharmony_ci continue; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci /* Build a ccwchain for the next segment */ 47862306a36Sopenharmony_ci ret = ccwchain_handle_ccw(tic->cda, cp); 47962306a36Sopenharmony_ci if (ret) 48062306a36Sopenharmony_ci return ret; 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci return 0; 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic int ccwchain_fetch_tic(struct ccw1 *ccw, 48762306a36Sopenharmony_ci struct channel_program *cp) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci struct ccwchain *iter; 49062306a36Sopenharmony_ci u32 ccw_head; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci list_for_each_entry(iter, &cp->ccwchain_list, next) { 49362306a36Sopenharmony_ci ccw_head = iter->ch_iova; 49462306a36Sopenharmony_ci if (is_cpa_within_range(ccw->cda, ccw_head, iter->ch_len)) { 49562306a36Sopenharmony_ci ccw->cda = (__u32) (addr_t) (((char *)iter->ch_ccw) + 49662306a36Sopenharmony_ci (ccw->cda - ccw_head)); 49762306a36Sopenharmony_ci return 0; 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci return -EFAULT; 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_cistatic unsigned long *get_guest_idal(struct ccw1 *ccw, 50562306a36Sopenharmony_ci struct channel_program *cp, 50662306a36Sopenharmony_ci int idaw_nr) 50762306a36Sopenharmony_ci{ 50862306a36Sopenharmony_ci struct vfio_device *vdev = 50962306a36Sopenharmony_ci &container_of(cp, struct vfio_ccw_private, cp)->vdev; 51062306a36Sopenharmony_ci unsigned long *idaws; 51162306a36Sopenharmony_ci unsigned int *idaws_f1; 51262306a36Sopenharmony_ci int idal_len = idaw_nr * sizeof(*idaws); 51362306a36Sopenharmony_ci int idaw_size = idal_is_2k(cp) ? PAGE_SIZE / 2 : PAGE_SIZE; 51462306a36Sopenharmony_ci int idaw_mask = ~(idaw_size - 1); 51562306a36Sopenharmony_ci int i, ret; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci idaws = kcalloc(idaw_nr, sizeof(*idaws), GFP_DMA | GFP_KERNEL); 51862306a36Sopenharmony_ci if (!idaws) 51962306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (ccw_is_idal(ccw)) { 52262306a36Sopenharmony_ci /* Copy IDAL from guest */ 52362306a36Sopenharmony_ci ret = vfio_dma_rw(vdev, ccw->cda, idaws, idal_len, false); 52462306a36Sopenharmony_ci if (ret) { 52562306a36Sopenharmony_ci kfree(idaws); 52662306a36Sopenharmony_ci return ERR_PTR(ret); 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci } else { 52962306a36Sopenharmony_ci /* Fabricate an IDAL based off CCW data address */ 53062306a36Sopenharmony_ci if (cp->orb.cmd.c64) { 53162306a36Sopenharmony_ci idaws[0] = ccw->cda; 53262306a36Sopenharmony_ci for (i = 1; i < idaw_nr; i++) 53362306a36Sopenharmony_ci idaws[i] = (idaws[i - 1] + idaw_size) & idaw_mask; 53462306a36Sopenharmony_ci } else { 53562306a36Sopenharmony_ci idaws_f1 = (unsigned int *)idaws; 53662306a36Sopenharmony_ci idaws_f1[0] = ccw->cda; 53762306a36Sopenharmony_ci for (i = 1; i < idaw_nr; i++) 53862306a36Sopenharmony_ci idaws_f1[i] = (idaws_f1[i - 1] + idaw_size) & idaw_mask; 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci return idaws; 54362306a36Sopenharmony_ci} 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci/* 54662306a36Sopenharmony_ci * ccw_count_idaws() - Calculate the number of IDAWs needed to transfer 54762306a36Sopenharmony_ci * a specified amount of data 54862306a36Sopenharmony_ci * 54962306a36Sopenharmony_ci * @ccw: The Channel Command Word being translated 55062306a36Sopenharmony_ci * @cp: Channel Program being processed 55162306a36Sopenharmony_ci * 55262306a36Sopenharmony_ci * The ORB is examined, since it specifies what IDAWs could actually be 55362306a36Sopenharmony_ci * used by any CCW in the channel program, regardless of whether or not 55462306a36Sopenharmony_ci * the CCW actually does. An ORB that does not specify Format-2-IDAW 55562306a36Sopenharmony_ci * Control could still contain a CCW with an IDAL, which would be 55662306a36Sopenharmony_ci * Format-1 and thus only move 2K with each IDAW. Thus all CCWs within 55762306a36Sopenharmony_ci * the channel program must follow the same size requirements. 55862306a36Sopenharmony_ci */ 55962306a36Sopenharmony_cistatic int ccw_count_idaws(struct ccw1 *ccw, 56062306a36Sopenharmony_ci struct channel_program *cp) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci struct vfio_device *vdev = 56362306a36Sopenharmony_ci &container_of(cp, struct vfio_ccw_private, cp)->vdev; 56462306a36Sopenharmony_ci u64 iova; 56562306a36Sopenharmony_ci int size = cp->orb.cmd.c64 ? sizeof(u64) : sizeof(u32); 56662306a36Sopenharmony_ci int ret; 56762306a36Sopenharmony_ci int bytes = 1; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci if (ccw->count) 57062306a36Sopenharmony_ci bytes = ccw->count; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (ccw_is_idal(ccw)) { 57362306a36Sopenharmony_ci /* Read first IDAW to check its starting address. */ 57462306a36Sopenharmony_ci /* All subsequent IDAWs will be 2K- or 4K-aligned. */ 57562306a36Sopenharmony_ci ret = vfio_dma_rw(vdev, ccw->cda, &iova, size, false); 57662306a36Sopenharmony_ci if (ret) 57762306a36Sopenharmony_ci return ret; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci /* 58062306a36Sopenharmony_ci * Format-1 IDAWs only occupy the first 32 bits, 58162306a36Sopenharmony_ci * and bit 0 is always off. 58262306a36Sopenharmony_ci */ 58362306a36Sopenharmony_ci if (!cp->orb.cmd.c64) 58462306a36Sopenharmony_ci iova = iova >> 32; 58562306a36Sopenharmony_ci } else { 58662306a36Sopenharmony_ci iova = ccw->cda; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci /* Format-1 IDAWs operate on 2K each */ 59062306a36Sopenharmony_ci if (!cp->orb.cmd.c64) 59162306a36Sopenharmony_ci return idal_2k_nr_words((void *)iova, bytes); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci /* Using the 2K variant of Format-2 IDAWs? */ 59462306a36Sopenharmony_ci if (cp->orb.cmd.i2k) 59562306a36Sopenharmony_ci return idal_2k_nr_words((void *)iova, bytes); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci /* The 'usual' case is 4K Format-2 IDAWs */ 59862306a36Sopenharmony_ci return idal_nr_words((void *)iova, bytes); 59962306a36Sopenharmony_ci} 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_cistatic int ccwchain_fetch_ccw(struct ccw1 *ccw, 60262306a36Sopenharmony_ci struct page_array *pa, 60362306a36Sopenharmony_ci struct channel_program *cp) 60462306a36Sopenharmony_ci{ 60562306a36Sopenharmony_ci struct vfio_device *vdev = 60662306a36Sopenharmony_ci &container_of(cp, struct vfio_ccw_private, cp)->vdev; 60762306a36Sopenharmony_ci unsigned long *idaws; 60862306a36Sopenharmony_ci unsigned int *idaws_f1; 60962306a36Sopenharmony_ci int ret; 61062306a36Sopenharmony_ci int idaw_nr; 61162306a36Sopenharmony_ci int i; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci /* Calculate size of IDAL */ 61462306a36Sopenharmony_ci idaw_nr = ccw_count_idaws(ccw, cp); 61562306a36Sopenharmony_ci if (idaw_nr < 0) 61662306a36Sopenharmony_ci return idaw_nr; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci /* Allocate an IDAL from host storage */ 61962306a36Sopenharmony_ci idaws = get_guest_idal(ccw, cp, idaw_nr); 62062306a36Sopenharmony_ci if (IS_ERR(idaws)) { 62162306a36Sopenharmony_ci ret = PTR_ERR(idaws); 62262306a36Sopenharmony_ci goto out_init; 62362306a36Sopenharmony_ci } 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci /* 62662306a36Sopenharmony_ci * Allocate an array of pages to pin/translate. 62762306a36Sopenharmony_ci * The number of pages is actually the count of the idaws 62862306a36Sopenharmony_ci * required for the data transfer, since we only only support 62962306a36Sopenharmony_ci * 4K IDAWs today. 63062306a36Sopenharmony_ci */ 63162306a36Sopenharmony_ci ret = page_array_alloc(pa, idaw_nr); 63262306a36Sopenharmony_ci if (ret < 0) 63362306a36Sopenharmony_ci goto out_free_idaws; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci /* 63662306a36Sopenharmony_ci * Copy guest IDAWs into page_array, in case the memory they 63762306a36Sopenharmony_ci * occupy is not contiguous. 63862306a36Sopenharmony_ci */ 63962306a36Sopenharmony_ci idaws_f1 = (unsigned int *)idaws; 64062306a36Sopenharmony_ci for (i = 0; i < idaw_nr; i++) { 64162306a36Sopenharmony_ci if (cp->orb.cmd.c64) 64262306a36Sopenharmony_ci pa->pa_iova[i] = idaws[i]; 64362306a36Sopenharmony_ci else 64462306a36Sopenharmony_ci pa->pa_iova[i] = idaws_f1[i]; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (ccw_does_data_transfer(ccw)) { 64862306a36Sopenharmony_ci ret = page_array_pin(pa, vdev, idal_is_2k(cp)); 64962306a36Sopenharmony_ci if (ret < 0) 65062306a36Sopenharmony_ci goto out_unpin; 65162306a36Sopenharmony_ci } else { 65262306a36Sopenharmony_ci pa->pa_nr = 0; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci ccw->cda = (__u32) virt_to_phys(idaws); 65662306a36Sopenharmony_ci ccw->flags |= CCW_FLAG_IDA; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci /* Populate the IDAL with pinned/translated addresses from page */ 65962306a36Sopenharmony_ci page_array_idal_create_words(pa, idaws); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci return 0; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ciout_unpin: 66462306a36Sopenharmony_ci page_array_unpin_free(pa, vdev, idal_is_2k(cp)); 66562306a36Sopenharmony_ciout_free_idaws: 66662306a36Sopenharmony_ci kfree(idaws); 66762306a36Sopenharmony_ciout_init: 66862306a36Sopenharmony_ci ccw->cda = 0; 66962306a36Sopenharmony_ci return ret; 67062306a36Sopenharmony_ci} 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci/* 67362306a36Sopenharmony_ci * Fetch one ccw. 67462306a36Sopenharmony_ci * To reduce memory copy, we'll pin the cda page in memory, 67562306a36Sopenharmony_ci * and to get rid of the cda 2G limitation of ccw1, we'll translate 67662306a36Sopenharmony_ci * direct ccws to idal ccws. 67762306a36Sopenharmony_ci */ 67862306a36Sopenharmony_cistatic int ccwchain_fetch_one(struct ccw1 *ccw, 67962306a36Sopenharmony_ci struct page_array *pa, 68062306a36Sopenharmony_ci struct channel_program *cp) 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci{ 68362306a36Sopenharmony_ci if (ccw_is_tic(ccw)) 68462306a36Sopenharmony_ci return ccwchain_fetch_tic(ccw, cp); 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci return ccwchain_fetch_ccw(ccw, pa, cp); 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci/** 69062306a36Sopenharmony_ci * cp_init() - allocate ccwchains for a channel program. 69162306a36Sopenharmony_ci * @cp: channel_program on which to perform the operation 69262306a36Sopenharmony_ci * @orb: control block for the channel program from the guest 69362306a36Sopenharmony_ci * 69462306a36Sopenharmony_ci * This creates one or more ccwchain(s), and copies the raw data of 69562306a36Sopenharmony_ci * the target channel program from @orb->cmd.iova to the new ccwchain(s). 69662306a36Sopenharmony_ci * 69762306a36Sopenharmony_ci * Limitations: 69862306a36Sopenharmony_ci * 1. Supports idal(c64) ccw chaining. 69962306a36Sopenharmony_ci * 2. Supports 4k idaw. 70062306a36Sopenharmony_ci * 70162306a36Sopenharmony_ci * Returns: 70262306a36Sopenharmony_ci * %0 on success and a negative error value on failure. 70362306a36Sopenharmony_ci */ 70462306a36Sopenharmony_ciint cp_init(struct channel_program *cp, union orb *orb) 70562306a36Sopenharmony_ci{ 70662306a36Sopenharmony_ci struct vfio_device *vdev = 70762306a36Sopenharmony_ci &container_of(cp, struct vfio_ccw_private, cp)->vdev; 70862306a36Sopenharmony_ci /* custom ratelimit used to avoid flood during guest IPL */ 70962306a36Sopenharmony_ci static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 1); 71062306a36Sopenharmony_ci int ret; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci /* this is an error in the caller */ 71362306a36Sopenharmony_ci if (cp->initialized) 71462306a36Sopenharmony_ci return -EBUSY; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci /* 71762306a36Sopenharmony_ci * We only support prefetching the channel program. We assume all channel 71862306a36Sopenharmony_ci * programs executed by supported guests likewise support prefetching. 71962306a36Sopenharmony_ci * Executing a channel program that does not specify prefetching will 72062306a36Sopenharmony_ci * typically not cause an error, but a warning is issued to help identify 72162306a36Sopenharmony_ci * the problem if something does break. 72262306a36Sopenharmony_ci */ 72362306a36Sopenharmony_ci if (!orb->cmd.pfch && __ratelimit(&ratelimit_state)) 72462306a36Sopenharmony_ci dev_warn( 72562306a36Sopenharmony_ci vdev->dev, 72662306a36Sopenharmony_ci "Prefetching channel program even though prefetch not specified in ORB"); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci INIT_LIST_HEAD(&cp->ccwchain_list); 72962306a36Sopenharmony_ci memcpy(&cp->orb, orb, sizeof(*orb)); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci /* Build a ccwchain for the first CCW segment */ 73262306a36Sopenharmony_ci ret = ccwchain_handle_ccw(orb->cmd.cpa, cp); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci if (!ret) 73562306a36Sopenharmony_ci cp->initialized = true; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci return ret; 73862306a36Sopenharmony_ci} 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci/** 74262306a36Sopenharmony_ci * cp_free() - free resources for channel program. 74362306a36Sopenharmony_ci * @cp: channel_program on which to perform the operation 74462306a36Sopenharmony_ci * 74562306a36Sopenharmony_ci * This unpins the memory pages and frees the memory space occupied by 74662306a36Sopenharmony_ci * @cp, which must have been returned by a previous call to cp_init(). 74762306a36Sopenharmony_ci * Otherwise, undefined behavior occurs. 74862306a36Sopenharmony_ci */ 74962306a36Sopenharmony_civoid cp_free(struct channel_program *cp) 75062306a36Sopenharmony_ci{ 75162306a36Sopenharmony_ci struct vfio_device *vdev = 75262306a36Sopenharmony_ci &container_of(cp, struct vfio_ccw_private, cp)->vdev; 75362306a36Sopenharmony_ci struct ccwchain *chain, *temp; 75462306a36Sopenharmony_ci int i; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci if (!cp->initialized) 75762306a36Sopenharmony_ci return; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci cp->initialized = false; 76062306a36Sopenharmony_ci list_for_each_entry_safe(chain, temp, &cp->ccwchain_list, next) { 76162306a36Sopenharmony_ci for (i = 0; i < chain->ch_len; i++) { 76262306a36Sopenharmony_ci page_array_unpin_free(&chain->ch_pa[i], vdev, idal_is_2k(cp)); 76362306a36Sopenharmony_ci ccwchain_cda_free(chain, i); 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci ccwchain_free(chain); 76662306a36Sopenharmony_ci } 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci/** 77062306a36Sopenharmony_ci * cp_prefetch() - translate a guest physical address channel program to 77162306a36Sopenharmony_ci * a real-device runnable channel program. 77262306a36Sopenharmony_ci * @cp: channel_program on which to perform the operation 77362306a36Sopenharmony_ci * 77462306a36Sopenharmony_ci * This function translates the guest-physical-address channel program 77562306a36Sopenharmony_ci * and stores the result to ccwchain list. @cp must have been 77662306a36Sopenharmony_ci * initialized by a previous call with cp_init(). Otherwise, undefined 77762306a36Sopenharmony_ci * behavior occurs. 77862306a36Sopenharmony_ci * For each chain composing the channel program: 77962306a36Sopenharmony_ci * - On entry ch_len holds the count of CCWs to be translated. 78062306a36Sopenharmony_ci * - On exit ch_len is adjusted to the count of successfully translated CCWs. 78162306a36Sopenharmony_ci * This allows cp_free to find in ch_len the count of CCWs to free in a chain. 78262306a36Sopenharmony_ci * 78362306a36Sopenharmony_ci * The S/390 CCW Translation APIS (prefixed by 'cp_') are introduced 78462306a36Sopenharmony_ci * as helpers to do ccw chain translation inside the kernel. Basically 78562306a36Sopenharmony_ci * they accept a channel program issued by a virtual machine, and 78662306a36Sopenharmony_ci * translate the channel program to a real-device runnable channel 78762306a36Sopenharmony_ci * program. 78862306a36Sopenharmony_ci * 78962306a36Sopenharmony_ci * These APIs will copy the ccws into kernel-space buffers, and update 79062306a36Sopenharmony_ci * the guest physical addresses with their corresponding host physical 79162306a36Sopenharmony_ci * addresses. Then channel I/O device drivers could issue the 79262306a36Sopenharmony_ci * translated channel program to real devices to perform an I/O 79362306a36Sopenharmony_ci * operation. 79462306a36Sopenharmony_ci * 79562306a36Sopenharmony_ci * These interfaces are designed to support translation only for 79662306a36Sopenharmony_ci * channel programs, which are generated and formatted by a 79762306a36Sopenharmony_ci * guest. Thus this will make it possible for things like VFIO to 79862306a36Sopenharmony_ci * leverage the interfaces to passthrough a channel I/O mediated 79962306a36Sopenharmony_ci * device in QEMU. 80062306a36Sopenharmony_ci * 80162306a36Sopenharmony_ci * We support direct ccw chaining by translating them to idal ccws. 80262306a36Sopenharmony_ci * 80362306a36Sopenharmony_ci * Returns: 80462306a36Sopenharmony_ci * %0 on success and a negative error value on failure. 80562306a36Sopenharmony_ci */ 80662306a36Sopenharmony_ciint cp_prefetch(struct channel_program *cp) 80762306a36Sopenharmony_ci{ 80862306a36Sopenharmony_ci struct ccwchain *chain; 80962306a36Sopenharmony_ci struct ccw1 *ccw; 81062306a36Sopenharmony_ci struct page_array *pa; 81162306a36Sopenharmony_ci int len, idx, ret; 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci /* this is an error in the caller */ 81462306a36Sopenharmony_ci if (!cp->initialized) 81562306a36Sopenharmony_ci return -EINVAL; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci list_for_each_entry(chain, &cp->ccwchain_list, next) { 81862306a36Sopenharmony_ci len = chain->ch_len; 81962306a36Sopenharmony_ci for (idx = 0; idx < len; idx++) { 82062306a36Sopenharmony_ci ccw = &chain->ch_ccw[idx]; 82162306a36Sopenharmony_ci pa = &chain->ch_pa[idx]; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci ret = ccwchain_fetch_one(ccw, pa, cp); 82462306a36Sopenharmony_ci if (ret) 82562306a36Sopenharmony_ci goto out_err; 82662306a36Sopenharmony_ci } 82762306a36Sopenharmony_ci } 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci return 0; 83062306a36Sopenharmony_ciout_err: 83162306a36Sopenharmony_ci /* Only cleanup the chain elements that were actually translated. */ 83262306a36Sopenharmony_ci chain->ch_len = idx; 83362306a36Sopenharmony_ci list_for_each_entry_continue(chain, &cp->ccwchain_list, next) { 83462306a36Sopenharmony_ci chain->ch_len = 0; 83562306a36Sopenharmony_ci } 83662306a36Sopenharmony_ci return ret; 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci/** 84062306a36Sopenharmony_ci * cp_get_orb() - get the orb of the channel program 84162306a36Sopenharmony_ci * @cp: channel_program on which to perform the operation 84262306a36Sopenharmony_ci * @sch: subchannel the operation will be performed against 84362306a36Sopenharmony_ci * 84462306a36Sopenharmony_ci * This function returns the address of the updated orb of the channel 84562306a36Sopenharmony_ci * program. Channel I/O device drivers could use this orb to issue a 84662306a36Sopenharmony_ci * ssch. 84762306a36Sopenharmony_ci */ 84862306a36Sopenharmony_ciunion orb *cp_get_orb(struct channel_program *cp, struct subchannel *sch) 84962306a36Sopenharmony_ci{ 85062306a36Sopenharmony_ci union orb *orb; 85162306a36Sopenharmony_ci struct ccwchain *chain; 85262306a36Sopenharmony_ci struct ccw1 *cpa; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci /* this is an error in the caller */ 85562306a36Sopenharmony_ci if (!cp->initialized) 85662306a36Sopenharmony_ci return NULL; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci orb = &cp->orb; 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci orb->cmd.intparm = (u32)virt_to_phys(sch); 86162306a36Sopenharmony_ci orb->cmd.fmt = 1; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci /* 86462306a36Sopenharmony_ci * Everything built by vfio-ccw is a Format-2 IDAL. 86562306a36Sopenharmony_ci * If the input was a Format-1 IDAL, indicate that 86662306a36Sopenharmony_ci * 2K Format-2 IDAWs were created here. 86762306a36Sopenharmony_ci */ 86862306a36Sopenharmony_ci if (!orb->cmd.c64) 86962306a36Sopenharmony_ci orb->cmd.i2k = 1; 87062306a36Sopenharmony_ci orb->cmd.c64 = 1; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci if (orb->cmd.lpm == 0) 87362306a36Sopenharmony_ci orb->cmd.lpm = sch->lpm; 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci chain = list_first_entry(&cp->ccwchain_list, struct ccwchain, next); 87662306a36Sopenharmony_ci cpa = chain->ch_ccw; 87762306a36Sopenharmony_ci orb->cmd.cpa = (__u32)virt_to_phys(cpa); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci return orb; 88062306a36Sopenharmony_ci} 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci/** 88362306a36Sopenharmony_ci * cp_update_scsw() - update scsw for a channel program. 88462306a36Sopenharmony_ci * @cp: channel_program on which to perform the operation 88562306a36Sopenharmony_ci * @scsw: I/O results of the channel program and also the target to be 88662306a36Sopenharmony_ci * updated 88762306a36Sopenharmony_ci * 88862306a36Sopenharmony_ci * @scsw contains the I/O results of the channel program that pointed 88962306a36Sopenharmony_ci * to by @cp. However what @scsw->cpa stores is a host physical 89062306a36Sopenharmony_ci * address, which is meaningless for the guest, which is waiting for 89162306a36Sopenharmony_ci * the I/O results. 89262306a36Sopenharmony_ci * 89362306a36Sopenharmony_ci * This function updates @scsw->cpa to its coressponding guest physical 89462306a36Sopenharmony_ci * address. 89562306a36Sopenharmony_ci */ 89662306a36Sopenharmony_civoid cp_update_scsw(struct channel_program *cp, union scsw *scsw) 89762306a36Sopenharmony_ci{ 89862306a36Sopenharmony_ci struct ccwchain *chain; 89962306a36Sopenharmony_ci u32 cpa = scsw->cmd.cpa; 90062306a36Sopenharmony_ci u32 ccw_head; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci if (!cp->initialized) 90362306a36Sopenharmony_ci return; 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci /* 90662306a36Sopenharmony_ci * LATER: 90762306a36Sopenharmony_ci * For now, only update the cmd.cpa part. We may need to deal with 90862306a36Sopenharmony_ci * other portions of the schib as well, even if we don't return them 90962306a36Sopenharmony_ci * in the ioctl directly. Path status changes etc. 91062306a36Sopenharmony_ci */ 91162306a36Sopenharmony_ci list_for_each_entry(chain, &cp->ccwchain_list, next) { 91262306a36Sopenharmony_ci ccw_head = (u32)(u64)chain->ch_ccw; 91362306a36Sopenharmony_ci /* 91462306a36Sopenharmony_ci * On successful execution, cpa points just beyond the end 91562306a36Sopenharmony_ci * of the chain. 91662306a36Sopenharmony_ci */ 91762306a36Sopenharmony_ci if (is_cpa_within_range(cpa, ccw_head, chain->ch_len + 1)) { 91862306a36Sopenharmony_ci /* 91962306a36Sopenharmony_ci * (cpa - ccw_head) is the offset value of the host 92062306a36Sopenharmony_ci * physical ccw to its chain head. 92162306a36Sopenharmony_ci * Adding this value to the guest physical ccw chain 92262306a36Sopenharmony_ci * head gets us the guest cpa. 92362306a36Sopenharmony_ci */ 92462306a36Sopenharmony_ci cpa = chain->ch_iova + (cpa - ccw_head); 92562306a36Sopenharmony_ci break; 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci } 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci scsw->cmd.cpa = cpa; 93062306a36Sopenharmony_ci} 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci/** 93362306a36Sopenharmony_ci * cp_iova_pinned() - check if an iova is pinned for a ccw chain. 93462306a36Sopenharmony_ci * @cp: channel_program on which to perform the operation 93562306a36Sopenharmony_ci * @iova: the iova to check 93662306a36Sopenharmony_ci * @length: the length to check from @iova 93762306a36Sopenharmony_ci * 93862306a36Sopenharmony_ci * If the @iova is currently pinned for the ccw chain, return true; 93962306a36Sopenharmony_ci * else return false. 94062306a36Sopenharmony_ci */ 94162306a36Sopenharmony_cibool cp_iova_pinned(struct channel_program *cp, u64 iova, u64 length) 94262306a36Sopenharmony_ci{ 94362306a36Sopenharmony_ci struct ccwchain *chain; 94462306a36Sopenharmony_ci int i; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci if (!cp->initialized) 94762306a36Sopenharmony_ci return false; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci list_for_each_entry(chain, &cp->ccwchain_list, next) { 95062306a36Sopenharmony_ci for (i = 0; i < chain->ch_len; i++) 95162306a36Sopenharmony_ci if (page_array_iova_pinned(&chain->ch_pa[i], iova, length)) 95262306a36Sopenharmony_ci return true; 95362306a36Sopenharmony_ci } 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci return false; 95662306a36Sopenharmony_ci} 957