1*37002bc6SCosta Shulyupin.. SPDX-License-Identifier: GPL-2.0 2*37002bc6SCosta Shulyupin 3*37002bc6SCosta Shulyupin====================== 4*37002bc6SCosta ShulyupinVFIO AP Locks Overview 5*37002bc6SCosta Shulyupin====================== 6*37002bc6SCosta ShulyupinThis document describes the locks that are pertinent to the secure operation 7*37002bc6SCosta Shulyupinof the vfio_ap device driver. Throughout this document, the following variables 8*37002bc6SCosta Shulyupinwill be used to denote instances of the structures herein described: 9*37002bc6SCosta Shulyupin 10*37002bc6SCosta Shulyupin.. code-block:: c 11*37002bc6SCosta Shulyupin 12*37002bc6SCosta Shulyupin struct ap_matrix_dev *matrix_dev; 13*37002bc6SCosta Shulyupin struct ap_matrix_mdev *matrix_mdev; 14*37002bc6SCosta Shulyupin struct kvm *kvm; 15*37002bc6SCosta Shulyupin 16*37002bc6SCosta ShulyupinThe Matrix Devices Lock (drivers/s390/crypto/vfio_ap_private.h) 17*37002bc6SCosta Shulyupin--------------------------------------------------------------- 18*37002bc6SCosta Shulyupin 19*37002bc6SCosta Shulyupin.. code-block:: c 20*37002bc6SCosta Shulyupin 21*37002bc6SCosta Shulyupin struct ap_matrix_dev { 22*37002bc6SCosta Shulyupin ... 23*37002bc6SCosta Shulyupin struct list_head mdev_list; 24*37002bc6SCosta Shulyupin struct mutex mdevs_lock; 25*37002bc6SCosta Shulyupin ... 26*37002bc6SCosta Shulyupin } 27*37002bc6SCosta Shulyupin 28*37002bc6SCosta ShulyupinThe Matrix Devices Lock (matrix_dev->mdevs_lock) is implemented as a global 29*37002bc6SCosta Shulyupinmutex contained within the single object of struct ap_matrix_dev. This lock 30*37002bc6SCosta Shulyupincontrols access to all fields contained within each matrix_mdev 31*37002bc6SCosta Shulyupin(matrix_dev->mdev_list). This lock must be held while reading from, writing to 32*37002bc6SCosta Shulyupinor using the data from a field contained within a matrix_mdev instance 33*37002bc6SCosta Shulyupinrepresenting one of the vfio_ap device driver's mediated devices. 34*37002bc6SCosta Shulyupin 35*37002bc6SCosta ShulyupinThe KVM Lock (include/linux/kvm_host.h) 36*37002bc6SCosta Shulyupin--------------------------------------- 37*37002bc6SCosta Shulyupin 38*37002bc6SCosta Shulyupin.. code-block:: c 39*37002bc6SCosta Shulyupin 40*37002bc6SCosta Shulyupin struct kvm { 41*37002bc6SCosta Shulyupin ... 42*37002bc6SCosta Shulyupin struct mutex lock; 43*37002bc6SCosta Shulyupin ... 44*37002bc6SCosta Shulyupin } 45*37002bc6SCosta Shulyupin 46*37002bc6SCosta ShulyupinThe KVM Lock (kvm->lock) controls access to the state data for a KVM guest. This 47*37002bc6SCosta Shulyupinlock must be held by the vfio_ap device driver while one or more AP adapters, 48*37002bc6SCosta Shulyupindomains or control domains are being plugged into or unplugged from the guest. 49*37002bc6SCosta Shulyupin 50*37002bc6SCosta ShulyupinThe KVM pointer is stored in the in the matrix_mdev instance 51*37002bc6SCosta Shulyupin(matrix_mdev->kvm = kvm) containing the state of the mediated device that has 52*37002bc6SCosta Shulyupinbeen attached to the KVM guest. 53*37002bc6SCosta Shulyupin 54*37002bc6SCosta ShulyupinThe Guests Lock (drivers/s390/crypto/vfio_ap_private.h) 55*37002bc6SCosta Shulyupin----------------------------------------------------------- 56*37002bc6SCosta Shulyupin 57*37002bc6SCosta Shulyupin.. code-block:: c 58*37002bc6SCosta Shulyupin 59*37002bc6SCosta Shulyupin struct ap_matrix_dev { 60*37002bc6SCosta Shulyupin ... 61*37002bc6SCosta Shulyupin struct list_head mdev_list; 62*37002bc6SCosta Shulyupin struct mutex guests_lock; 63*37002bc6SCosta Shulyupin ... 64*37002bc6SCosta Shulyupin } 65*37002bc6SCosta Shulyupin 66*37002bc6SCosta ShulyupinThe Guests Lock (matrix_dev->guests_lock) controls access to the 67*37002bc6SCosta Shulyupinmatrix_mdev instances (matrix_dev->mdev_list) that represent mediated devices 68*37002bc6SCosta Shulyupinthat hold the state for the mediated devices that have been attached to a 69*37002bc6SCosta ShulyupinKVM guest. This lock must be held: 70*37002bc6SCosta Shulyupin 71*37002bc6SCosta Shulyupin1. To control access to the KVM pointer (matrix_mdev->kvm) while the vfio_ap 72*37002bc6SCosta Shulyupin device driver is using it to plug/unplug AP devices passed through to the KVM 73*37002bc6SCosta Shulyupin guest. 74*37002bc6SCosta Shulyupin 75*37002bc6SCosta Shulyupin2. To add matrix_mdev instances to or remove them from matrix_dev->mdev_list. 76*37002bc6SCosta Shulyupin This is necessary to ensure the proper locking order when the list is perused 77*37002bc6SCosta Shulyupin to find an ap_matrix_mdev instance for the purpose of plugging/unplugging 78*37002bc6SCosta Shulyupin AP devices passed through to a KVM guest. 79*37002bc6SCosta Shulyupin 80*37002bc6SCosta Shulyupin For example, when a queue device is removed from the vfio_ap device driver, 81*37002bc6SCosta Shulyupin if the adapter is passed through to a KVM guest, it will have to be 82*37002bc6SCosta Shulyupin unplugged. In order to figure out whether the adapter is passed through, 83*37002bc6SCosta Shulyupin the matrix_mdev object to which the queue is assigned will have to be 84*37002bc6SCosta Shulyupin found. The KVM pointer (matrix_mdev->kvm) can then be used to determine if 85*37002bc6SCosta Shulyupin the mediated device is passed through (matrix_mdev->kvm != NULL) and if so, 86*37002bc6SCosta Shulyupin to unplug the adapter. 87*37002bc6SCosta Shulyupin 88*37002bc6SCosta ShulyupinIt is not necessary to take the Guests Lock to access the KVM pointer if the 89*37002bc6SCosta Shulyupinpointer is not used to plug/unplug devices passed through to the KVM guest; 90*37002bc6SCosta Shulyupinhowever, in this case, the Matrix Devices Lock (matrix_dev->mdevs_lock) must be 91*37002bc6SCosta Shulyupinheld in order to access the KVM pointer since it is set and cleared under the 92*37002bc6SCosta Shulyupinprotection of the Matrix Devices Lock. A case in point is the function that 93*37002bc6SCosta Shulyupinhandles interception of the PQAP(AQIC) instruction sub-function. This handler 94*37002bc6SCosta Shulyupinneeds to access the KVM pointer only for the purposes of setting or clearing IRQ 95*37002bc6SCosta Shulyupinresources, so only the matrix_dev->mdevs_lock needs to be held. 96*37002bc6SCosta Shulyupin 97*37002bc6SCosta ShulyupinThe PQAP Hook Lock (arch/s390/include/asm/kvm_host.h) 98*37002bc6SCosta Shulyupin----------------------------------------------------- 99*37002bc6SCosta Shulyupin 100*37002bc6SCosta Shulyupin.. code-block:: c 101*37002bc6SCosta Shulyupin 102*37002bc6SCosta Shulyupin typedef int (*crypto_hook)(struct kvm_vcpu *vcpu); 103*37002bc6SCosta Shulyupin 104*37002bc6SCosta Shulyupin struct kvm_s390_crypto { 105*37002bc6SCosta Shulyupin ... 106*37002bc6SCosta Shulyupin struct rw_semaphore pqap_hook_rwsem; 107*37002bc6SCosta Shulyupin crypto_hook *pqap_hook; 108*37002bc6SCosta Shulyupin ... 109*37002bc6SCosta Shulyupin }; 110*37002bc6SCosta Shulyupin 111*37002bc6SCosta ShulyupinThe PQAP Hook Lock is a r/w semaphore that controls access to the function 112*37002bc6SCosta Shulyupinpointer of the handler ``(*kvm->arch.crypto.pqap_hook)`` to invoke when the 113*37002bc6SCosta ShulyupinPQAP(AQIC) instruction sub-function is intercepted by the host. The lock must be 114*37002bc6SCosta Shulyupinheld in write mode when pqap_hook value is set, and in read mode when the 115*37002bc6SCosta Shulyupinpqap_hook function is called. 116