Skip to content

Commit 1e75373

Browse files
Tony KrowiakAlex Williamson
authored andcommitted
s390/vfio-ap: r/w lock for PQAP interception handler function pointer
The function pointer to the interception handler for the PQAP instruction can get changed during the interception process. Let's add a semaphore to struct kvm_s390_crypto to control read/write access to the function pointer contained therein. The semaphore must be locked for write access by the vfio_ap device driver when notified that the KVM pointer has been set or cleared. It must be locked for read access by the interception framework when the PQAP instruction is intercepted. Signed-off-by: Tony Krowiak <akrowiak@linux.ibm.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Link: https://lore.kernel.org/r/20210823212047.1476436-2-akrowiak@linux.ibm.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent eb24c10 commit 1e75373

5 files changed

Lines changed: 31 additions & 18 deletions

File tree

arch/s390/include/asm/kvm_host.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -798,14 +798,12 @@ struct kvm_s390_cpu_model {
798798
unsigned short ibc;
799799
};
800800

801-
struct kvm_s390_module_hook {
802-
int (*hook)(struct kvm_vcpu *vcpu);
803-
struct module *owner;
804-
};
801+
typedef int (*crypto_hook)(struct kvm_vcpu *vcpu);
805802

806803
struct kvm_s390_crypto {
807804
struct kvm_s390_crypto_cb *crycb;
808-
struct kvm_s390_module_hook *pqap_hook;
805+
struct rw_semaphore pqap_hook_rwsem;
806+
crypto_hook *pqap_hook;
809807
__u32 crycbd;
810808
__u8 aes_kw;
811809
__u8 dea_kw;

arch/s390/kvm/kvm-s390.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,6 +2630,7 @@ static void kvm_s390_crypto_init(struct kvm *kvm)
26302630
{
26312631
kvm->arch.crypto.crycb = &kvm->arch.sie_page2->crycb;
26322632
kvm_s390_set_crycb_format(kvm);
2633+
init_rwsem(&kvm->arch.crypto.pqap_hook_rwsem);
26332634

26342635
if (!test_kvm_facility(kvm, 76))
26352636
return;

arch/s390/kvm/priv.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ static int handle_io_inst(struct kvm_vcpu *vcpu)
610610
static int handle_pqap(struct kvm_vcpu *vcpu)
611611
{
612612
struct ap_queue_status status = {};
613+
crypto_hook pqap_hook;
613614
unsigned long reg0;
614615
int ret;
615616
uint8_t fc;
@@ -654,18 +655,20 @@ static int handle_pqap(struct kvm_vcpu *vcpu)
654655
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
655656

656657
/*
657-
* Verify that the hook callback is registered, lock the owner
658-
* and call the hook.
658+
* If the hook callback is registered, there will be a pointer to the
659+
* hook function pointer in the kvm_s390_crypto structure. Lock the
660+
* owner, retrieve the hook function pointer and call the hook.
659661
*/
662+
down_read(&vcpu->kvm->arch.crypto.pqap_hook_rwsem);
660663
if (vcpu->kvm->arch.crypto.pqap_hook) {
661-
if (!try_module_get(vcpu->kvm->arch.crypto.pqap_hook->owner))
662-
return -EOPNOTSUPP;
663-
ret = vcpu->kvm->arch.crypto.pqap_hook->hook(vcpu);
664-
module_put(vcpu->kvm->arch.crypto.pqap_hook->owner);
664+
pqap_hook = *vcpu->kvm->arch.crypto.pqap_hook;
665+
ret = pqap_hook(vcpu);
665666
if (!ret && vcpu->run->s.regs.gprs[1] & 0x00ff0000)
666667
kvm_s390_set_psw_cc(vcpu, 3);
668+
up_read(&vcpu->kvm->arch.crypto.pqap_hook_rwsem);
667669
return ret;
668670
}
671+
up_read(&vcpu->kvm->arch.crypto.pqap_hook_rwsem);
669672
/*
670673
* A vfio_driver must register a hook.
671674
* No hook means no driver to enable the SIE CRYCB and no queues.

drivers/s390/crypto/vfio_ap_ops.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,7 @@ static int vfio_ap_mdev_create(struct mdev_device *mdev)
352352
vfio_ap_matrix_init(&matrix_dev->info, &matrix_mdev->matrix);
353353
init_waitqueue_head(&matrix_mdev->wait_for_kvm);
354354
mdev_set_drvdata(mdev, matrix_mdev);
355-
matrix_mdev->pqap_hook.hook = handle_pqap;
356-
matrix_mdev->pqap_hook.owner = THIS_MODULE;
355+
matrix_mdev->pqap_hook = handle_pqap;
357356
mutex_lock(&matrix_dev->lock);
358357
list_add(&matrix_mdev->node, &matrix_dev->mdev_list);
359358
mutex_unlock(&matrix_dev->lock);
@@ -1115,15 +1114,20 @@ static int vfio_ap_mdev_set_kvm(struct ap_matrix_mdev *matrix_mdev,
11151114
}
11161115

11171116
kvm_get_kvm(kvm);
1117+
matrix_mdev->kvm = kvm;
11181118
matrix_mdev->kvm_busy = true;
11191119
mutex_unlock(&matrix_dev->lock);
1120+
1121+
down_write(&matrix_mdev->kvm->arch.crypto.pqap_hook_rwsem);
1122+
kvm->arch.crypto.pqap_hook = &matrix_mdev->pqap_hook;
1123+
up_write(&matrix_mdev->kvm->arch.crypto.pqap_hook_rwsem);
1124+
11201125
kvm_arch_crypto_set_masks(kvm,
11211126
matrix_mdev->matrix.apm,
11221127
matrix_mdev->matrix.aqm,
11231128
matrix_mdev->matrix.adm);
1129+
11241130
mutex_lock(&matrix_dev->lock);
1125-
kvm->arch.crypto.pqap_hook = &matrix_mdev->pqap_hook;
1126-
matrix_mdev->kvm = kvm;
11271131
matrix_mdev->kvm_busy = false;
11281132
wake_up_all(&matrix_mdev->wait_for_kvm);
11291133
}
@@ -1189,10 +1193,17 @@ static void vfio_ap_mdev_unset_kvm(struct ap_matrix_mdev *matrix_mdev)
11891193
if (matrix_mdev->kvm) {
11901194
matrix_mdev->kvm_busy = true;
11911195
mutex_unlock(&matrix_dev->lock);
1192-
kvm_arch_crypto_clear_masks(matrix_mdev->kvm);
1196+
1197+
if (matrix_mdev->kvm->arch.crypto.crycbd) {
1198+
down_write(&matrix_mdev->kvm->arch.crypto.pqap_hook_rwsem);
1199+
matrix_mdev->kvm->arch.crypto.pqap_hook = NULL;
1200+
up_write(&matrix_mdev->kvm->arch.crypto.pqap_hook_rwsem);
1201+
1202+
kvm_arch_crypto_clear_masks(matrix_mdev->kvm);
1203+
}
1204+
11931205
mutex_lock(&matrix_dev->lock);
11941206
vfio_ap_mdev_reset_queues(matrix_mdev->mdev);
1195-
matrix_mdev->kvm->arch.crypto.pqap_hook = NULL;
11961207
kvm_put_kvm(matrix_mdev->kvm);
11971208
matrix_mdev->kvm = NULL;
11981209
matrix_mdev->kvm_busy = false;

drivers/s390/crypto/vfio_ap_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ struct ap_matrix_mdev {
8686
bool kvm_busy;
8787
wait_queue_head_t wait_for_kvm;
8888
struct kvm *kvm;
89-
struct kvm_s390_module_hook pqap_hook;
89+
crypto_hook pqap_hook;
9090
struct mdev_device *mdev;
9191
};
9292

0 commit comments

Comments
 (0)