Received: by 10.192.165.148 with SMTP id m20csp3197539imm; Mon, 7 May 2018 08:13:53 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpxbccj98BwCgqPwOcCXR3zjFpsbxgvgteLAboTQ61cPZMDD9EZU2ai7CM4+bWPXubK/gOK X-Received: by 2002:a9d:2cf9:: with SMTP id e54-v6mr12096773otd.81.1525706033338; Mon, 07 May 2018 08:13:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525706033; cv=none; d=google.com; s=arc-20160816; b=0jB6VYCHdg4UIol8g0JUFqO0MSaizb7DBcE1hdH7Wu+OwqdjRcD7H5HNJZdPKEjr0K CaH/UCmqI1+cOY7wV8EG8N9m0Icu1FBUYqFQnAbmW/AYOFx/V5tdZWfmtABa50xg99M9 im8EeNrnzkx6RYWB0XyfwUYe4JTuCoBka3dgSa0L+43mE9V8s5vjBGRUHJBkRo3dR4o8 3whyOl1B7Vw0dXUqA/I1nw7mVFj7keoR0koQ4vKl39PBGd0wHSCMw7pzihCWKvep5Ue1 PKokv9BrFbaooGOV2F6LZ+HXBP8SZwA6Wu7wI0i4EW9Tql3Qwd1q0eSQ7bwhEr9fHDlz KPPw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:references:in-reply-to:date :subject:cc:to:from:arc-authentication-results; bh=mN6Pt2GJ5mdcG+489T6laCjRCvhL1xC8bkyU7YU9/s4=; b=WzkuWVUgScb0VWbHxVUxHGddmN+PSJso15SURhbsphrZhyhhVaZTPxIk9dmNYH5VHv U9XXig880nm9cOjMzfRaCGM9ExdH9AwLsTVjf1YAopj3BPT/6SzwnYIlLGzjV/Wi2l0I 46ai2bdzfjNdQSkCHRi1An5rc282xdQ5qaV2MzNHJJ5qHlQLF1jjNKUWKRmE56iSGef0 p+Od4N0P68e4ZQLmUN2c/bIp/pKhBbrfaeic3fYx7tH5aPwD2gBq/Jq6yjNM+hTOiiZ9 2s/9kR1cWWucQsd7e/7Q8LLFdJjiGHTRQGR2MnCdLeXEl7YbNGgzyEkELFTpmoEbCZEw uETA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p26-v6si8502942otb.142.2018.05.07.08.13.39; Mon, 07 May 2018 08:13:53 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752561AbeEGPMl (ORCPT + 99 others); Mon, 7 May 2018 11:12:41 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:49750 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752466AbeEGPMd (ORCPT ); Mon, 7 May 2018 11:12:33 -0400 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w47F9Gwq140070 for ; Mon, 7 May 2018 11:12:32 -0400 Received: from e34.co.us.ibm.com (e34.co.us.ibm.com [32.97.110.152]) by mx0a-001b2d01.pphosted.com with ESMTP id 2htqduwdes-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 07 May 2018 11:12:32 -0400 Received: from localhost by e34.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 7 May 2018 09:12:31 -0600 Received: from b03cxnp08027.gho.boulder.ibm.com (9.17.130.19) by e34.co.us.ibm.com (192.168.1.134) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 7 May 2018 09:12:27 -0600 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp08027.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w47FCQTY4391328; Mon, 7 May 2018 08:12:26 -0700 Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 174DDC6051; Mon, 7 May 2018 09:12:26 -0600 (MDT) Received: from localhost.localdomain (unknown [9.85.146.27]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTPS id C3A62C603C; Mon, 7 May 2018 09:12:23 -0600 (MDT) From: Tony Krowiak To: linux-s390@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: freude@de.ibm.com, schwidefsky@de.ibm.com, heiko.carstens@de.ibm.com, borntraeger@de.ibm.com, cohuck@redhat.com, kwankhede@nvidia.com, bjsdjshi@linux.vnet.ibm.com, pbonzini@redhat.com, alex.williamson@redhat.com, pmorel@linux.vnet.ibm.com, alifm@linux.vnet.ibm.com, mjrosato@linux.vnet.ibm.com, jjherne@linux.vnet.ibm.com, thuth@redhat.com, pasic@linux.vnet.ibm.com, berrange@redhat.com, fiuczy@linux.vnet.ibm.com, buendgen@de.ibm.com, akrowiak@linux.vnet.ibm.com Subject: [PATCH v5 08/13] s390: vfio-ap: sysfs interfaces to configure domains Date: Mon, 7 May 2018 11:11:47 -0400 X-Mailer: git-send-email 1.7.1 In-Reply-To: <1525705912-12815-1-git-send-email-akrowiak@linux.vnet.ibm.com> References: <1525705912-12815-1-git-send-email-akrowiak@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18050715-0016-0000-0000-000008AC40C0 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008987; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000258; SDB=6.01028858; UDB=6.00525678; IPR=6.00807992; MB=3.00020972; MTD=3.00000008; XFM=3.00000015; UTC=2018-05-07 15:12:30 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18050715-0017-0000-0000-00003E987A6B Message-Id: <1525705912-12815-9-git-send-email-akrowiak@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-05-07_06:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1805070154 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Provides the sysfs interfaces for assigning AP domains to and unassigning AP domains from a mediated matrix device. An AP domain ID corresponds to an AP queue index (APQI). For each domain assigned to the mediated matrix device, its corresponging APQI is stored in an AP queue mask (AQM). The bits in the AQM, from most significant to least significant bit, correspond to AP domain numbers 0 to 255. When a domain is assigned, the bit corresponding to its APQI will be set in the AQM. Likewise, when a domain is unassigned, the bit corresponding to its APQI will be cleared from the AQM. The relevant sysfs structures are: /sys/devices/vfio_ap ... [matrix] ...... [mdev_supported_types] ......... [vfio_ap-passthrough] ............ [devices] ...............[$uuid] .................. assign_domain .................. unassign_domain To assign a domain to the $uuid mediated matrix device, write the domain's ID to the assign_domain file. To unassign a domain, write the domain's ID to the unassign_domain file. The ID is specified using conventional semantics: If it begins with 0x, the number will be parsed as a hexadecimal (case insensitive) number; if it begins with 0, it will be parsed as an octal number; otherwise, it will be parsed as a decimal number. For example, to assign domain 173 (0xad) to the mediated matrix device $uuid: echo 173 > assign_domain or echo 0255 > assign_domain or echo 0xad > assign_domain To unassign domain 173 (0xad): echo 173 > unassign_domain or echo 0255 > unassign_domain or echo 0xad > unassign_domain The assignment will be rejected: * If the domain ID exceeds the maximum value for an AP domain: * If the AP Extended Addressing (APXA) facility is installed, the max value is 255 * Else the max value is 15 * If no AP adapters have yet been assigned and there are no AP queues reserved by the VFIO AP driver that have an APQN with an APQI matching that of the AP domain number being assigned. * If any of the APQNs that can be derived from the intersection of the APQI being assigned and the AP adapter ID (APID) of each of the AP adapters previously assigned can not be matched with an APQN of an AP queue device reserved by the VFIO AP driver. Signed-off-by: Tony Krowiak --- drivers/s390/crypto/vfio_ap_ops.c | 228 ++++++++++++++++++++++++++++++++++++- 1 files changed, 227 insertions(+), 1 deletions(-) diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index 914274d..5c232de 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -381,10 +381,236 @@ static ssize_t unassign_adapter_store(struct device *dev, } DEVICE_ATTR_WO(unassign_adapter); +/** + * vfio_ap_validate_queues_for_apqi + * + * @ap_matrix: the matrix device + * @matrix_mdev: the mediated matrix device + * @apqi: an AP queue index (APQI) - corresponds to a domain ID + * + * Verifies that each APQN that is derived from the intersection of @apqi and + * each AP adapter ID (APID) corresponding to an AP domain assigned to the + * @matrix_mdev matches the APQN of an AP queue reserved by the VFIO AP device + * driver. + * + * Returns 0 if validation succeeds; otherwise, returns an error. + */ +static int vfio_ap_validate_queues_for_apqi(struct ap_matrix *ap_matrix, + struct ap_matrix_mdev *matrix_mdev, + unsigned long apqi) +{ + int ret; + struct vfio_ap_qid_match qid_match; + unsigned long apid; + unsigned long nbits = matrix_mdev->matrix.apm_max + 1; + struct device_driver *drv = ap_matrix->device.driver; + + /** + * Examine each APQN with the specified APQI + */ + for_each_set_bit_inv(apid, matrix_mdev->matrix.apm, nbits) { + qid_match.qid = AP_MKQID(apid, apqi); + qid_match.dev = NULL; + + ret = driver_for_each_device(drv, NULL, &qid_match, + vfio_ap_queue_match); + if (ret) { + pr_err("%s: %s: error %d validating AP queue %02lx.%04lx reservation", + VFIO_AP_MODULE_NAME, __func__, ret, apid, apqi); + + return ret; + } + + /* + * If the APQN identifies an AP queue that is reserved by the + * VFIO AP device driver, continue processing. + */ + if (qid_match.dev) + continue; + + pr_err("%s: %s: AP queue %02lx.%04lx not reserved by %s driver", + VFIO_AP_MODULE_NAME, __func__, apid, apqi, + VFIO_AP_DRV_NAME); + + return -ENXIO; + } + + return 0; +} + +struct vfio_ap_apqi_reserved { + unsigned long apqi; + bool reserved; +}; + +/** + * vfio_ap_queue_id_contains_apqi + * + * @dev: an AP queue device + * @data: an AP queue index (APQI) + * + * Returns 1 (true) if the APQI (@data) is contained in the AP queue's + * identifier; otherwise, returns 0; + */ +static int vfio_ap_queue_id_contains_apqi(struct device *dev, void *data) +{ + struct vfio_ap_apqi_reserved *apqi_res = data; + struct ap_queue *ap_queue = to_ap_queue(dev); + + if (apqi_res->apqi == AP_QID_QUEUE(ap_queue->qid)) + apqi_res->reserved = true; + + return 0; +} + +/** + * vfio_ap_verify_apqi_reserved + * + * @ap_matrix: the AP matrix configured for the mediated matrix device + * @apqi: the AP queue index (APQI) - corresponds to domain ID + * + * Verifies that at least one AP queue reserved by the VFIO AP device driver + * has an APQN containing @apqi. + * + * Returns 0 if the APQI is reserved; otherwise, returns -ENODEV. + */ +static int vfio_ap_verify_apqi_reserved(struct ap_matrix *ap_matrix, + unsigned long apqi) +{ + int ret; + struct vfio_ap_apqi_reserved apqi_res; + + apqi_res.apqi = apqi; + apqi_res.reserved = false; + + ret = driver_for_each_device(ap_matrix->device.driver, NULL, + &apqi_res, + vfio_ap_queue_id_contains_apqi); + if (ret) { + pr_err("%s: %s: error %d validating AP queue index %04lx reservation", + VFIO_AP_MODULE_NAME, __func__, ret, apqi); + return ret; + } + + if (apqi_res.reserved) + return 0; + + pr_err("%s: %s: no APQNs with domain ID %lu(%02lx) are reserved by %s driver", + VFIO_AP_MODULE_NAME, __func__, apqi, apqi, VFIO_AP_DRV_NAME); + + return -ENODEV; +} + +/** + * vfio_ap_validate_apqi + * + * @matrix_mdev: the mediated matrix device + * @apqi: the APQI (domain ID) to validate + * + * Validates the value of @apqi: + * * If there are no AP adapters assigned, then there must be at least + * one AP queue device reserved by the VFIO AP device driver with an + * APQN containing @apqi. + * + * * Else each APQN that can be derived from the intersection of @apqi and + * the IDs of the AP adapters already assigned must identify an AP queue + * that has been reserved by the VFIO AP device driver. + * + * Returns 0 if the value of @apqi is valid; otherwise, returns an error. + */ +static int vfio_ap_validate_apqi(struct mdev_device *mdev, + struct ap_matrix_mdev *matrix_mdev, + unsigned long apqi) +{ + int ret; + struct device *dev = mdev_parent_dev(mdev); + struct ap_matrix *ap_matrix = to_ap_matrix(dev); + unsigned long apid; + unsigned long max_apid = matrix_mdev->matrix.apm_max; + + apid = find_first_bit_inv(matrix_mdev->matrix.apm, max_apid + 1); + /* If there are no adapters assigned */ + if (apid > max_apid) { + ret = vfio_ap_verify_apqi_reserved(ap_matrix, apqi); + } else { + ret = vfio_ap_validate_queues_for_apqi(ap_matrix, matrix_mdev, + apqi); + } + + if (ret) + return ret; + + return 0; +} + +static ssize_t assign_domain_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + unsigned long apqi; + struct mdev_device *mdev = mdev_from_dev(dev); + struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev); + unsigned long max_apqi = matrix_mdev->matrix.aqm_max; + + ret = kstrtoul(buf, 0, &apqi); + if (ret || (apqi > max_apqi)) { + pr_err("%s: %s: domain id '%s' not a value from 0 to %02lu(%#04lx)", + VFIO_AP_MODULE_NAME, __func__, buf, max_apqi, max_apqi); + + return ret ? ret : -EINVAL; + } + + ret = vfio_ap_validate_apqi(mdev, matrix_mdev, apqi); + if (ret) + return ret; + + /* Set the bit in the AQM (bitmask) corresponding to the AP domain + * number (APQI). The bits in the mask, from most significant to least + * significant, correspond to numbers 0-255. + */ + set_bit_inv(apqi, matrix_mdev->matrix.aqm); + + return count; +} +DEVICE_ATTR_WO(assign_domain); + +static ssize_t unassign_domain_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + unsigned long apqi; + struct mdev_device *mdev = mdev_from_dev(dev); + struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev); + unsigned long max_apqi = matrix_mdev->matrix.aqm_max; + + ret = kstrtoul(buf, 0, &apqi); + if (ret || (apqi > max_apqi)) { + pr_err("%s: %s: domain id '%s' not a value from 0 to %02lu(%#04lx)", + VFIO_AP_MODULE_NAME, __func__, buf, max_apqi, max_apqi); + + return ret ? ret : -EINVAL; + } + + if (!test_bit_inv(apqi, matrix_mdev->matrix.aqm)) { + pr_err("%s: %s: domain %02lu(%#04lx) not assigned", + VFIO_AP_MODULE_NAME, __func__, apqi, apqi); + return -ENODEV; + } + + clear_bit_inv((unsigned long)apqi, matrix_mdev->matrix.aqm); + + return count; +} +DEVICE_ATTR_WO(unassign_domain); + static struct attribute *vfio_ap_mdev_attrs[] = { &dev_attr_assign_adapter.attr, &dev_attr_unassign_adapter.attr, - NULL + &dev_attr_assign_domain.attr, + &dev_attr_unassign_domain.attr, + NULL, }; static struct attribute_group vfio_ap_mdev_attr_group = { -- 1.7.1