The patch below does not apply to the 6.1-stable tree. If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <stable@xxxxxxxxxxxxxxx>. To reproduce the conflict and resubmit, you may use the following commands: git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y git checkout FETCH_HEAD git cherry-pick -x f009cfa466558b7dfe97f167ba1875d6f9ea4c07 # <resolve conflicts, build, test, etc.> git commit -s git send-email --to '<stable@xxxxxxxxxxxxxxx>' --in-reply-to '2024012656-cider-favorable-b52e@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^.. Possible dependencies: f009cfa46655 ("s390/vfio-ap: reset queues associated with adapter for queue unbound from driver") f848cba767e5 ("s390/vfio-ap: reset queues filtered from the guest's AP config") 774d10196e64 ("s390/vfio-ap: let on_scan_complete() callback filter matrix and update guest's APCB") 850fb7fa8c68 ("s390/vfio-ap: always filter entire AP matrix") 9261f0438835 ("s390/vfio-ap: use work struct to verify queue reset") 62aab082e999 ("s390/vfio-ap: store entire AP queue status word with the queue object") dd174833e44e ("s390/vfio-ap: remove upper limit on wait for queue reset to complete") c51f8c6bb5c8 ("s390/vfio-ap: allow deconfigured queue to be passed through to a guest") 411b0109daa5 ("s390/vfio-ap: wait for response code 05 to clear on queue reset") 7aa7b2a80cb7 ("s390/vfio-ap: clean up irq resources if possible") 680b7ddd7e2a ("s390/vfio-ap: no need to check the 'E' and 'I' bits in APQSW after TAPQ") 4bdf3c3956d8 ("s390/ap: provide F bit parameter for ap_rapq() and ap_zapq()") 7cb7636a1ac1 ("s390/vfio_ap: increase max wait time for reset verification") 51d4d9877087 ("s390/vfio_ap: fix handling of error response codes") 5a42b348adf9 ("s390/vfio_ap: verify ZAPQ completion after return of response code zero") 3ba41768105c ("s390/vfio_ap: use TAPQ to verify reset in progress completes") 0daf9878a799 ("s390/vfio_ap: check TAPQ response code when waiting for queue reset") 62414d901c3a ("s390/vfio-ap: verify reset complete in separate function") 08866d34c709 ("s390/vfio-ap: fix an error handling path in vfio_ap_mdev_probe_queue()") thanks, greg k-h ------------------ original commit in Linus's tree ------------------ >From f009cfa466558b7dfe97f167ba1875d6f9ea4c07 Mon Sep 17 00:00:00 2001 From: Tony Krowiak <akrowiak@xxxxxxxxxxxxx> Date: Mon, 15 Jan 2024 13:54:35 -0500 Subject: [PATCH] s390/vfio-ap: reset queues associated with adapter for queue unbound from driver When a queue is unbound from the vfio_ap device driver, if that queue is assigned to a guest's AP configuration, its associated adapter is removed because queues are defined to a guest via a matrix of adapters and domains; so, it is not possible to remove a single queue. If an adapter is removed from the guest's AP configuration, all associated queues must be reset to prevent leaking crypto data should any of them be assigned to a different guest or device driver. The one caveat is that if the queue is being removed because the adapter or domain has been removed from the host's AP configuration, then an attempt to reset the queue will fail with response code 01, AP-queue number not valid; so resetting these queues should be skipped. Acked-by: Halil Pasic <pasic@xxxxxxxxxxxxx> Signed-off-by: Tony Krowiak <akrowiak@xxxxxxxxxxxxx> Fixes: 09d31ff78793 ("s390/vfio-ap: hot plug/unplug of AP devices when probed/removed") Cc: stable@xxxxxxxxxxxxxxx Link: https://lore.kernel.org/r/20240115185441.31526-6-akrowiak@xxxxxxxxxxxxx Signed-off-by: Alexander Gordeev <agordeev@xxxxxxxxxxxxx> diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index 44cd29aace8e..550c936c413d 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -939,45 +939,45 @@ static void vfio_ap_mdev_link_adapter(struct ap_matrix_mdev *matrix_mdev, AP_MKQID(apid, apqi)); } +static void collect_queues_to_reset(struct ap_matrix_mdev *matrix_mdev, + unsigned long apid, + struct list_head *qlist) +{ + struct vfio_ap_queue *q; + unsigned long apqi; + + for_each_set_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm, AP_DOMAINS) { + q = vfio_ap_mdev_get_queue(matrix_mdev, AP_MKQID(apid, apqi)); + if (q) + list_add_tail(&q->reset_qnode, qlist); + } +} + +static void reset_queues_for_apid(struct ap_matrix_mdev *matrix_mdev, + unsigned long apid) +{ + struct list_head qlist; + + INIT_LIST_HEAD(&qlist); + collect_queues_to_reset(matrix_mdev, apid, &qlist); + vfio_ap_mdev_reset_qlist(&qlist); +} + static int reset_queues_for_apids(struct ap_matrix_mdev *matrix_mdev, unsigned long *apm_reset) { - struct vfio_ap_queue *q, *tmpq; struct list_head qlist; - unsigned long apid, apqi; - int apqn, ret = 0; + unsigned long apid; if (bitmap_empty(apm_reset, AP_DEVICES)) return 0; INIT_LIST_HEAD(&qlist); - for_each_set_bit_inv(apid, apm_reset, AP_DEVICES) { - for_each_set_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm, - AP_DOMAINS) { - /* - * If the domain is not in the host's AP configuration, - * then resetting it will fail with response code 01 - * (APQN not valid). - */ - if (!test_bit_inv(apqi, - (unsigned long *)matrix_dev->info.aqm)) - continue; - - apqn = AP_MKQID(apid, apqi); - q = vfio_ap_mdev_get_queue(matrix_mdev, apqn); - - if (q) - list_add_tail(&q->reset_qnode, &qlist); - } - } + for_each_set_bit_inv(apid, apm_reset, AP_DEVICES) + collect_queues_to_reset(matrix_mdev, apid, &qlist); - ret = vfio_ap_mdev_reset_qlist(&qlist); - - list_for_each_entry_safe(q, tmpq, &qlist, reset_qnode) - list_del(&q->reset_qnode); - - return ret; + return vfio_ap_mdev_reset_qlist(&qlist); } /** @@ -2217,24 +2217,30 @@ void vfio_ap_mdev_remove_queue(struct ap_device *apdev) matrix_mdev = q->matrix_mdev; if (matrix_mdev) { - vfio_ap_unlink_queue_fr_mdev(q); - apid = AP_QID_CARD(q->apqn); apqi = AP_QID_QUEUE(q->apqn); - - /* - * If the queue is assigned to the guest's APCB, then remove - * the adapter's APID from the APCB and hot it into the guest. - */ + /* If the queue is assigned to the guest's AP configuration */ if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm) && test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm)) { + /* + * Since the queues are defined via a matrix of adapters + * and domains, it is not possible to hot unplug a + * single queue; so, let's unplug the adapter. + */ clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm); vfio_ap_mdev_update_guest_apcb(matrix_mdev); + reset_queues_for_apid(matrix_mdev, apid); + goto done; } } vfio_ap_mdev_reset_queue(q); flush_work(&q->reset_work); + +done: + if (matrix_mdev) + vfio_ap_unlink_queue_fr_mdev(q); + dev_set_drvdata(&apdev->device, NULL); kfree(q); release_update_locks_for_mdev(matrix_mdev);