Skip to content

Commit f009cfa

Browse files
Tony KrowiakAlexander Gordeev
authored andcommitted
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@linux.ibm.com> Signed-off-by: Tony Krowiak <akrowiak@linux.ibm.com> Fixes: 09d31ff ("s390/vfio-ap: hot plug/unplug of AP devices when probed/removed") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240115185441.31526-6-akrowiak@linux.ibm.com Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
1 parent f848cba commit f009cfa

1 file changed

Lines changed: 41 additions & 35 deletions

File tree

drivers/s390/crypto/vfio_ap_ops.c

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -939,45 +939,45 @@ static void vfio_ap_mdev_link_adapter(struct ap_matrix_mdev *matrix_mdev,
939939
AP_MKQID(apid, apqi));
940940
}
941941

942+
static void collect_queues_to_reset(struct ap_matrix_mdev *matrix_mdev,
943+
unsigned long apid,
944+
struct list_head *qlist)
945+
{
946+
struct vfio_ap_queue *q;
947+
unsigned long apqi;
948+
949+
for_each_set_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm, AP_DOMAINS) {
950+
q = vfio_ap_mdev_get_queue(matrix_mdev, AP_MKQID(apid, apqi));
951+
if (q)
952+
list_add_tail(&q->reset_qnode, qlist);
953+
}
954+
}
955+
956+
static void reset_queues_for_apid(struct ap_matrix_mdev *matrix_mdev,
957+
unsigned long apid)
958+
{
959+
struct list_head qlist;
960+
961+
INIT_LIST_HEAD(&qlist);
962+
collect_queues_to_reset(matrix_mdev, apid, &qlist);
963+
vfio_ap_mdev_reset_qlist(&qlist);
964+
}
965+
942966
static int reset_queues_for_apids(struct ap_matrix_mdev *matrix_mdev,
943967
unsigned long *apm_reset)
944968
{
945-
struct vfio_ap_queue *q, *tmpq;
946969
struct list_head qlist;
947-
unsigned long apid, apqi;
948-
int apqn, ret = 0;
970+
unsigned long apid;
949971

950972
if (bitmap_empty(apm_reset, AP_DEVICES))
951973
return 0;
952974

953975
INIT_LIST_HEAD(&qlist);
954976

955-
for_each_set_bit_inv(apid, apm_reset, AP_DEVICES) {
956-
for_each_set_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm,
957-
AP_DOMAINS) {
958-
/*
959-
* If the domain is not in the host's AP configuration,
960-
* then resetting it will fail with response code 01
961-
* (APQN not valid).
962-
*/
963-
if (!test_bit_inv(apqi,
964-
(unsigned long *)matrix_dev->info.aqm))
965-
continue;
966-
967-
apqn = AP_MKQID(apid, apqi);
968-
q = vfio_ap_mdev_get_queue(matrix_mdev, apqn);
969-
970-
if (q)
971-
list_add_tail(&q->reset_qnode, &qlist);
972-
}
973-
}
977+
for_each_set_bit_inv(apid, apm_reset, AP_DEVICES)
978+
collect_queues_to_reset(matrix_mdev, apid, &qlist);
974979

975-
ret = vfio_ap_mdev_reset_qlist(&qlist);
976-
977-
list_for_each_entry_safe(q, tmpq, &qlist, reset_qnode)
978-
list_del(&q->reset_qnode);
979-
980-
return ret;
980+
return vfio_ap_mdev_reset_qlist(&qlist);
981981
}
982982

983983
/**
@@ -2217,24 +2217,30 @@ void vfio_ap_mdev_remove_queue(struct ap_device *apdev)
22172217
matrix_mdev = q->matrix_mdev;
22182218

22192219
if (matrix_mdev) {
2220-
vfio_ap_unlink_queue_fr_mdev(q);
2221-
22222220
apid = AP_QID_CARD(q->apqn);
22232221
apqi = AP_QID_QUEUE(q->apqn);
2224-
2225-
/*
2226-
* If the queue is assigned to the guest's APCB, then remove
2227-
* the adapter's APID from the APCB and hot it into the guest.
2228-
*/
2222+
/* If the queue is assigned to the guest's AP configuration */
22292223
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm) &&
22302224
test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm)) {
2225+
/*
2226+
* Since the queues are defined via a matrix of adapters
2227+
* and domains, it is not possible to hot unplug a
2228+
* single queue; so, let's unplug the adapter.
2229+
*/
22312230
clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm);
22322231
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
2232+
reset_queues_for_apid(matrix_mdev, apid);
2233+
goto done;
22332234
}
22342235
}
22352236

22362237
vfio_ap_mdev_reset_queue(q);
22372238
flush_work(&q->reset_work);
2239+
2240+
done:
2241+
if (matrix_mdev)
2242+
vfio_ap_unlink_queue_fr_mdev(q);
2243+
22382244
dev_set_drvdata(&apdev->device, NULL);
22392245
kfree(q);
22402246
release_update_locks_for_mdev(matrix_mdev);

0 commit comments

Comments
 (0)