**Next message:**Tony Krowiak: "[PATCH v6 02/10] s390: vfio-ap: allow assignment of unavailable AP resources to mdev device"**Previous message:**Tony Krowiak: "[PATCH v6 07/10] s390: zcrypt: driver callback to indicate resource in use"**In reply to:**Tony Krowiak: "[PATCH v6 07/10] s390: zcrypt: driver callback to indicate resource in use"**Next in thread:**Tony Krowiak: "[PATCH v6 02/10] s390: vfio-ap: allow assignment of unavailable AP resources to mdev device"**Messages sorted by:**[ date ] [ thread ] [ subject ] [ author ]

When the vfio_ap device driver's probe callback is invoked to bind a

an AP queue device, if its APQN has been assigned to a matrix mdev that is

in use by a guest, the queue will be hot plugged into the guest's AP

configuration if:

1. Each APQN derived from the APID and the APQIs already set in the

guest's CRYCB references an AP queue device bound to the vfio_ap

device driver.

2. Each APQN derived from the APQI and the APIDs already set in the

guest's CRYCB references an AP queue device bound to the vfio_ap

device driver.

When an AP adapter is removed from the AP configuration via the SE or an

'SCLP Deconfigure AP Adapter' instruction, each queue device associated

with the adapter will be unbound from device driver to which it is bound.

When the vfio_ap device driver's remove callback is invoked to unbind an

AP queue device, if the queue's APQN is assigned to a matrix mdev in use

by a guest, the adapter to which the queue is connected will be hot

unplugged from the guest's configuration. The reason for this is because

an adapter of a different type can be added back to the AP configuration

with the APID corresponding to the adapter being removed. If the new

adapter is not of the appropriate type, it will not get bound to the

vfio_ap driver. If we did not unplug it from the guest, both the guest

and the host would have access to all of the queues associated with the

adapter which is a no-no.

Signed-off-by: Tony Krowiak <akrowiak@xxxxxxxxxxxxx>

---

drivers/s390/crypto/vfio_ap_ops.c | 93 +++++++++++++++++++++++++++++++++++++++

1 file changed, 93 insertions(+)

diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c

index 14f221b7426b..f3332424670f 100644

--- a/drivers/s390/crypto/vfio_ap_ops.c

+++ b/drivers/s390/crypto/vfio_ap_ops.c

@@ -507,6 +507,63 @@ static void vfio_ap_mdev_get_crycb_matrix(struct ap_matrix_mdev *matrix_mdev)

}

}

+static bool vfio_ap_mdev_update_crycb_matrix(struct ap_matrix_mdev *matrix_mdev,

+ struct vfio_ap_queue *q)

+{

+ unsigned long crycb_apid, crycb_apqi;

+ unsigned long apid = AP_QID_CARD(q->apqn);

+ unsigned long apqi = AP_QID_QUEUE(q->apqn);

+

+ /*

+ * If the APID of the input queue is not already set in the guest's

+ * CRYCB, then verify that all APQNs derived from Cartesian product of

+ * the APID and each APQI set in the guest's CRYCB references a queue

+ * that is bound to the vfio_ap driver.

+ */

+ if (!test_bit_inv(apid, matrix_mdev->crycb.apm)) {

+ for_each_set_bit_inv(crycb_apqi, matrix_mdev->crycb.aqm,

+ matrix_mdev->crycb.aqm_max + 1) {

+ /*

+ * The APQN formulated from the APID and APQI of the

+ * input queue is in the process of being bound to the

+ * vfio_ap driver so there is no need to verify it.

+ */

+ if (apqi == crycb_apqi)

+ continue;

+

+ if (!vfio_ap_find_queue(AP_MKQID(apid, crycb_apqi)))

+ return false;

+ }

+ }

+

+ /*

+ * If the APQI of the input queue is not already set in the guest's

+ * CRYCB, then verify that all APQNs derived from Cartesian product of

+ * the APQI and each APID set in the guest's CRYCB references a queue

+ * that is bound to the vfio_ap driver.

+ */

+ if (!test_bit_inv(apqi, matrix_mdev->crycb.aqm)) {

+ for_each_set_bit_inv(crycb_apid, matrix_mdev->crycb.apm,

+ matrix_mdev->crycb.apm_max + 1) {

+ /*

+ * The APQN formulated from the APID and APQI of the

+ * input queue is in the process of being bound to the

+ * vfio_ap driver so there is no need to verify it.

+ */

+ if (apid == crycb_apid)

+ continue;

+

+ if (!vfio_ap_find_queue(AP_MKQID(crycb_apid, apqi)))

+ return false;

+ }

+ }

+

+ set_bit_inv(apid, matrix_mdev->crycb.apm);

+ set_bit_inv(apqi, matrix_mdev->crycb.aqm);

+

+ return true;

+}

+

static bool vfio_ap_mdev_has_crycb(struct ap_matrix_mdev *matrix_mdev)

{

return matrix_mdev->kvm && matrix_mdev->kvm->arch.crypto.crycbd;

@@ -1311,9 +1368,23 @@ void vfio_ap_mdev_unregister(void)

mdev_unregister_device(&matrix_dev->device);

}

+static struct ap_matrix_mdev *vfio_ap_mdev_for_queue(int apqn)

+{

+ struct ap_matrix_mdev *matrix_mdev;

+

+ list_for_each_entry(matrix_mdev, &matrix_dev->mdev_list, node) {

+ if (test_bit_inv(AP_QID_CARD(apqn), matrix_mdev->matrix.apm) &&

+ test_bit_inv(AP_QID_QUEUE(apqn), matrix_mdev->matrix.aqm))

+ return matrix_mdev;

+ }

+

+ return NULL;

+}

+

int vfio_ap_mdev_probe_queue(struct ap_queue *queue)

{

struct vfio_ap_queue *q;

+ struct ap_matrix_mdev *matrix_mdev;

q = kzalloc(sizeof(*q), GFP_KERNEL);

if (!q)

@@ -1322,18 +1393,40 @@ int vfio_ap_mdev_probe_queue(struct ap_queue *queue)

q->apqn = queue->qid;

q->saved_isc = VFIO_AP_ISC_INVALID;

+ /*

+ * If the APQN for the queue is assigned to a matrix mdev that is in

+ * use by a guest, then plug the queue into the guest.

+ */

+ matrix_mdev = vfio_ap_mdev_for_queue(queue->qid);

+ if (matrix_mdev && vfio_ap_mdev_has_crycb(matrix_mdev)) {

+ vfio_ap_mdev_update_crycb_matrix(matrix_mdev, q);

+ vfio_ap_mdev_update_crycb(matrix_mdev);

+ }

+

return 0;

}

void vfio_ap_mdev_remove_queue(struct ap_queue *queue)

{

struct vfio_ap_queue *q;

+ struct ap_matrix_mdev *matrix_mdev;

int apid, apqi;

q = dev_get_drvdata(&queue->ap_dev.device);

dev_set_drvdata(&queue->ap_dev.device, NULL);

apid = AP_QID_CARD(q->apqn);

apqi = AP_QID_QUEUE(q->apqn);

+

+ /*

+ * If the APQN for the queue is assigned to a matrix mdev that is in

+ * use by a guest, then unplug the adapter from the guest.

+ */

+ matrix_mdev = vfio_ap_mdev_for_queue(queue->qid);

+ if (matrix_mdev && vfio_ap_mdev_has_crycb(matrix_mdev)) {

+ clear_bit_inv(apid, matrix_mdev->crycb.apm);

+ vfio_ap_mdev_update_crycb(matrix_mdev);

+ }

+

vfio_ap_mdev_reset_queue(apid, apqi);

vfio_ap_irq_disable(q);

kfree(q);

--

2.7.4

**Next message:**Tony Krowiak: "[PATCH v6 02/10] s390: vfio-ap: allow assignment of unavailable AP resources to mdev device"**Previous message:**Tony Krowiak: "[PATCH v6 07/10] s390: zcrypt: driver callback to indicate resource in use"**In reply to:**Tony Krowiak: "[PATCH v6 07/10] s390: zcrypt: driver callback to indicate resource in use"**Next in thread:**Tony Krowiak: "[PATCH v6 02/10] s390: vfio-ap: allow assignment of unavailable AP resources to mdev device"**Messages sorted by:**[ date ] [ thread ] [ subject ] [ author ]