Re: [PATCH v4 6/7] s390: ap: Cleanup on removing the AP device

From: Pierre Morel
Date: Wed Feb 27 2019 - 04:58:32 EST


On 26/02/2019 19:27, Tony Krowiak wrote:
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.

The code here is run inside the host. So the queue is still available for ZAPQ.


Besides, once the card is removed from the guest's CRYCB, the bus
running in the guest will do a reset.

I already answered this:
- The AP bus reset the queue before calling the driver probe
- which means that the guest can still access the queue after the reset done by the bus.
- we need to first clear the CRYCB to remove the queue from the guest before we reset the queue.


Regards,
Pierre


--
Pierre Morel
Linux/KVM/QEMU in BÃblingen - Germany