Skip to content

Commit f848cba

Browse files
Tony KrowiakAlexander Gordeev
authored andcommitted
s390/vfio-ap: reset queues filtered from the guest's AP config
When filtering the adapters from the configuration profile for a guest to create or update a guest's AP configuration, if the APID of an adapter and the APQI of a domain identify a queue device that is not bound to the vfio_ap device driver, the APID of the adapter will be filtered because an individual APQN can not be filtered due to the fact the APQNs are assigned to an AP configuration as a matrix of APIDs and APQIs. Consequently, a guest will not have access to all of the queues associated with the filtered adapter. If the queues are subsequently made available again to the guest, they should re-appear in a reset state; so, let's make sure all queues associated with an adapter unplugged from the guest are reset. In order to identify the set of queues that need to be reset, let's allow a vfio_ap_queue object to be simultaneously stored in both a hashtable and a list: A hashtable used to store all of the queues assigned to a matrix mdev; and/or, a list used to store a subset of the queues that need to be reset. For example, when an adapter is hot unplugged from a guest, all guest queues associated with that adapter must be reset. Since that may be a subset of those assigned to the matrix mdev, they can be stored in a list that can be passed to the vfio_ap_mdev_reset_queues function. Signed-off-by: Tony Krowiak <akrowiak@linux.ibm.com> Acked-by: Halil Pasic <pasic@linux.ibm.com> Fixes: 48cae94 ("s390/vfio-ap: refresh guest's APCB by filtering AP resources assigned to mdev") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240115185441.31526-5-akrowiak@linux.ibm.com Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
1 parent 774d101 commit f848cba

2 files changed

Lines changed: 129 additions & 45 deletions

File tree

drivers/s390/crypto/vfio_ap_ops.c

Lines changed: 126 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232

3333
#define AP_RESET_INTERVAL 20 /* Reset sleep interval (20ms) */
3434

35-
static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable);
35+
static int vfio_ap_mdev_reset_queues(struct ap_matrix_mdev *matrix_mdev);
36+
static int vfio_ap_mdev_reset_qlist(struct list_head *qlist);
3637
static struct vfio_ap_queue *vfio_ap_find_queue(int apqn);
3738
static const struct vfio_device_ops vfio_ap_matrix_dev_ops;
3839
static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q);
@@ -665,16 +666,23 @@ static bool vfio_ap_mdev_filter_cdoms(struct ap_matrix_mdev *matrix_mdev)
665666
* device driver.
666667
*
667668
* @matrix_mdev: the matrix mdev whose matrix is to be filtered.
669+
* @apm_filtered: a 256-bit bitmap for storing the APIDs filtered from the
670+
* guest's AP configuration that are still in the host's AP
671+
* configuration.
668672
*
669673
* Note: If an APQN referencing a queue device that is not bound to the vfio_ap
670674
* driver, its APID will be filtered from the guest's APCB. The matrix
671675
* structure precludes filtering an individual APQN, so its APID will be
672-
* filtered.
676+
* filtered. Consequently, all queues associated with the adapter that
677+
* are in the host's AP configuration must be reset. If queues are
678+
* subsequently made available again to the guest, they should re-appear
679+
* in a reset state
673680
*
674681
* Return: a boolean value indicating whether the KVM guest's APCB was changed
675682
* by the filtering or not.
676683
*/
677-
static bool vfio_ap_mdev_filter_matrix(struct ap_matrix_mdev *matrix_mdev)
684+
static bool vfio_ap_mdev_filter_matrix(struct ap_matrix_mdev *matrix_mdev,
685+
unsigned long *apm_filtered)
678686
{
679687
unsigned long apid, apqi, apqn;
680688
DECLARE_BITMAP(prev_shadow_apm, AP_DEVICES);
@@ -684,6 +692,7 @@ static bool vfio_ap_mdev_filter_matrix(struct ap_matrix_mdev *matrix_mdev)
684692
bitmap_copy(prev_shadow_apm, matrix_mdev->shadow_apcb.apm, AP_DEVICES);
685693
bitmap_copy(prev_shadow_aqm, matrix_mdev->shadow_apcb.aqm, AP_DOMAINS);
686694
vfio_ap_matrix_init(&matrix_dev->info, &matrix_mdev->shadow_apcb);
695+
bitmap_clear(apm_filtered, 0, AP_DEVICES);
687696

688697
/*
689698
* Copy the adapters, domains and control domains to the shadow_apcb
@@ -709,8 +718,16 @@ static bool vfio_ap_mdev_filter_matrix(struct ap_matrix_mdev *matrix_mdev)
709718
apqn = AP_MKQID(apid, apqi);
710719
q = vfio_ap_mdev_get_queue(matrix_mdev, apqn);
711720
if (!q || q->reset_status.response_code) {
712-
clear_bit_inv(apid,
713-
matrix_mdev->shadow_apcb.apm);
721+
clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm);
722+
723+
/*
724+
* If the adapter was previously plugged into
725+
* the guest, let's let the caller know that
726+
* the APID was filtered.
727+
*/
728+
if (test_bit_inv(apid, prev_shadow_apm))
729+
set_bit_inv(apid, apm_filtered);
730+
714731
break;
715732
}
716733
}
@@ -812,7 +829,7 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev)
812829

813830
mutex_lock(&matrix_dev->guests_lock);
814831
mutex_lock(&matrix_dev->mdevs_lock);
815-
vfio_ap_mdev_reset_queues(&matrix_mdev->qtable);
832+
vfio_ap_mdev_reset_queues(matrix_mdev);
816833
vfio_ap_mdev_unlink_fr_queues(matrix_mdev);
817834
list_del(&matrix_mdev->node);
818835
mutex_unlock(&matrix_dev->mdevs_lock);
@@ -922,6 +939,47 @@ static void vfio_ap_mdev_link_adapter(struct ap_matrix_mdev *matrix_mdev,
922939
AP_MKQID(apid, apqi));
923940
}
924941

942+
static int reset_queues_for_apids(struct ap_matrix_mdev *matrix_mdev,
943+
unsigned long *apm_reset)
944+
{
945+
struct vfio_ap_queue *q, *tmpq;
946+
struct list_head qlist;
947+
unsigned long apid, apqi;
948+
int apqn, ret = 0;
949+
950+
if (bitmap_empty(apm_reset, AP_DEVICES))
951+
return 0;
952+
953+
INIT_LIST_HEAD(&qlist);
954+
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+
}
974+
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;
981+
}
982+
925983
/**
926984
* assign_adapter_store - parses the APID from @buf and sets the
927985
* corresponding bit in the mediated matrix device's APM
@@ -962,6 +1020,7 @@ static ssize_t assign_adapter_store(struct device *dev,
9621020
{
9631021
int ret;
9641022
unsigned long apid;
1023+
DECLARE_BITMAP(apm_filtered, AP_DEVICES);
9651024
struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
9661025

9671026
mutex_lock(&ap_perms_mutex);
@@ -991,8 +1050,10 @@ static ssize_t assign_adapter_store(struct device *dev,
9911050

9921051
vfio_ap_mdev_link_adapter(matrix_mdev, apid);
9931052

994-
if (vfio_ap_mdev_filter_matrix(matrix_mdev))
1053+
if (vfio_ap_mdev_filter_matrix(matrix_mdev, apm_filtered)) {
9951054
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
1055+
reset_queues_for_apids(matrix_mdev, apm_filtered);
1056+
}
9961057

9971058
ret = count;
9981059
done:
@@ -1023,50 +1084,47 @@ static struct vfio_ap_queue
10231084
* adapter was assigned.
10241085
* @matrix_mdev: the matrix mediated device to which the adapter was assigned.
10251086
* @apid: the APID of the unassigned adapter.
1026-
* @qtable: table for storing queues associated with unassigned adapter.
1087+
* @qlist: list for storing queues associated with unassigned adapter that
1088+
* need to be reset.
10271089
*/
10281090
static void vfio_ap_mdev_unlink_adapter(struct ap_matrix_mdev *matrix_mdev,
10291091
unsigned long apid,
1030-
struct ap_queue_table *qtable)
1092+
struct list_head *qlist)
10311093
{
10321094
unsigned long apqi;
10331095
struct vfio_ap_queue *q;
10341096

10351097
for_each_set_bit_inv(apqi, matrix_mdev->matrix.aqm, AP_DOMAINS) {
10361098
q = vfio_ap_unlink_apqn_fr_mdev(matrix_mdev, apid, apqi);
10371099

1038-
if (q && qtable) {
1100+
if (q && qlist) {
10391101
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm) &&
10401102
test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm))
1041-
hash_add(qtable->queues, &q->mdev_qnode,
1042-
q->apqn);
1103+
list_add_tail(&q->reset_qnode, qlist);
10431104
}
10441105
}
10451106
}
10461107

10471108
static void vfio_ap_mdev_hot_unplug_adapter(struct ap_matrix_mdev *matrix_mdev,
10481109
unsigned long apid)
10491110
{
1050-
int loop_cursor;
1051-
struct vfio_ap_queue *q;
1052-
struct ap_queue_table *qtable = kzalloc(sizeof(*qtable), GFP_KERNEL);
1111+
struct vfio_ap_queue *q, *tmpq;
1112+
struct list_head qlist;
10531113

1054-
hash_init(qtable->queues);
1055-
vfio_ap_mdev_unlink_adapter(matrix_mdev, apid, qtable);
1114+
INIT_LIST_HEAD(&qlist);
1115+
vfio_ap_mdev_unlink_adapter(matrix_mdev, apid, &qlist);
10561116

10571117
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm)) {
10581118
clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm);
10591119
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
10601120
}
10611121

1062-
vfio_ap_mdev_reset_queues(qtable);
1122+
vfio_ap_mdev_reset_qlist(&qlist);
10631123

1064-
hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) {
1124+
list_for_each_entry_safe(q, tmpq, &qlist, reset_qnode) {
10651125
vfio_ap_unlink_mdev_fr_queue(q);
1066-
hash_del(&q->mdev_qnode);
1126+
list_del(&q->reset_qnode);
10671127
}
1068-
1069-
kfree(qtable);
10701128
}
10711129

10721130
/**
@@ -1167,6 +1225,7 @@ static ssize_t assign_domain_store(struct device *dev,
11671225
{
11681226
int ret;
11691227
unsigned long apqi;
1228+
DECLARE_BITMAP(apm_filtered, AP_DEVICES);
11701229
struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
11711230

11721231
mutex_lock(&ap_perms_mutex);
@@ -1196,8 +1255,10 @@ static ssize_t assign_domain_store(struct device *dev,
11961255

11971256
vfio_ap_mdev_link_domain(matrix_mdev, apqi);
11981257

1199-
if (vfio_ap_mdev_filter_matrix(matrix_mdev))
1258+
if (vfio_ap_mdev_filter_matrix(matrix_mdev, apm_filtered)) {
12001259
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
1260+
reset_queues_for_apids(matrix_mdev, apm_filtered);
1261+
}
12011262

12021263
ret = count;
12031264
done:
@@ -1210,46 +1271,42 @@ static DEVICE_ATTR_WO(assign_domain);
12101271

12111272
static void vfio_ap_mdev_unlink_domain(struct ap_matrix_mdev *matrix_mdev,
12121273
unsigned long apqi,
1213-
struct ap_queue_table *qtable)
1274+
struct list_head *qlist)
12141275
{
12151276
unsigned long apid;
12161277
struct vfio_ap_queue *q;
12171278

12181279
for_each_set_bit_inv(apid, matrix_mdev->matrix.apm, AP_DEVICES) {
12191280
q = vfio_ap_unlink_apqn_fr_mdev(matrix_mdev, apid, apqi);
12201281

1221-
if (q && qtable) {
1282+
if (q && qlist) {
12221283
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm) &&
12231284
test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm))
1224-
hash_add(qtable->queues, &q->mdev_qnode,
1225-
q->apqn);
1285+
list_add_tail(&q->reset_qnode, qlist);
12261286
}
12271287
}
12281288
}
12291289

12301290
static void vfio_ap_mdev_hot_unplug_domain(struct ap_matrix_mdev *matrix_mdev,
12311291
unsigned long apqi)
12321292
{
1233-
int loop_cursor;
1234-
struct vfio_ap_queue *q;
1235-
struct ap_queue_table *qtable = kzalloc(sizeof(*qtable), GFP_KERNEL);
1293+
struct vfio_ap_queue *q, *tmpq;
1294+
struct list_head qlist;
12361295

1237-
hash_init(qtable->queues);
1238-
vfio_ap_mdev_unlink_domain(matrix_mdev, apqi, qtable);
1296+
INIT_LIST_HEAD(&qlist);
1297+
vfio_ap_mdev_unlink_domain(matrix_mdev, apqi, &qlist);
12391298

12401299
if (test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm)) {
12411300
clear_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm);
12421301
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
12431302
}
12441303

1245-
vfio_ap_mdev_reset_queues(qtable);
1304+
vfio_ap_mdev_reset_qlist(&qlist);
12461305

1247-
hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) {
1306+
list_for_each_entry_safe(q, tmpq, &qlist, reset_qnode) {
12481307
vfio_ap_unlink_mdev_fr_queue(q);
1249-
hash_del(&q->mdev_qnode);
1308+
list_del(&q->reset_qnode);
12501309
}
1251-
1252-
kfree(qtable);
12531310
}
12541311

12551312
/**
@@ -1604,7 +1661,7 @@ static void vfio_ap_mdev_unset_kvm(struct ap_matrix_mdev *matrix_mdev)
16041661
get_update_locks_for_kvm(kvm);
16051662

16061663
kvm_arch_crypto_clear_masks(kvm);
1607-
vfio_ap_mdev_reset_queues(&matrix_mdev->qtable);
1664+
vfio_ap_mdev_reset_queues(matrix_mdev);
16081665
kvm_put_kvm(kvm);
16091666
matrix_mdev->kvm = NULL;
16101667

@@ -1740,15 +1797,33 @@ static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q)
17401797
}
17411798
}
17421799

1743-
static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable)
1800+
static int vfio_ap_mdev_reset_queues(struct ap_matrix_mdev *matrix_mdev)
17441801
{
17451802
int ret = 0, loop_cursor;
17461803
struct vfio_ap_queue *q;
17471804

1748-
hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode)
1805+
hash_for_each(matrix_mdev->qtable.queues, loop_cursor, q, mdev_qnode)
17491806
vfio_ap_mdev_reset_queue(q);
17501807

1751-
hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) {
1808+
hash_for_each(matrix_mdev->qtable.queues, loop_cursor, q, mdev_qnode) {
1809+
flush_work(&q->reset_work);
1810+
1811+
if (q->reset_status.response_code)
1812+
ret = -EIO;
1813+
}
1814+
1815+
return ret;
1816+
}
1817+
1818+
static int vfio_ap_mdev_reset_qlist(struct list_head *qlist)
1819+
{
1820+
int ret = 0;
1821+
struct vfio_ap_queue *q;
1822+
1823+
list_for_each_entry(q, qlist, reset_qnode)
1824+
vfio_ap_mdev_reset_queue(q);
1825+
1826+
list_for_each_entry(q, qlist, reset_qnode) {
17521827
flush_work(&q->reset_work);
17531828

17541829
if (q->reset_status.response_code)
@@ -1934,7 +2009,7 @@ static ssize_t vfio_ap_mdev_ioctl(struct vfio_device *vdev,
19342009
ret = vfio_ap_mdev_get_device_info(arg);
19352010
break;
19362011
case VFIO_DEVICE_RESET:
1937-
ret = vfio_ap_mdev_reset_queues(&matrix_mdev->qtable);
2012+
ret = vfio_ap_mdev_reset_queues(matrix_mdev);
19382013
break;
19392014
case VFIO_DEVICE_GET_IRQ_INFO:
19402015
ret = vfio_ap_get_irq_info(arg);
@@ -2080,6 +2155,7 @@ int vfio_ap_mdev_probe_queue(struct ap_device *apdev)
20802155
{
20812156
int ret;
20822157
struct vfio_ap_queue *q;
2158+
DECLARE_BITMAP(apm_filtered, AP_DEVICES);
20832159
struct ap_matrix_mdev *matrix_mdev;
20842160

20852161
ret = sysfs_create_group(&apdev->device.kobj, &vfio_queue_attr_group);
@@ -2112,15 +2188,17 @@ int vfio_ap_mdev_probe_queue(struct ap_device *apdev)
21122188
!bitmap_empty(matrix_mdev->aqm_add, AP_DOMAINS))
21132189
goto done;
21142190

2115-
if (vfio_ap_mdev_filter_matrix(matrix_mdev))
2191+
if (vfio_ap_mdev_filter_matrix(matrix_mdev, apm_filtered)) {
21162192
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
2193+
reset_queues_for_apids(matrix_mdev, apm_filtered);
2194+
}
21172195
}
21182196

21192197
done:
21202198
dev_set_drvdata(&apdev->device, q);
21212199
release_update_locks_for_mdev(matrix_mdev);
21222200

2123-
return 0;
2201+
return ret;
21242202

21252203
err_remove_group:
21262204
sysfs_remove_group(&apdev->device.kobj, &vfio_queue_attr_group);
@@ -2464,6 +2542,7 @@ void vfio_ap_on_cfg_changed(struct ap_config_info *cur_cfg_info,
24642542

24652543
static void vfio_ap_mdev_hot_plug_cfg(struct ap_matrix_mdev *matrix_mdev)
24662544
{
2545+
DECLARE_BITMAP(apm_filtered, AP_DEVICES);
24672546
bool filter_domains, filter_adapters, filter_cdoms, do_hotplug = false;
24682547

24692548
mutex_lock(&matrix_mdev->kvm->lock);
@@ -2477,14 +2556,16 @@ static void vfio_ap_mdev_hot_plug_cfg(struct ap_matrix_mdev *matrix_mdev)
24772556
matrix_mdev->adm_add, AP_DOMAINS);
24782557

24792558
if (filter_adapters || filter_domains)
2480-
do_hotplug = vfio_ap_mdev_filter_matrix(matrix_mdev);
2559+
do_hotplug = vfio_ap_mdev_filter_matrix(matrix_mdev, apm_filtered);
24812560

24822561
if (filter_cdoms)
24832562
do_hotplug |= vfio_ap_mdev_filter_cdoms(matrix_mdev);
24842563

24852564
if (do_hotplug)
24862565
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
24872566

2567+
reset_queues_for_apids(matrix_mdev, apm_filtered);
2568+
24882569
mutex_unlock(&matrix_dev->mdevs_lock);
24892570
mutex_unlock(&matrix_mdev->kvm->lock);
24902571
}

0 commit comments

Comments
 (0)