Skip to content

Commit f21916e

Browse files
Tony KrowiakVasily Gorbik
authored andcommitted
s390/vfio-ap: clean up vfio_ap resources when KVM pointer invalidated
The vfio_ap device driver registers a group notifier with VFIO when the file descriptor for a VFIO mediated device for a KVM guest is opened to receive notification that the KVM pointer is set (VFIO_GROUP_NOTIFY_SET_KVM event). When the KVM pointer is set, the vfio_ap driver takes the following actions: 1. Stashes the KVM pointer in the vfio_ap_mdev struct that holds the state of the mediated device. 2. Calls the kvm_get_kvm() function to increment its reference counter. 3. Sets the function pointer to the function that handles interception of the instruction that enables/disables interrupt processing. 4. Sets the masks in the KVM guest's CRYCB to pass AP resources through to the guest. In order to avoid memory leaks, when the notifier is called to receive notification that the KVM pointer has been set to NULL, the vfio_ap device driver should reverse the actions taken when the KVM pointer was set. Fixes: 258287c ("s390: vfio-ap: implement mediated device open callback") Signed-off-by: Tony Krowiak <[email protected]> Reviewed-by: Halil Pasic <[email protected]> Reviewed-by: Cornelia Huck <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Borntraeger <[email protected]> Signed-off-by: Vasily Gorbik <[email protected]>
1 parent 6ee1d74 commit f21916e

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

drivers/s390/crypto/vfio_ap_ops.c

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,19 +1037,14 @@ static int vfio_ap_mdev_set_kvm(struct ap_matrix_mdev *matrix_mdev,
10371037
{
10381038
struct ap_matrix_mdev *m;
10391039

1040-
mutex_lock(&matrix_dev->lock);
1041-
10421040
list_for_each_entry(m, &matrix_dev->mdev_list, node) {
1043-
if ((m != matrix_mdev) && (m->kvm == kvm)) {
1044-
mutex_unlock(&matrix_dev->lock);
1041+
if ((m != matrix_mdev) && (m->kvm == kvm))
10451042
return -EPERM;
1046-
}
10471043
}
10481044

10491045
matrix_mdev->kvm = kvm;
10501046
kvm_get_kvm(kvm);
10511047
kvm->arch.crypto.pqap_hook = &matrix_mdev->pqap_hook;
1052-
mutex_unlock(&matrix_dev->lock);
10531048

10541049
return 0;
10551050
}
@@ -1083,35 +1078,52 @@ static int vfio_ap_mdev_iommu_notifier(struct notifier_block *nb,
10831078
return NOTIFY_DONE;
10841079
}
10851080

1081+
static void vfio_ap_mdev_unset_kvm(struct ap_matrix_mdev *matrix_mdev)
1082+
{
1083+
kvm_arch_crypto_clear_masks(matrix_mdev->kvm);
1084+
matrix_mdev->kvm->arch.crypto.pqap_hook = NULL;
1085+
vfio_ap_mdev_reset_queues(matrix_mdev->mdev);
1086+
kvm_put_kvm(matrix_mdev->kvm);
1087+
matrix_mdev->kvm = NULL;
1088+
}
1089+
10861090
static int vfio_ap_mdev_group_notifier(struct notifier_block *nb,
10871091
unsigned long action, void *data)
10881092
{
1089-
int ret;
1093+
int ret, notify_rc = NOTIFY_OK;
10901094
struct ap_matrix_mdev *matrix_mdev;
10911095

10921096
if (action != VFIO_GROUP_NOTIFY_SET_KVM)
10931097
return NOTIFY_OK;
10941098

10951099
matrix_mdev = container_of(nb, struct ap_matrix_mdev, group_notifier);
1100+
mutex_lock(&matrix_dev->lock);
10961101

10971102
if (!data) {
1098-
matrix_mdev->kvm = NULL;
1099-
return NOTIFY_OK;
1103+
if (matrix_mdev->kvm)
1104+
vfio_ap_mdev_unset_kvm(matrix_mdev);
1105+
goto notify_done;
11001106
}
11011107

11021108
ret = vfio_ap_mdev_set_kvm(matrix_mdev, data);
1103-
if (ret)
1104-
return NOTIFY_DONE;
1109+
if (ret) {
1110+
notify_rc = NOTIFY_DONE;
1111+
goto notify_done;
1112+
}
11051113

11061114
/* If there is no CRYCB pointer, then we can't copy the masks */
1107-
if (!matrix_mdev->kvm->arch.crypto.crycbd)
1108-
return NOTIFY_DONE;
1115+
if (!matrix_mdev->kvm->arch.crypto.crycbd) {
1116+
notify_rc = NOTIFY_DONE;
1117+
goto notify_done;
1118+
}
11091119

11101120
kvm_arch_crypto_set_masks(matrix_mdev->kvm, matrix_mdev->matrix.apm,
11111121
matrix_mdev->matrix.aqm,
11121122
matrix_mdev->matrix.adm);
11131123

1114-
return NOTIFY_OK;
1124+
notify_done:
1125+
mutex_unlock(&matrix_dev->lock);
1126+
return notify_rc;
11151127
}
11161128

11171129
static void vfio_ap_irq_disable_apqn(int apqn)
@@ -1222,13 +1234,8 @@ static void vfio_ap_mdev_release(struct mdev_device *mdev)
12221234
struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
12231235

12241236
mutex_lock(&matrix_dev->lock);
1225-
if (matrix_mdev->kvm) {
1226-
kvm_arch_crypto_clear_masks(matrix_mdev->kvm);
1227-
matrix_mdev->kvm->arch.crypto.pqap_hook = NULL;
1228-
vfio_ap_mdev_reset_queues(mdev);
1229-
kvm_put_kvm(matrix_mdev->kvm);
1230-
matrix_mdev->kvm = NULL;
1231-
}
1237+
if (matrix_mdev->kvm)
1238+
vfio_ap_mdev_unset_kvm(matrix_mdev);
12321239
mutex_unlock(&matrix_dev->lock);
12331240

12341241
vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,

0 commit comments

Comments
 (0)