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