On 2/22/19 10:29 AM, Pierre Morel wrote:
When the device is remove, we must make sure to
clear the interruption and reset the AP device.
We also need to clear the CRYCB of the guest.
Signed-off-by: Pierre Morel <pmorel@xxxxxxxxxxxxx>
---
 drivers/s390/crypto/vfio_ap_drv.c | 35 +++++++++++++++++++++++++++++++++++
 drivers/s390/crypto/vfio_ap_ops.c | 3 ++-
 drivers/s390/crypto/vfio_ap_private.h | 3 +++
 3 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/s390/crypto/vfio_ap_drv.c b/drivers/s390/crypto/vfio_ap_drv.c
index eca0ffc..e5d91ff 100644
--- a/drivers/s390/crypto/vfio_ap_drv.c
+++ b/drivers/s390/crypto/vfio_ap_drv.c
@@ -5,6 +5,7 @@
ÂÂ * Copyright IBM Corp. 2018
ÂÂ *
ÂÂ * Author(s): Tony Krowiak <akrowiak@xxxxxxxxxxxxx>
+ *ÂÂÂÂÂÂÂÂÂ Pierre Morel <pmorel@xxxxxxxxxxxxx>
ÂÂ */
 #include <linux/module.h>
@@ -12,6 +13,8 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/facility.h>
+#include <linux/bitops.h>
+#include <linux/kvm_host.h>
 #include "vfio_ap_private.h"
 #define VFIO_AP_ROOT_NAME "vfio_ap"
@@ -61,6 +64,33 @@ static int vfio_ap_queue_dev_probe(struct ap_device *apdev)
 }
 /**
+ * vfio_ap_update_crycb
+ * @q: A pointer to the queue being removed
+ *
+ * We clear the APID of the queue, making this queue unusable for the guest.
+ * After this function we can reset the queue without to fear a race with
+ * the guest to access the queue again.
+ * We do not fear race with the host as we still get the device.
+ */
+static void vfio_ap_update_crycb(struct vfio_ap_queue *q)
+{
+ÂÂÂ struct ap_matrix_mdev *matrix_mdev = q->matrix_mdev;
+
+ÂÂÂ if (!matrix_mdev)
+ÂÂÂÂÂÂÂ return;
+
+ÂÂÂ clear_bit_inv(AP_QID_CARD(q->apqn), matrix_mdev->matrix.apm);
+
+ÂÂÂ if (!matrix_mdev->kvm)
+ÂÂÂÂÂÂÂ return;
+
+ÂÂÂ kvm_arch_crypto_set_masks(matrix_mdev->kvm,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ matrix_mdev->matrix.apm,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ matrix_mdev->matrix.aqm,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ matrix_mdev->matrix.adm);
+}
+
+/**
ÂÂ * vfio_ap_queue_dev_remove:
ÂÂ *
ÂÂ * Free the associated vfio_ap_queue structure
@@ -70,6 +100,11 @@ static void vfio_ap_queue_dev_remove(struct ap_device *apdev)
ÂÂÂÂÂ struct vfio_ap_queue *q;
ÂÂÂÂÂ q = dev_get_drvdata(&apdev->device);
+ÂÂÂ if (!q)
+ÂÂÂÂÂÂÂ return;
+
+ÂÂÂ vfio_ap_update_crycb(q);
+ÂÂÂ vfio_ap_mdev_reset_queue(q);
The reset is unnecessary because once the card is removed from the
CRYCB, the ZAPQ may fail with because the queue may not exist anymore.
Besides, once the card is removed from the guest's CRYCB, the bus
running in the guest will do a reset.