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 );
3637static struct vfio_ap_queue * vfio_ap_find_queue (int apqn );
3738static const struct vfio_device_ops vfio_ap_matrix_dev_ops ;
3839static 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 ;
9981059done :
@@ -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 */
10281090static 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
10471108static 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 ;
12031264done :
@@ -1210,46 +1271,42 @@ static DEVICE_ATTR_WO(assign_domain);
12101271
12111272static 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
12301290static 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
21192197done :
21202198 dev_set_drvdata (& apdev -> device , q );
21212199 release_update_locks_for_mdev (matrix_mdev );
21222200
2123- return 0 ;
2201+ return ret ;
21242202
21252203err_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
24652543static 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