lkml.org 
[lkml]   [2020]   [Aug]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v10 05/16] s390/vfio-ap: implement in-use callback for vfio_ap driver
    Date
    Let's implement the callback to indicate when an APQN
    is in use by the vfio_ap device driver. The callback is
    invoked whenever a change to the apmask or aqmask would
    result in one or more queue devices being removed from the driver. The
    vfio_ap device driver will indicate a resource is in use
    if the APQN of any of the queue devices to be removed are assigned to
    any of the matrix mdevs under the driver's control.

    Signed-off-by: Tony Krowiak <akrowiak@linux.ibm.com>
    ---
    drivers/s390/crypto/vfio_ap_drv.c | 1 +
    drivers/s390/crypto/vfio_ap_ops.c | 68 ++++++++++++++++++++-------
    drivers/s390/crypto/vfio_ap_private.h | 2 +
    3 files changed, 53 insertions(+), 18 deletions(-)

    diff --git a/drivers/s390/crypto/vfio_ap_drv.c b/drivers/s390/crypto/vfio_ap_drv.c
    index 24cdef60039a..aae5b3d8e3fa 100644
    --- a/drivers/s390/crypto/vfio_ap_drv.c
    +++ b/drivers/s390/crypto/vfio_ap_drv.c
    @@ -175,6 +175,7 @@ static int __init vfio_ap_init(void)
    memset(&vfio_ap_drv, 0, sizeof(vfio_ap_drv));
    vfio_ap_drv.probe = vfio_ap_queue_dev_probe;
    vfio_ap_drv.remove = vfio_ap_queue_dev_remove;
    + vfio_ap_drv.in_use = vfio_ap_mdev_resource_in_use;
    vfio_ap_drv.ids = ap_queue_ids;

    ret = ap_driver_register(&vfio_ap_drv, THIS_MODULE, VFIO_AP_DRV_NAME);
    diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
    index 2e37ee82e422..fc1aa6f947eb 100644
    --- a/drivers/s390/crypto/vfio_ap_ops.c
    +++ b/drivers/s390/crypto/vfio_ap_ops.c
    @@ -515,18 +515,36 @@ vfio_ap_mdev_verify_queues_reserved_for_apid(struct ap_matrix_mdev *matrix_mdev,
    return 0;
    }

    +#define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \
    + "already assigned to %s"
    +
    +static void vfio_ap_mdev_log_sharing_err(const char *mdev_name,
    + unsigned long *apm,
    + unsigned long *aqm)
    +{
    + unsigned long apid, apqi;
    +
    + for_each_set_bit_inv(apid, apm, AP_DEVICES)
    + for_each_set_bit_inv(apqi, aqm, AP_DOMAINS)
    + pr_err(MDEV_SHARING_ERR, apid, apqi, mdev_name);
    +}
    +
    /**
    * vfio_ap_mdev_verify_no_sharing
    *
    * Verifies that the APQNs derived from the cross product of the AP adapter IDs
    - * and AP queue indexes comprising the AP matrix are not configured for another
    + * and AP queue indexes comprising an AP matrix are not assigned to another
    * mediated device. AP queue sharing is not allowed.
    *
    * @matrix_mdev: the mediated matrix device
    + * @mdev_apm: mask indicating the APIDs of the APQNs to be verified
    + * @mdev_aqm: mask indicating the APQIs of the APQNs to be verified
    *
    * Returns 0 if the APQNs are not shared, otherwise; returns -EADDRINUSE.
    */
    -static int vfio_ap_mdev_verify_no_sharing(struct ap_matrix_mdev *matrix_mdev)
    +static int vfio_ap_mdev_verify_no_sharing(struct ap_matrix_mdev *matrix_mdev,
    + unsigned long *mdev_apm,
    + unsigned long *mdev_aqm)
    {
    struct ap_matrix_mdev *lstdev;
    DECLARE_BITMAP(apm, AP_DEVICES);
    @@ -543,14 +561,15 @@ static int vfio_ap_mdev_verify_no_sharing(struct ap_matrix_mdev *matrix_mdev)
    * We work on full longs, as we can only exclude the leftover
    * bits in non-inverse order. The leftover is all zeros.
    */
    - if (!bitmap_and(apm, matrix_mdev->matrix.apm,
    - lstdev->matrix.apm, AP_DEVICES))
    + if (!bitmap_and(apm, mdev_apm, lstdev->matrix.apm, AP_DEVICES))
    continue;

    - if (!bitmap_and(aqm, matrix_mdev->matrix.aqm,
    - lstdev->matrix.aqm, AP_DOMAINS))
    + if (!bitmap_and(aqm, mdev_aqm, lstdev->matrix.aqm, AP_DOMAINS))
    continue;

    + vfio_ap_mdev_log_sharing_err(dev_name(mdev_dev(lstdev->mdev)),
    + apm, aqm);
    +
    return -EADDRINUSE;
    }

    @@ -676,6 +695,7 @@ static ssize_t assign_adapter_store(struct device *dev,
    {
    int ret;
    unsigned long apid;
    + DECLARE_BITMAP(apm, AP_DEVICES);
    struct mdev_device *mdev = mdev_from_dev(dev);
    struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);

    @@ -701,18 +721,18 @@ static ssize_t assign_adapter_store(struct device *dev,
    if (ret)
    goto done;

    - set_bit_inv(apid, matrix_mdev->matrix.apm);
    + memset(apm, 0, sizeof(apm));
    + set_bit_inv(apid, apm);

    - ret = vfio_ap_mdev_verify_no_sharing(matrix_mdev);
    + ret = vfio_ap_mdev_verify_no_sharing(matrix_mdev, apm,
    + matrix_mdev->matrix.aqm);
    if (ret)
    - goto share_err;
    + goto done;

    + set_bit_inv(apid, matrix_mdev->matrix.apm);
    vfio_ap_mdev_link_queues(matrix_mdev, LINK_APID, apid);
    ret = count;
    - goto done;

    -share_err:
    - clear_bit_inv(apid, matrix_mdev->matrix.apm);
    done:
    mutex_unlock(&matrix_dev->lock);

    @@ -824,6 +844,7 @@ static ssize_t assign_domain_store(struct device *dev,
    {
    int ret;
    unsigned long apqi;
    + DECLARE_BITMAP(aqm, AP_DOMAINS);
    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;
    @@ -844,18 +865,18 @@ static ssize_t assign_domain_store(struct device *dev,
    if (ret)
    goto done;

    - set_bit_inv(apqi, matrix_mdev->matrix.aqm);
    + memset(aqm, 0, sizeof(aqm));
    + set_bit_inv(apqi, aqm);

    - ret = vfio_ap_mdev_verify_no_sharing(matrix_mdev);
    + ret = vfio_ap_mdev_verify_no_sharing(matrix_mdev,
    + matrix_mdev->matrix.apm, aqm);
    if (ret)
    - goto share_err;
    + goto done;

    + set_bit_inv(apqi, matrix_mdev->matrix.aqm);
    vfio_ap_mdev_link_queues(matrix_mdev, LINK_APQI, apqi);
    ret = count;
    - goto done;

    -share_err:
    - clear_bit_inv(apqi, matrix_mdev->matrix.aqm);
    done:
    mutex_unlock(&matrix_dev->lock);

    @@ -1434,3 +1455,14 @@ void vfio_ap_mdev_remove_queue(struct ap_queue *queue)
    kfree(q);
    mutex_unlock(&matrix_dev->lock);
    }
    +
    +bool vfio_ap_mdev_resource_in_use(unsigned long *apm, unsigned long *aqm)
    +{
    + bool in_use;
    +
    + mutex_lock(&matrix_dev->lock);
    + in_use = !!vfio_ap_mdev_verify_no_sharing(NULL, apm, aqm);
    + mutex_unlock(&matrix_dev->lock);
    +
    + return in_use;
    +}
    diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
    index 57da703b549a..0c796ef11426 100644
    --- a/drivers/s390/crypto/vfio_ap_private.h
    +++ b/drivers/s390/crypto/vfio_ap_private.h
    @@ -105,4 +105,6 @@ struct vfio_ap_queue {
    int vfio_ap_mdev_probe_queue(struct ap_queue *queue);
    void vfio_ap_mdev_remove_queue(struct ap_queue *queue);

    +bool vfio_ap_mdev_resource_in_use(unsigned long *apm, unsigned long *aqm);
    +
    #endif /* _VFIO_AP_PRIVATE_H_ */
    --
    2.21.1
    \
     
     \ /
      Last update: 2020-08-21 22:00    [W:3.255 / U:1.528 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site