xref: /linux/Documentation/arch/s390/vfio-ap-locking.rst (revision a1c613ae4c322ddd58d5a8539dbfba2a0380a8c0)
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