0001 .. SPDX-License-Identifier: GPL-2.0
0002
0003 ======================
0004 VFIO AP Locks Overview
0005 ======================
0006 This document describes the locks that are pertinent to the secure operation
0007 of the vfio_ap device driver. Throughout this document, the following variables
0008 will be used to denote instances of the structures herein described:
0009
0010 .. code-block:: c
0011
0012 struct ap_matrix_dev *matrix_dev;
0013 struct ap_matrix_mdev *matrix_mdev;
0014 struct kvm *kvm;
0015
0016 The Matrix Devices Lock (drivers/s390/crypto/vfio_ap_private.h)
0017 ---------------------------------------------------------------
0018
0019 .. code-block:: c
0020
0021 struct ap_matrix_dev {
0022 ...
0023 struct list_head mdev_list;
0024 struct mutex mdevs_lock;
0025 ...
0026 }
0027
0028 The Matrix Devices Lock (matrix_dev->mdevs_lock) is implemented as a global
0029 mutex contained within the single object of struct ap_matrix_dev. This lock
0030 controls access to all fields contained within each matrix_mdev
0031 (matrix_dev->mdev_list). This lock must be held while reading from, writing to
0032 or using the data from a field contained within a matrix_mdev instance
0033 representing one of the vfio_ap device driver's mediated devices.
0034
0035 The KVM Lock (include/linux/kvm_host.h)
0036 ---------------------------------------
0037
0038 .. code-block:: c
0039
0040 struct kvm {
0041 ...
0042 struct mutex lock;
0043 ...
0044 }
0045
0046 The KVM Lock (kvm->lock) controls access to the state data for a KVM guest. This
0047 lock must be held by the vfio_ap device driver while one or more AP adapters,
0048 domains or control domains are being plugged into or unplugged from the guest.
0049
0050 The KVM pointer is stored in the in the matrix_mdev instance
0051 (matrix_mdev->kvm = kvm) containing the state of the mediated device that has
0052 been attached to the KVM guest.
0053
0054 The Guests Lock (drivers/s390/crypto/vfio_ap_private.h)
0055 -----------------------------------------------------------
0056
0057 .. code-block:: c
0058
0059 struct ap_matrix_dev {
0060 ...
0061 struct list_head mdev_list;
0062 struct mutex guests_lock;
0063 ...
0064 }
0065
0066 The Guests Lock (matrix_dev->guests_lock) controls access to the
0067 matrix_mdev instances (matrix_dev->mdev_list) that represent mediated devices
0068 that hold the state for the mediated devices that have been attached to a
0069 KVM guest. This lock must be held:
0070
0071 1. To control access to the KVM pointer (matrix_mdev->kvm) while the vfio_ap
0072 device driver is using it to plug/unplug AP devices passed through to the KVM
0073 guest.
0074
0075 2. To add matrix_mdev instances to or remove them from matrix_dev->mdev_list.
0076 This is necessary to ensure the proper locking order when the list is perused
0077 to find an ap_matrix_mdev instance for the purpose of plugging/unplugging
0078 AP devices passed through to a KVM guest.
0079
0080 For example, when a queue device is removed from the vfio_ap device driver,
0081 if the adapter is passed through to a KVM guest, it will have to be
0082 unplugged. In order to figure out whether the adapter is passed through,
0083 the matrix_mdev object to which the queue is assigned will have to be
0084 found. The KVM pointer (matrix_mdev->kvm) can then be used to determine if
0085 the mediated device is passed through (matrix_mdev->kvm != NULL) and if so,
0086 to unplug the adapter.
0087
0088 It is not necessary to take the Guests Lock to access the KVM pointer if the
0089 pointer is not used to plug/unplug devices passed through to the KVM guest;
0090 however, in this case, the Matrix Devices Lock (matrix_dev->mdevs_lock) must be
0091 held in order to access the KVM pointer since it is set and cleared under the
0092 protection of the Matrix Devices Lock. A case in point is the function that
0093 handles interception of the PQAP(AQIC) instruction sub-function. This handler
0094 needs to access the KVM pointer only for the purposes of setting or clearing IRQ
0095 resources, so only the matrix_dev->mdevs_lock needs to be held.
0096
0097 The PQAP Hook Lock (arch/s390/include/asm/kvm_host.h)
0098 -----------------------------------------------------
0099
0100 .. code-block:: c
0101
0102 typedef int (*crypto_hook)(struct kvm_vcpu *vcpu);
0103
0104 struct kvm_s390_crypto {
0105 ...
0106 struct rw_semaphore pqap_hook_rwsem;
0107 crypto_hook *pqap_hook;
0108 ...
0109 };
0110
0111 The PQAP Hook Lock is a r/w semaphore that controls access to the function
0112 pointer of the handler ``(*kvm->arch.crypto.pqap_hook)`` to invoke when the
0113 PQAP(AQIC) instruction sub-function is intercepted by the host. The lock must be
0114 held in write mode when pqap_hook value is set, and in read mode when the
0115 pqap_hook function is called.