2017-10-13 17:45:37

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 00/19] KVM: s390/crypto/vfio: guest dedicated crypto adapters

Overview:
--------
An adjunct processor (AP) facility is an IBM Z cryptographic facility. The
AP facility is comprised of three AP instructions and from 1 to 256 AP
adapter cards. The design takes advantage of the interpretive execution mode
provided by the SIE architecture. With interpretive execution mode, the AP
instructions executed on the guest are interpreted by the hardware. This
allows guests direct access to AP adapter cards. The first goal of this
patch series is to provide direct access by a KVM guest to an AP as a
pass-through device. The second goal is to provide administrators with the
means to configure KVM guests to grant direct access to AP facilities
assigned to the LPAR in which the host linux system is running.

To facilitate the comprehension of the design, let's present an overview of
the AP architecture.

AP Architectural Overview
-------------------------
Let's start with some definitions:

* AP adapter

An AP adapter is an IBM Z adapter card that can perform cryptographic
functionality. There can be from 0 to 256 adapters assigned to an LPAR.
Each adapter is identified by a number from 0 to 255. When
installed, an AP is accessed by AP instructions executed by any CPU.

* AP domain

An adapter can be partitioned into domains. An adapter can hold up to 256
domains. Each domain is identified by a number from 0 to 255. Domains can
be further classified into two types:

* Usage domains are domains that can be accessed directly to process AP
commands

* Control domains are domains that are accessed indirectly by AP
commands sent to a usage domain to control or change the domain.

* AP Queue

An AP queue is the means by which an AP command is sent to an
AP usage domain inside a specific AP. An AP queue is identified by a tuple
comprised of an AP adapter ID and a usage domain index corresponding
to a given usage domain within the adapter. This tuple forms an AP Queue
Number (APQN) uniquely identifying an AP queue. AP instructions include
a field containing the APQN to identify the AP queue to which the AP
command is targetted.

* AP Instructions:

There are three AP instructions:

* NQAP: to enqueue an AP command-request message to a queue
* DQAP: to dequeue an AP command-reply message from a queue
* PQAP: to adminster the queues

Let's now see how AP instructions are interpreted by the hardware.

Start Interpretive Execution (SIE) Instruction
----------------------------------------------
A KVM guest is started by executing the Start Interpretive Execution (SIE)
instruction. The SIE state description is a control block that contains the
state information for a KVM guest and is supplied as input to the SIE
instruction. The SIE state description contains a field that references
a Crypto Control Block (CRYCB). The CRYCB contains three bitmask fields
identifying the adapters, usage domains and control domains assigned to the
KVM guest:

* The AP Mask (APM) field specifies the AP adapters assigned to the
KVM guest. The APM controls which adapters are valid for the KVM guest.
The bits in the mask, from left to right, correspond to APIDs
0 up to the number of adapters that can be assigned to the LPAR. If a bit
is set, the corresponding adapter is valid for use by the KVM guest.

* The AP Queue Mask (AQM) field specifies the AP usage domains assigned
to the KVM guest. The bits in the mask, from left to right, correspond
to the usage domains, from 0 up to the number of domains that can be
assigned to the LPAR. If a bit is set, the corresponding usage domain is
valid for use by the KVM guest.

* The AP Domain Mask field specifies the AP control domains assigned to the
KVM guest. The ADM bitmask controls which domains can be changed by an AP
command-request message sent to a usage domain from the guest. The bits in
the mask, from left to right, correspond to domain 0 up to the number of
domains that can be assigned to the LPAR. If a bit is set, the
corresponding domain can be modified by an AP command-request message
sent to a usage domain configured for the KVM guest.

If you recall from the description of an AP Queue, AP instructions include
an APQN to identify the AP adapter and the specific usage domain within
the adapter to which an AP command-request message is to be sent (NQAP
and PQAP instructions), or from which a command-reply message is to be
received (DQAP instruction). The validity of an APQN is defined by the
matrix calculated from the APM and AQM; it is the intersection of all
assigned adapter numbers (APM) with all assigned usage domain numbers (AQM).
For example, if adapters 1 and 2 and usage domains 5 and 6 are assigned to
a guest, the APQNs (1,5), (1,6), (2,5) and (2,6) will be valid for the
guest.

The APQNs provide secure key functionality - i.e., the key is stored on the
adapter card - so when the adapter card is not virtualized - i.e., the
adapter is accessed directly by the guest - each APQN must be assigned to
at most one guest.

Example 1: Valid configuration:
------------------------------
Guest1: adapters 1,2 domains 5,6
Guest2: adapter 1,2 domain 7

This is valid because both guests have a unique set of APQNs: Guest1 has
APQNs (1,5), (1,6), (2,5) and (2,6); Guest2 has APQN (1,7) and (2,7).

Example 2: Invalid configuration:
--------------------------------
Guest1: adapters 1,2 domains 5,6
Guest2: adapter 1 domains 6,7

This is an invalid configuration because both guests have access to
APQNs (1,6).

Interruption architecture:

The AP interruption architecture may or may not generate interruptions to
signal to the CPU the end of an AP transaction. The SIE interruption
architecture, depending upon its configuration, may or may not redirect
AP interrupts directly to a guest if the associated queue is valid for a
guest, and may or may not report the interruption to the host.

Effective masking for guest level I and II:

A linux host running in the LPAR operates at guest-level 1 and has its own
SIE state description. When operating at guest-level 1, the masks from the
host's state description are used directly. A linux guest running in the
host operates at guest-level 2. When operating at guest-level 2, the masks
from the guest-level 1 (host) and guest-level 2 (guest) state descriptions
are combined into a single description called an effective mask by
performing a logical AND of the two state descriptions.

The effective mask algorithm is used for the APM, AQM and ADM to create
an EAPM, EAQM and EADM respectively. Use of the EAPM, EAQM and EADM
precludes a guest-level 1 host program from passing to a guest-level 2
program APQNs to which it does not have access.

Linux cryptographic bus driver:

Linux already has a cryptographic bus driver that provides one AP device per
AP adapter and one device per AP queue. There is a device driver for each
type of AP adapter device and each type of AP queue device. This design
utilizes some of the interfaces and functionality provided by the AP bus
driver.

Design Origin:
-------------

The original design was based on modelling AP Queue devices. The design
utilized the VFIO mediated device framework whereby a mediated AP queue
device would be created for each AP Queue bound to the VFIO AP Queue device
driver. This at first seemed like the most logical design choice for the
following reasons:

* Securing access to an AP Queue device by unbinding it from its default
device driver and binding it to the VFIO device driver would not preclude
the host from having access to the other usage domains contained within
the same adapter card connected to the AP queue.

* An AP command is sent to a usage domain within a specific AP adapter via
an AP queue.

It became readily apparent that modelling the design on an AP queue was very
convoluted for a number of reasons:

* There is no convenient way to notify the VFIO device driver which guest
will have access to a given mediated AP queue device until the mediated
device's file descriptor is opened by the guest. Recall that the APQNs
configured for the guest are an intersection of all of the bits set in
both the APM and AQM, so the guest's APQNs can not be validated nor
its SIE state description configured until all of the guest's mediated
AP queue device file descriptors have been opened.

For example, suppose a guest opens file descriptors for mediated AP
queue devices representing APQNs 3,5 and 4,6. If bits 3 and 4 are set in
the guest's APM and bits 5 and 6 are set in the guest's AQM, then APQNs
(3,5), (3,6), (4,5) and (4,6) will be valid for the guest, but mediated
AP queue devices have been created only for APQNs (3,5) and (4,6). In
this case, APQNs still assigned to the host would also be available to
the guest which is a potential security breach.

* Control domains are not devices and are not logically modelled as
mediated devices. In our original design, they were modelled as
attributes of a mediated AP queue device, but this was a clumsy use of
the VFIO mediated device model.

* The SIE state description models the assignment of AP resources as a
matrix via the APM, AQM and ADM.

The design we ultimately settled upon was modelled on the AP matrix as
defined by the SIE state description. Supplying the complete AP matrix
to SIE using bitmasks when starting a guest simplifies the code, is far
easier to secure, and more closely matches the model employed by SIE. This
is the design model implemented via this patch set.

The Design
----------
This design introduces four new objects:

1. AP matrix bus

The sysfs location of the AP matrix bus is /sys/bus/ap_matrix. This
bus will create a single AP matrix device (see below).

2. AP matrix device

The AP matrix device is a singleton that hangs off of the AP matrix bus.
This device holds the AP Queues that have been reserved for use by
KVM guests. The sysfs location of the AP matrix device is
/sys/devices/ap_matrix/matrix. It is also linked from the AP matrix
bus at /sys/bus/ap_matrix/devices/matrix.

3. VFIO AP matrix driver

This driver is based on the VFIO mediated device framework. When the
driver is initialized, it will:

* Get the AP matrix device created by AP matrix bus from the bus

* Register with the AP bus to indicate that it can control AP Queue
devices. This allows AP Queue devices unbound from AP device drivers
to be bound to the VFIO AP matrix driver. The AP Queues bound to the
VFIO AP matrix driver will be stored by the driver in the AP matrix
device.

* Register the AP matrix device with the VFIO mediated device
framework (MDEV). Registration with MDEV will create the sysfs
structures needed to create mediated matrix devices. Each MDEV matrix
device is used to configure the AP matrix for a KVM guest. The MDEV
matrix device's file descriptor can be used by QEMU to communicate
with the VFIO AP matrix device driver.

The VFIO AP matrix driver:

* Provides the interfaces the administrator can use to secure AP Queues
for use by KVM guests. This is accomplished by unbinding the AP Queues
needed by each KVM guest from its AP device driver and binding it to
the VFIO AP queue driver. This prevents the host linux system from
using these Queues.

* Provides an ioctl that can be used by QEMU to configure the
CRYCB referenced by the KVM guest's SIE state description. The ioctl
will

* Create an EAPM, EAQM and EADM by performing a logical AND of the
APM, AQM and ADM configured via the MDEV matrix device's sysfs
attributes files (see below) with the APM, AQM and ADM of the host's
SIE state description respectively.

* Configure the SIE state description for the KVM guest using the
effective masks created in the previous step.

4. VFIO MDEV matrix passthrough device

An MDEV matrix passthrough device must be created for each KVM guest that
will need access to AP facilities. An MDEV matrix passthrough device is
used by QEMU to configure the APM, AQM and ADM fields of the CRYCB
referenced by the KVM guest's SIE state description. The file descriptor
for the MDEV matrix passthrough device provides the communication pathway
between QEMU and the VFIO AP matrix device driver.

The MDEV matrix passthrough device, like the CRYCB, contains three
bitmasks - an APM, AQM and ADM - for specifying the AP matrix for the
KVM guest. Three sets of attributes files will be provided to allow an
administrator to set the bits in the MDEV matrix device's APM, AQM and
ADM:

* A file to assign an AP adapter
* A file to unassign an AP adapter
* A file to display the adapters assigned

* A file to assign an AP domain
* A file to unassign an AP domain
* A file to display the domains assigned

* A file to assign an AP control domain
* A file to unassign an AP control domain
* A file to display the control domains assigned

Example:
-------
Let's now provide an example to illustrate how KVM guests may be given
access to AP facilities. For this example, we will show how to configure
two guests such that executing the lszcrypt command on the guests would
look like this:

Guest1
------
CARD.DOMAIN TYPE MODE
------------------------------
05 CEX5C CCA-Coproc
05.0004 CEX5C CCA-Coproc
05.00ab CEX5C CCA-Coproc
06 CEX5A Accelerator
06.0004 CEX5A Accelerator
06.00ab CEX5C CCA-Coproc

Guest2
------
CARD.DOMAIN TYPE MODE
------------------------------
05 CEX5A Accelerator
05.0047 CEX5A Accelerator
05.00ff CEX5A Accelerator

One thing to notice in this example is that each AP Queue set is identical.
For example, the two AP Queue sets for Guest1 both contain APQI 0004 and
00ab. It would be an invalid condition if both queue sets did not contain
the same set of queues. We could not, for example, configure Guest1 with
access to AP queue 05.00ff because the AP queue set for adapter 06 does not
contain AP queue 06.00ff. The point is, one must be careful to reserve
a valid set of AP queues for a given guest.
a valid configuration.

These are the steps for configuring the Guest1 and Guest2:

1. The first thing that needs to be done is to secure the AP queues to be
used by the two guests so that the host can not access them. This is done
by unbinding each AP Queue device from its respective AP driver. In our
example, these queues are bound to the cex4queue driver. This would be
the sysfs location of these devices:

/sys/bus/ap
--- [drivers]
------ [cex4queue]
--------- [05.0004]
--------- [05.0047]
--------- [05.00ab]
--------- [05.00ff]
--------- [06.0004]
--------- [06.00ab]
--------- unbind

To unbind AP queue 05.0004 from the cex4queue device driver:

echo 05.0004 > unbind

This must also be done for AP queues 05.00ab, 05.0047, 05.00ff, 06.0004,
and 06.00ab.

2. The next step is to reserve the queues for use by the two KVM guests.
This is accomplished by binding them to the VFIO AP matrix device driver.
This is the sysfs location of the VFIO AP matrix device driver:

/sys/bus/ap
---[drivers]
------ [vfio_ap_matrix]
---------- bind

To bind queue 05.0004 to the vfio_ap_matrix driver:

echo 05.0004 > bind

This must also be done for AP queues 05.00ab, 05.0047, 05.00ff, 06.0004,
and 06.00ab.

3. Create the mediated devices needed to configure the AP matrices for the
two guests and to provide an interface to the vfio_ap_matrix driver for
use by the guests:

/sys/devices/
--- [ap_matrix]
------ [matrix] (this is the matrix device)
--------- [mdev_supported_types]
------------ [ap_matrix-passthrough] (passthrough mediated device type)
--------------- create
--------------- [devices]

To create the mediated devices for the two guests:

uuidgen > create
uuidgen > create

This will create two mediated devices in the [devices] subdirectory named
with the UUID written to the create attribute file. We call them $uuid1
and $uuid2:

/sys/devices/
--- [ap_matrix]
------ [matrix]
--------- [mdev_supported_types]
------------ [ap_matrix-passthrough]
--------------- [devices]
------------------ [$uuid1]
--------------------- adapters
--------------------- assign_adapter
--------------------- assign_control_domain
--------------------- assign_domain
--------------------- control_domains
--------------------- domains
--------------------- unassign_adapter
--------------------- unassign_control_domain
--------------------- unassign_domain
------------------ [$uuid2]
--------------------- adapters
--------------------- assign_adapter
--------------------- assign_control_domain
--------------------- assign_domain
--------------------- control_domains
--------------------- domains
--------------------- unassign_adapter
--------------------- unassign_control_domain
--------------------- unassign_domain

4. The administrator now needs to configure the matrices for mediated
devices $uuid1 (for Guest1) and $uuid2 (for Guest2).

This is how the matrix is configured for Guest1:

echo 5 > assign_adapter
echo 6 > assign_adapter
echo 4 > assign_domain
echo ab > assign_domain

When the assign.xxx file is written, the corresponding bit in the
respective MDEV matrix device's bitmask will be set. For example, when
adapter 5 is assigned, bit 5 - numbered from left to right starting with
bit 0 - will be set in the MDEV matrix device's APM.

By architectural convention, all usage domains - i.e., domains assigned
via the assign_domain attribute file - will also be configured in the ADM
field of the KVM guest's CRYCB, so there is no need to assign control
domains here unless you want to assign control domains that are not
assigned as usage domains.

If a mistake is made configuring an adapter, domain or control domain,
you can use the unassign_xxx files to unassign the adapter, domain or
control domain.

To display the matrix configuration for Guest1:

cat adapters
cat domains
cat control_domains

This is how the matrix is configured for Guest2:

echo 5 > assign_adapter
echo 47 > assign_domain
echo ff > assign_domain

When a KVM guest is started, QEMU will open the file descriptor for its
MDEV matrix device. The VFIO AP matrix device driver will be notified
and will store the reference to the KVM guest's SIE state description.
QEMU will then call the VFIO AP matrix ioctl requesting that the
KVM guest's matrix be configured. The matrix driver will set the bits in the
APM, AQM and ADM fields of the CRYCB referenced by the guest's SIE state
description from the EAPM, EAQM and EADM created by performing a logical AND
of the AP masks configured in the MDEV matrix device and the masks
configured in the host's SIE state description. When the guest comes up, it
will have access to the APQNs identified in the AP matrix specified in the
KVM guest's SIE state description. Programs running on the guest will then
be able to use the cryptographic functions provided by the AP facilities
configured for the guest.

Tony Krowiak (19):
KVM: s390: SIE considerations for AP Queue virtualization
KVM: s390: refactor crypto initialization
s390/zcrypt: new AP matrix bus
s390/zcrypt: create an AP matrix device on the AP matrix bus
s390/zcrypt: base implementation of AP matrix device driver
s390/zcrypt: register matrix device with VFIO mediated device
framework
KVM: s390: introduce AP matrix configuration interface
s390/zcrypt: support for assigning adapters to matrix mdev
s390/zcrypt: validate adapter assignment
s390/zcrypt: sysfs interfaces supporting AP domain assignment
s390/zcrypt: validate domain assignment
s390/zcrypt: sysfs support for control domain assignment
s390/zcrypt: validate control domain assignment
KVM: s390: Connect the AP mediated matrix device to KVM
s390/zcrypt: introduce ioctl access to VFIO AP Matrix driver
KVM: s390: interface to configure KVM guest's AP matrix
KVM: s390: validate input to AP matrix config interface
KVM: s390: New ioctl to configure KVM guest's AP matrix
s390/facilities: enable AP facilities needed by guest

MAINTAINERS | 13 +
arch/s390/Kconfig | 13 +
arch/s390/configs/default_defconfig | 1 +
arch/s390/configs/gcov_defconfig | 1 +
arch/s390/configs/performance_defconfig | 1 +
arch/s390/defconfig | 1 +
arch/s390/include/asm/ap-config.h | 32 +
arch/s390/include/asm/kvm_host.h | 26 +-
arch/s390/kvm/Makefile | 2 +-
arch/s390/kvm/ap-config.c | 224 ++++++++
arch/s390/kvm/kvm-s390.c | 17 +-
arch/s390/tools/gen_facilities.c | 2 +
drivers/s390/crypto/Makefile | 6 +-
drivers/s390/crypto/ap_matrix_bus.c | 115 ++++
drivers/s390/crypto/ap_matrix_bus.h | 25 +
drivers/s390/crypto/vfio_ap_matrix_drv.c | 107 ++++
drivers/s390/crypto/vfio_ap_matrix_ops.c | 790 ++++++++++++++++++++++++++
drivers/s390/crypto/vfio_ap_matrix_private.h | 50 ++
include/uapi/linux/vfio.h | 22 +
19 files changed, 1438 insertions(+), 10 deletions(-)
create mode 100644 arch/s390/include/asm/ap-config.h
create mode 100644 arch/s390/kvm/ap-config.c
create mode 100644 drivers/s390/crypto/ap_matrix_bus.c
create mode 100644 drivers/s390/crypto/ap_matrix_bus.h
create mode 100644 drivers/s390/crypto/vfio_ap_matrix_drv.c
create mode 100644 drivers/s390/crypto/vfio_ap_matrix_ops.c
create mode 100644 drivers/s390/crypto/vfio_ap_matrix_private.h


From 1585955326421730549@xxx Tue Dec 05 14:41:01 +0000 2017
X-GM-THRID: 1585827627701114314
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread


2017-10-13 17:46:07

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 05/19] s390/zcrypt: base implementation of AP matrix device driver

Introduces a new AP matrix device driver. This device driver
will ultimately perform the following functions:

* Register with the AP bus to let it know that the matrix
driver can control AP queue devices. This will allow
an administrator to unbind an AP queue device from its
device driver and bind it to the matrix device driver.
This is how AP queue devices will be reserved for use
by guest machines.

* Register the matrix device created by the AP matrix bus
with the VFIO mediated device framework. This will create
the sysfs entries needed to create mediated matrix devices.
Each mediated matrix device can be configured with a matrix
of adapters, usage domains and control domains that can be
accessed by a guest machine.

* Process requests via ioctl calls defined for the mediated
matrix device. The guest can access the ioctl calls via
the mediated device's file descriptor to:

* Grant access to the adapters, usage domains and
control domains configured for the mediated matrix
device.

This device driver
is built on the VFIO mediated device framework. The VFIO mediated
device framework allows a mediated device to be dedicated exclusively
to a single guest VM.

Signed-off-by: Tony Krowiak <[email protected]>
---
MAINTAINERS | 2 +
arch/s390/Kconfig | 13 +++
arch/s390/configs/default_defconfig | 1 +
arch/s390/configs/gcov_defconfig | 1 +
arch/s390/configs/performance_defconfig | 1 +
arch/s390/defconfig | 1 +
drivers/s390/crypto/Makefile | 6 +-
drivers/s390/crypto/ap_matrix_bus.c | 8 ++
drivers/s390/crypto/ap_matrix_bus.h | 2 +-
drivers/s390/crypto/vfio_ap_matrix_drv.c | 102 ++++++++++++++++++++++++++
drivers/s390/crypto/vfio_ap_matrix_private.h | 47 ++++++++++++
11 files changed, 182 insertions(+), 2 deletions(-)
create mode 100644 drivers/s390/crypto/vfio_ap_matrix_drv.c
create mode 100644 drivers/s390/crypto/vfio_ap_matrix_private.h

diff --git a/MAINTAINERS b/MAINTAINERS
index cbd6f7c..115965e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11718,6 +11718,8 @@ W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported
F: drivers/s390/crypto/ap_matrix_bus.h
F: drivers/s390/crypto/ap_matrix_bus.c
+F: drivers/s390/crypto/vfio_ap_matrix_drv.c
+F: drivers/s390/crypto/vfio_ap_matrix_private.h

S390 ZFCP DRIVER
M: Steffen Maier <[email protected]>
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 48af970..411c19a 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -722,6 +722,19 @@ config VFIO_CCW
To compile this driver as a module, choose M here: the
module will be called vfio_ccw.

+config VFIO_AP_MATRIX
+ def_tristate m
+ prompt "Support for Adjunct Processor Matrix device interface"
+ depends on ZCRYPT
+ select VFIO
+ select MDEV
+ select VFIO_MDEV
+ select VFIO_MDEV_DEVICE
+ select IOMMU_API
+ help
+ driver grants access to Adjunct Processor (AP) devices
+ via the VFIO mediated device interface.
+
endmenu

menu "Dump support"
diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig
index 2820722..d913042 100644
--- a/arch/s390/configs/default_defconfig
+++ b/arch/s390/configs/default_defconfig
@@ -725,3 +725,4 @@ CONFIG_APPLDATA_BASE=y
CONFIG_KVM=m
CONFIG_KVM_S390_UCONTROL=y
CONFIG_VHOST_NET=m
+CONFIG_VFIO_AP_MATRIX=m
diff --git a/arch/s390/configs/gcov_defconfig b/arch/s390/configs/gcov_defconfig
index 3c6b781..5f08278 100644
--- a/arch/s390/configs/gcov_defconfig
+++ b/arch/s390/configs/gcov_defconfig
@@ -666,3 +666,4 @@ CONFIG_APPLDATA_BASE=y
CONFIG_KVM=m
CONFIG_KVM_S390_UCONTROL=y
CONFIG_VHOST_NET=m
+CONFIG_VFIO_AP_MATRIX=m
diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig
index 653d72b..4b77519 100644
--- a/arch/s390/configs/performance_defconfig
+++ b/arch/s390/configs/performance_defconfig
@@ -664,3 +664,4 @@ CONFIG_APPLDATA_BASE=y
CONFIG_KVM=m
CONFIG_KVM_S390_UCONTROL=y
CONFIG_VHOST_NET=m
+CONFIG_VFIO_AP_MATRIX=m
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 20244a3..aa46cb5 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -242,3 +242,4 @@ CONFIG_CRC7=m
# CONFIG_XZ_DEC_ARMTHUMB is not set
# CONFIG_XZ_DEC_SPARC is not set
CONFIG_CMM=m
+CONFIG_VFIO_AP_MATRIX=m
diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile
index 87646ca..1983afa 100644
--- a/drivers/s390/crypto/Makefile
+++ b/drivers/s390/crypto/Makefile
@@ -13,4 +13,8 @@ obj-$(CONFIG_ZCRYPT) += zcrypt_pcixcc.o zcrypt_cex2a.o zcrypt_cex4.o

# pkey kernel module
pkey-objs := pkey_api.o
-obj-$(CONFIG_PKEY) += pkey.o
\ No newline at end of file
+obj-$(CONFIG_PKEY) += pkey.o
+
+# adjunct processor matrix
+vfio_ap_matrix-objs := vfio_ap_matrix_drv.o
+obj-$(CONFIG_VFIO_AP_MATRIX) += vfio_ap_matrix.o
diff --git a/drivers/s390/crypto/ap_matrix_bus.c b/drivers/s390/crypto/ap_matrix_bus.c
index 4eb1e3c..66bfa54 100644
--- a/drivers/s390/crypto/ap_matrix_bus.c
+++ b/drivers/s390/crypto/ap_matrix_bus.c
@@ -75,10 +75,18 @@ static int ap_matrix_dev_create(void)
return 0;
}

+struct ap_matrix *ap_matrix_get_device(void)
+{
+ return matrix;
+}
+EXPORT_SYMBOL(ap_matrix_get_device);
+
int __init ap_matrix_init(void)
{
int ret;

+ matrix = NULL;
+
ap_matrix_root_device = root_device_register(AP_MATRIX_BUS_NAME);
ret = PTR_RET(ap_matrix_root_device);
if (ret)
diff --git a/drivers/s390/crypto/ap_matrix_bus.h b/drivers/s390/crypto/ap_matrix_bus.h
index 225db4f..c2aff23 100644
--- a/drivers/s390/crypto/ap_matrix_bus.h
+++ b/drivers/s390/crypto/ap_matrix_bus.h
@@ -16,6 +16,6 @@ struct ap_matrix {
struct device device;
};

-int ap_matrix_init(void);
+struct ap_matrix *ap_matrix_get_device(void);

#endif /* _AP_MATRIX_BUS_H_ */
diff --git a/drivers/s390/crypto/vfio_ap_matrix_drv.c b/drivers/s390/crypto/vfio_ap_matrix_drv.c
new file mode 100644
index 0000000..760ed56
--- /dev/null
+++ b/drivers/s390/crypto/vfio_ap_matrix_drv.c
@@ -0,0 +1,102 @@
+/*
+ * VFIO based AP Matrix device driver
+ *
+ * Copyright IBM Corp. 2017
+ *
+ * Author(s): Tony Krowiak <[email protected]>
+ */
+
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include "ap_bus.h"
+#include "ap_matrix_bus.h"
+#include "vfio_ap_matrix_private.h"
+
+#define VFIO_AP_MATRIX_DRV_NAME "vfio_ap_queue"
+
+MODULE_AUTHOR("IBM Corporation");
+MODULE_DESCRIPTION("AP Matrix device driver, Copyright IBM Corp. 2017");
+MODULE_LICENSE("GPL v2");
+
+static struct ap_device_id ap_queue_ids[] = {
+ { .dev_type = AP_DEVICE_TYPE_CEX4,
+ .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
+ { .dev_type = AP_DEVICE_TYPE_CEX5,
+ .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
+ { .dev_type = AP_DEVICE_TYPE_CEX6,
+ .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
+ { /* end of list */ },
+};
+
+MODULE_DEVICE_TABLE(ap_matrix, ap_queue_ids);
+
+static struct ap_matrix_driver {
+ struct ap_driver ap_drv;
+ struct ap_matrix *ap_matrix;
+} vfio_ap_matrix_drv;
+
+static int ap_matrix_queue_dev_probe(struct ap_device *apdev)
+{
+ struct vfio_ap_queue *vapq;
+ struct ap_queue *apq = to_ap_queue(&apdev->device);
+ struct ap_matrix *ap_matrix = vfio_ap_matrix_drv.ap_matrix;
+
+ vapq = kzalloc(sizeof(*vapq), GFP_KERNEL);
+ if (!vapq)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&vapq->list);
+ vapq->queue = apq;
+ spin_lock_bh(&ap_matrix->qlock);
+ list_add_tail(&vapq->list, &ap_matrix->queues);
+ spin_unlock_bh(&ap_matrix->qlock);
+
+ return 0;
+}
+
+static void ap_matrix_queue_dev_remove(struct ap_device *apdev)
+{
+ struct vfio_ap_queue *vapq;
+ struct ap_queue *apq = to_ap_queue(&apdev->device);
+ struct ap_matrix *ap_matrix = vfio_ap_matrix_drv.ap_matrix;
+
+ vapq = find_vapq(ap_matrix, apq->qid);
+
+ if (vapq) {
+ spin_lock_bh(&ap_matrix->qlock);
+ list_del_init(&vapq->list);
+ spin_unlock_bh(&ap_matrix->qlock);
+ kfree(vapq);
+ }
+}
+
+int __init ap_matrix_init(void)
+{
+
+ int ret;
+
+ vfio_ap_matrix_drv.ap_matrix = ap_matrix_get_device();
+ if (!vfio_ap_matrix_drv.ap_matrix)
+ return -ENODEV;
+
+ vfio_ap_matrix_drv.ap_drv.probe = ap_matrix_queue_dev_probe;
+ vfio_ap_matrix_drv.ap_drv.remove = ap_matrix_queue_dev_remove;
+ vfio_ap_matrix_drv.ap_drv.ids = ap_queue_ids;
+
+ ret = ap_driver_register(&vfio_ap_matrix_drv.ap_drv,
+ THIS_MODULE, VFIO_AP_MATRIX_DRV_NAME);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+void __exit ap_matrix_exit(void)
+{
+ ap_driver_unregister(&vfio_ap_matrix_drv.ap_drv);
+}
+
+module_init(ap_matrix_init);
+module_exit(ap_matrix_exit);
diff --git a/drivers/s390/crypto/vfio_ap_matrix_private.h b/drivers/s390/crypto/vfio_ap_matrix_private.h
new file mode 100644
index 0000000..11c5e02
--- /dev/null
+++ b/drivers/s390/crypto/vfio_ap_matrix_private.h
@@ -0,0 +1,47 @@
+/*
+ * Private data and functions for adjunct processor VFIO matrix driver.
+ *
+ * Copyright IBM Corp. 2016
+ * Author(s): Tony Krowiak <[email protected]>
+ */
+
+#ifndef _VFIO_AP_PRIVATE_H_
+#define _VFIO_AP_PRIVATE_H_
+
+#include <linux/types.h>
+
+#include "ap_bus.h"
+#include "ap_matrix_bus.h"
+
+#define VFIO_AP_MATRIX_MODULE_NAME "vfio_ap_matrix"
+
+struct vfio_ap_queue {
+ struct ap_queue *queue;
+ struct list_head list;
+};
+
+static inline struct vfio_ap_queue *to_vapq(struct ap_device *ap_dev)
+{
+ struct ap_queue *ap_queue = to_ap_queue(&ap_dev->device);
+ struct vfio_ap_queue *vapq;
+
+ vapq = container_of(&ap_queue, struct vfio_ap_queue, queue);
+
+ return vapq;
+}
+
+static inline struct vfio_ap_queue *find_vapq(struct ap_matrix *ap_matrix,
+ ap_qid_t qid)
+{
+ struct vfio_ap_queue *vapq;
+
+ if (!list_empty(&ap_matrix->queues)) {
+ list_for_each_entry(vapq, &ap_matrix->queues, list)
+ if (vapq->queue->qid == qid)
+ return vapq;
+ }
+
+ return NULL;
+}
+
+#endif /* _VFIO_AP_PRIVATE_H_ */
--
1.7.1


From 1584605859606801236@xxx Mon Nov 20 17:11:49 +0000 2017
X-GM-THRID: 1584605859606801236
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-10-13 17:45:01

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 08/19] s390/zcrypt: support for assigning adapters to matrix mdev

Provides the sysfs interfaces for assigning an adapter to
and unassigning an AP adapter from a mediated matrix device.

The IDs of the AP adapters assigned to the mediated matrix
device are stored in a bit mask. The bits in the mask, from
left to right, correspond to AP adapter numbers 0 to 255. The
bit corresponding to the ID of the adapter being assigned will
be set in the bit mask.

The relevant sysfs structures are:

/sys/devices/ap_matrix
... [matrix]
...... [mdev_supported_types]
......... [ap_matrix-passthrough]
............ [devices]
...............[$uuid]
.................. adapters
.................. assign_adapter
.................. unassign_adapter

To assign an adapter to the $uuid mediated matrix device, write
ID of the adapter (hex value) to the assign_adapter file. To
unassign an adapter, write the ID of the adapter (hex value)
to the unassign_adapter file. The list of adapters that have
been assigned can be viewed by displaying the contents of the
adapters file.

For example, to assign adapter 0xad to mediated matrix device
$uuid:

echo ad > assign_adapter

To unassign adapter 0xad:

echo ad > unassign_adapter

To see the list of adapters assigned:

cat adapters

Signed-off-by: Tony Krowiak <[email protected]>
---
arch/s390/include/asm/ap-config.h | 13 +++
drivers/s390/crypto/vfio_ap_matrix_ops.c | 147 ++++++++++++++++++++++++++++++
2 files changed, 160 insertions(+), 0 deletions(-)

diff --git a/arch/s390/include/asm/ap-config.h b/arch/s390/include/asm/ap-config.h
index 8491b5f..3064215 100644
--- a/arch/s390/include/asm/ap-config.h
+++ b/arch/s390/include/asm/ap-config.h
@@ -9,4 +9,17 @@
#ifndef _ASM_KVM_AP_CONFIG_H_
#define _ASM_KVM_AP_CONFIG_H_

+#include <linux/types.h>
+
+#define AP_MATRIX_MAX_MASK_BITS 256
+#define AP_MATRIX_MASK_INDICES (AP_MATRIX_MAX_MASK_BITS / \
+ (sizeof(u64) * 8))
+#define AP_MATRIX_MAX_MASK_BYTES (AP_MATRIX_MASK_INDICES * sizeof(u64))
+
+struct ap_config_masks {
+ u64 apm[AP_MATRIX_MASK_INDICES];
+ u64 aqm[AP_MATRIX_MASK_INDICES];
+ u64 adm[AP_MATRIX_MASK_INDICES];
+};
+
#endif /* _ASM_KVM_AP_CONFIG_H_ */
diff --git a/drivers/s390/crypto/vfio_ap_matrix_ops.c b/drivers/s390/crypto/vfio_ap_matrix_ops.c
index 7d01f18..e4b1236 100644
--- a/drivers/s390/crypto/vfio_ap_matrix_ops.c
+++ b/drivers/s390/crypto/vfio_ap_matrix_ops.c
@@ -23,6 +23,7 @@
struct ap_matrix_mdev {
struct mdev_device *mdev;
struct list_head node;
+ struct ap_config_masks masks;
};

struct ap_matrix *matrix;
@@ -136,9 +137,155 @@ static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
NULL,
};

+static int ap_matrix_id_is_xnum(char *id)
+{
+ size_t i;
+
+ for (i = 0; i < strlen(id); i++) {
+ if (!isxdigit(id[i]))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int ap_matrix_parse_id(const char *buf, unsigned int *id)
+{
+ int ret;
+ char *bufcpy;
+ char *id_str;
+
+ if ((strlen(buf) == 0) || (*buf == '\n')) {
+ pr_err("%s: input buffer '%s' contains no valid hex values",
+ VFIO_AP_MATRIX_MODULE_NAME, buf);
+ return -EINVAL;
+ }
+
+ bufcpy = kzalloc(strlen(buf) + 1, GFP_KERNEL);
+ if (!bufcpy)
+ return -ENOMEM;
+
+ strcpy(bufcpy, buf);
+ id_str = strim(bufcpy);
+
+ if (!ap_matrix_id_is_xnum(id_str)) {
+ pr_err("%s: input id '%s' contains an invalid hex value '%s'",
+ VFIO_AP_MATRIX_MODULE_NAME, buf, id_str);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = kstrtouint (id_str, 16, id);
+ if (ret || (*id >= AP_MATRIX_MAX_MASK_BITS)) {
+ pr_err("%s: input id '%s' is not a value from 0 to %x",
+ VFIO_AP_MATRIX_MODULE_NAME, buf,
+ AP_MATRIX_MAX_MASK_BITS);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ kfree(bufcpy);
+ return ret;
+}
+
+static ssize_t ap_matrix_adapters_assign(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ unsigned int apid;
+ struct mdev_device *mdev = mdev_from_dev(dev);
+ struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+
+ ret = ap_matrix_parse_id(buf, &apid);
+ if (ret)
+ return ret;
+
+ set_bit_inv((unsigned long)apid,
+ (unsigned long *)matrix_mdev->masks.apm);
+
+ return count;
+}
+static DEVICE_ATTR(assign_adapter, 0644, NULL, ap_matrix_adapters_assign);
+
+static ssize_t ap_matrix_adapters_unassign(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ unsigned int apid;
+ struct mdev_device *mdev = mdev_from_dev(dev);
+ struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+
+ ret = ap_matrix_parse_id(buf, &apid);
+ if (ret)
+ return ret;
+
+ clear_bit_inv((unsigned long)apid,
+ (unsigned long *)matrix_mdev->masks.apm);
+
+ return count;
+}
+static DEVICE_ATTR(unassign_adapter, 0644, NULL, ap_matrix_adapters_unassign);
+
+static ssize_t ap_matrix_adapters_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mdev_device *mdev = mdev_from_dev(dev);
+ struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ unsigned long *apm = (unsigned long *)matrix_mdev->masks.apm;
+ unsigned long id;
+ unsigned long nbits = 256;
+ char *bufpos = buf;
+ int nchars = 0;
+ int n;
+
+ id = find_first_bit_inv(apm, nbits);
+ while (id < nbits) {
+ if (nchars) {
+ n = sprintf(bufpos, ",");
+ bufpos += n;
+ nchars += n;
+ }
+
+ n = sprintf(bufpos, "%02lx", id);
+ bufpos += n;
+ nchars += n;
+ id = find_next_bit_inv(apm, nbits, id + 1);
+ }
+
+ n = sprintf(bufpos, "\n");
+ bufpos += n;
+ nchars += n;
+
+ return nchars;
+}
+static DEVICE_ATTR(adapters, 0644, ap_matrix_adapters_show, NULL);
+
+static struct attribute *ap_matrix_mdev_attrs[] = {
+ &dev_attr_assign_adapter.attr,
+ &dev_attr_unassign_adapter.attr,
+ &dev_attr_adapters.attr,
+ NULL
+};
+
+static struct attribute_group ap_matrix_mdev_attr_group = {
+ .attrs = ap_matrix_mdev_attrs
+};
+
+static const struct attribute_group *ap_matrix_mdev_attr_groups[] = {
+ &ap_matrix_mdev_attr_group,
+ NULL
+};
+
static const struct mdev_parent_ops vfio_ap_matrix_ops = {
.owner = THIS_MODULE,
.supported_type_groups = ap_matrix_mdev_type_groups,
+ .mdev_attr_groups = ap_matrix_mdev_attr_groups,
.create = ap_matrix_mdev_create,
.remove = ap_matrix_mdev_remove,
};
--
1.7.1


From 1584872937556752437@xxx Thu Nov 23 15:56:55 +0000 2017
X-GM-THRID: 1584872937556752437
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-10-13 17:45:56

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 06/19] s390/zcrypt: register matrix device with VFIO mediated device framework

Registers the matrix device created by the AP matrix bus with
the VFIO mediated device framework. Registering the matrix
device will create the sysfs structures needed to create
mediated matrix devices that can be configured with a matrix
of adapters, usage domains and control domains for a guest
machine.

Registering the matrix device with the VFIO mediated device
framework will create the following sysfs structures:

/sys/devices/ap_matrix
... [matrix]
...... [mdev_supported_types]
......... [ap_matrix-passthrough]
............ available_instances
............ create
............ device_api
............ [devices]
............ name

To create a mediated device for the AP matrix device, write a UUID
to the create file:

uuidgen > create

A symbolic link to the mediated device's directory will be created in the
devices subdirectory named after the generated $uuid:

/sys/devices/ap_matrix
... [matrix]
...... [mdev_supported_types]
......... [ap_matrix-passthrough]
............ [devices]
............... [$uuid]

Signed-off-by: Tony Krowiak <[email protected]>
---
MAINTAINERS | 1 +
drivers/s390/crypto/Makefile | 2 +-
drivers/s390/crypto/ap_matrix_bus.c | 1 +
drivers/s390/crypto/ap_matrix_bus.h | 4 +
drivers/s390/crypto/vfio_ap_matrix_drv.c | 5 +
drivers/s390/crypto/vfio_ap_matrix_ops.c | 172 ++++++++++++++++++++++++++
drivers/s390/crypto/vfio_ap_matrix_private.h | 3 +
include/uapi/linux/vfio.h | 1 +
8 files changed, 188 insertions(+), 1 deletions(-)
create mode 100644 drivers/s390/crypto/vfio_ap_matrix_ops.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 115965e..0c8855a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11720,6 +11720,7 @@ F: drivers/s390/crypto/ap_matrix_bus.h
F: drivers/s390/crypto/ap_matrix_bus.c
F: drivers/s390/crypto/vfio_ap_matrix_drv.c
F: drivers/s390/crypto/vfio_ap_matrix_private.h
+F: drivers/s390/crypto/vfio_ap_matrix_ops.c

S390 ZFCP DRIVER
M: Steffen Maier <[email protected]>
diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile
index 1983afa..b2545c8 100644
--- a/drivers/s390/crypto/Makefile
+++ b/drivers/s390/crypto/Makefile
@@ -16,5 +16,5 @@ pkey-objs := pkey_api.o
obj-$(CONFIG_PKEY) += pkey.o

# adjunct processor matrix
-vfio_ap_matrix-objs := vfio_ap_matrix_drv.o
+vfio_ap_matrix-objs := vfio_ap_matrix_drv.o vfio_ap_matrix_ops.o
obj-$(CONFIG_VFIO_AP_MATRIX) += vfio_ap_matrix.o
diff --git a/drivers/s390/crypto/ap_matrix_bus.c b/drivers/s390/crypto/ap_matrix_bus.c
index 66bfa54..418c23b 100644
--- a/drivers/s390/crypto/ap_matrix_bus.c
+++ b/drivers/s390/crypto/ap_matrix_bus.c
@@ -61,6 +61,7 @@ static int ap_matrix_dev_create(void)
matrix->device.bus = &ap_matrix_bus_type;
matrix->device.parent = ap_matrix_root_device;
matrix->device.release = ap_matrix_dev_release;
+ INIT_LIST_HEAD(&matrix->queues);

ret = device_register(&matrix->device);
if (ret) {
diff --git a/drivers/s390/crypto/ap_matrix_bus.h b/drivers/s390/crypto/ap_matrix_bus.h
index c2aff23..3eccc36 100644
--- a/drivers/s390/crypto/ap_matrix_bus.h
+++ b/drivers/s390/crypto/ap_matrix_bus.h
@@ -12,8 +12,12 @@

#include <linux/device.h>

+#include "ap_bus.h"
+
struct ap_matrix {
struct device device;
+ spinlock_t qlock;
+ struct list_head queues;
};

struct ap_matrix *ap_matrix_get_device(void);
diff --git a/drivers/s390/crypto/vfio_ap_matrix_drv.c b/drivers/s390/crypto/vfio_ap_matrix_drv.c
index 760ed56..664d2f7 100644
--- a/drivers/s390/crypto/vfio_ap_matrix_drv.c
+++ b/drivers/s390/crypto/vfio_ap_matrix_drv.c
@@ -90,11 +90,16 @@ int __init ap_matrix_init(void)
if (ret)
return ret;

+ ret = ap_matrix_mdev_register(vfio_ap_matrix_drv.ap_matrix);
+ if (ret)
+ ap_driver_unregister(&vfio_ap_matrix_drv.ap_drv);
+
return ret;
}

void __exit ap_matrix_exit(void)
{
+ ap_matrix_mdev_unregister(vfio_ap_matrix_drv.ap_matrix);
ap_driver_unregister(&vfio_ap_matrix_drv.ap_drv);
}

diff --git a/drivers/s390/crypto/vfio_ap_matrix_ops.c b/drivers/s390/crypto/vfio_ap_matrix_ops.c
new file mode 100644
index 0000000..7d01f18
--- /dev/null
+++ b/drivers/s390/crypto/vfio_ap_matrix_ops.c
@@ -0,0 +1,172 @@
+/*
+ * Adjunct processor matrix VFIO device driver callbacks.
+ *
+ * Copyright IBM Corp. 2017
+ * Author(s): Tony Krowiak <[email protected]>
+ *
+ */
+#include <asm/ap-config.h>
+#include <linux/string.h>
+#include <linux/vfio.h>
+#include <linux/mdev.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/ctype.h>
+
+#include "vfio_ap_matrix_private.h"
+
+#define AP_MATRIX_MDEV_TYPE_HWVIRT "passthrough"
+#define AP_MATRIX_MDEV_NAME_HWVIRT "AP Matrix Passthrough Device"
+
+#define AP_MATRIX_MAX_AVAILABLE_INSTANCES 255
+
+struct ap_matrix_mdev {
+ struct mdev_device *mdev;
+ struct list_head node;
+};
+
+struct ap_matrix *matrix;
+struct mutex mdev_devices_lock;
+struct list_head mdev_devices;
+int available_instances;
+
+static struct ap_matrix_mdev *ap_matrix_mdev_find_by_uuid(uuid_le uuid)
+{
+ struct ap_matrix_mdev *matrix_mdev;
+
+ list_for_each_entry(matrix_mdev, &mdev_devices, node) {
+ if (uuid_le_cmp(mdev_uuid(matrix_mdev->mdev), uuid) == 0)
+ return matrix_mdev;
+ }
+
+ return NULL;
+}
+
+static int ap_matrix_mdev_create(struct kobject *kobj,
+ struct mdev_device *mdev)
+{
+ struct ap_matrix_mdev *matrix_mdev;
+ uuid_le uuid;
+
+ if (available_instances == 0) {
+ pr_err("%s: Only %d mediated devices allowed for %s-%s device",
+ VFIO_AP_MATRIX_MODULE_NAME,
+ AP_MATRIX_MAX_AVAILABLE_INSTANCES,
+ VFIO_AP_MATRIX_MODULE_NAME,
+ AP_MATRIX_MDEV_TYPE_HWVIRT);
+ return -EPERM;
+ }
+
+ uuid = mdev_uuid(mdev);
+ matrix_mdev = ap_matrix_mdev_find_by_uuid(uuid);
+ if (matrix_mdev) {
+ pr_err("%s: Mediated device %pU already exists",
+ VFIO_AP_MATRIX_MODULE_NAME, uuid.b);
+ return -EEXIST;
+ }
+
+ matrix_mdev = kzalloc(sizeof(*matrix_mdev), GFP_KERNEL);
+ if (!matrix_mdev)
+ return -ENOMEM;
+
+ mdev_set_drvdata(mdev, matrix_mdev);
+ mutex_lock(&mdev_devices_lock);
+ list_add_tail(&matrix_mdev->node, &mdev_devices);
+ mutex_unlock(&mdev_devices_lock);
+
+ return 0;
+}
+
+static int ap_matrix_mdev_remove(struct mdev_device *mdev)
+{
+ struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+ uuid_le uuid = mdev_uuid(mdev);
+
+ matrix_mdev = ap_matrix_mdev_find_by_uuid(uuid);
+
+ if (matrix_mdev) {
+ mutex_lock(&mdev_devices_lock);
+ list_del(&matrix_mdev->node);
+ mutex_unlock(&mdev_devices_lock);
+ mdev_set_drvdata(mdev, NULL);
+ kfree(matrix_mdev);
+ available_instances--;
+ }
+
+ return 0;
+}
+
+static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+ return sprintf(buf, "%s\n", AP_MATRIX_MDEV_NAME_HWVIRT);
+}
+
+MDEV_TYPE_ATTR_RO(name);
+
+static ssize_t available_instances_show(struct kobject *kobj,
+ struct device *dev, char *buf)
+{
+ return sprintf(buf, "%d\n", available_instances);
+}
+
+MDEV_TYPE_ATTR_RO(available_instances);
+
+static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_MATRIX_STRING);
+}
+
+MDEV_TYPE_ATTR_RO(device_api);
+
+static struct attribute *ap_matrix_mdev_type_attrs[] = {
+ &mdev_type_attr_name.attr,
+ &mdev_type_attr_device_api.attr,
+ &mdev_type_attr_available_instances.attr,
+ NULL,
+};
+
+static struct attribute_group ap_matrix_mdev_hwvirt_type_group = {
+ .name = AP_MATRIX_MDEV_TYPE_HWVIRT,
+ .attrs = ap_matrix_mdev_type_attrs,
+};
+
+static struct attribute_group *ap_matrix_mdev_type_groups[] = {
+ &ap_matrix_mdev_hwvirt_type_group,
+ NULL,
+};
+
+static const struct mdev_parent_ops vfio_ap_matrix_ops = {
+ .owner = THIS_MODULE,
+ .supported_type_groups = ap_matrix_mdev_type_groups,
+ .create = ap_matrix_mdev_create,
+ .remove = ap_matrix_mdev_remove,
+};
+
+int ap_matrix_mdev_register(struct ap_matrix *ap_matrix)
+{
+ int ret;
+ struct device *dev = &ap_matrix->device;
+
+ ret = mdev_register_device(dev, &vfio_ap_matrix_ops);
+ if (ret)
+ return ret;
+
+ matrix = ap_matrix;
+ mutex_init(&mdev_devices_lock);
+ INIT_LIST_HEAD(&mdev_devices);
+ available_instances = AP_MATRIX_MAX_AVAILABLE_INSTANCES;
+
+ return 0;
+}
+
+void ap_matrix_mdev_unregister(struct ap_matrix *ap_matrix)
+{
+ struct device *dev;
+
+ if (ap_matrix == matrix) {
+ dev = &matrix->device;
+ available_instances--;
+ mdev_unregister_device(dev);
+ }
+}
diff --git a/drivers/s390/crypto/vfio_ap_matrix_private.h b/drivers/s390/crypto/vfio_ap_matrix_private.h
index 11c5e02..5c82bea 100644
--- a/drivers/s390/crypto/vfio_ap_matrix_private.h
+++ b/drivers/s390/crypto/vfio_ap_matrix_private.h
@@ -44,4 +44,7 @@ struct vfio_ap_queue {
return NULL;
}

+extern int ap_matrix_mdev_register(struct ap_matrix *ap_matrix);
+extern void ap_matrix_mdev_unregister(struct ap_matrix *ap_matrix);
+
#endif /* _VFIO_AP_PRIVATE_H_ */
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index ae46105..743456f 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -214,6 +214,7 @@ struct vfio_device_info {
#define VFIO_DEVICE_API_PLATFORM_STRING "vfio-platform"
#define VFIO_DEVICE_API_AMBA_STRING "vfio-amba"
#define VFIO_DEVICE_API_CCW_STRING "vfio-ccw"
+#define VFIO_DEVICE_API_AP_MATRIX_STRING "vfio-ap-matrix"

/**
* VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8,
--
1.7.1


From 1584157826513164299@xxx Wed Nov 15 18:30:32 +0000 2017
X-GM-THRID: 1584157826513164299
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-10-13 17:46:28

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 07/19] KVM: s390: introduce AP matrix configuration interface

This patch introduces a new compilation unit that will contain
all of the data structures and logic for configuring AP adapters,
usage domains and control domains for a KVM guest.

Signed-off-by: Tony Krowiak <[email protected]>
---
MAINTAINERS | 2 ++
arch/s390/include/asm/ap-config.h | 12 ++++++++++++
arch/s390/kvm/Makefile | 2 +-
arch/s390/kvm/ap-config.c | 9 +++++++++
4 files changed, 24 insertions(+), 1 deletions(-)
create mode 100644 arch/s390/include/asm/ap-config.h
create mode 100644 arch/s390/kvm/ap-config.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0c8855a..4de0904 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11721,6 +11721,8 @@ F: drivers/s390/crypto/ap_matrix_bus.c
F: drivers/s390/crypto/vfio_ap_matrix_drv.c
F: drivers/s390/crypto/vfio_ap_matrix_private.h
F: drivers/s390/crypto/vfio_ap_matrix_ops.c
+F: arch/s390/include/asm/kvm/ap-config.h
+F: arch/s390/kvm/ap-config.c

S390 ZFCP DRIVER
M: Steffen Maier <[email protected]>
diff --git a/arch/s390/include/asm/ap-config.h b/arch/s390/include/asm/ap-config.h
new file mode 100644
index 0000000..8491b5f
--- /dev/null
+++ b/arch/s390/include/asm/ap-config.h
@@ -0,0 +1,12 @@
+/*
+ * Adjunct Processor (AP) configuration management for KVM guests
+ *
+ * Copyright IBM Corp. 2017
+ *
+ * Author(s): Tony Krowiak <[email protected]>
+ */
+
+#ifndef _ASM_KVM_AP_CONFIG_H_
+#define _ASM_KVM_AP_CONFIG_H_
+
+#endif /* _ASM_KVM_AP_CONFIG_H_ */
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index 09a9e6d..0397b9c 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -12,6 +12,6 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqch
ccflags-y := -Ivirt/kvm -Iarch/s390/kvm

kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o
-kvm-objs += diag.o gaccess.o guestdbg.o sthyi.o vsie.o
+kvm-objs += diag.o gaccess.o guestdbg.o sthyi.o vsie.o ap-config.o

obj-$(CONFIG_KVM) += kvm.o
diff --git a/arch/s390/kvm/ap-config.c b/arch/s390/kvm/ap-config.c
new file mode 100644
index 0000000..84fdf43
--- /dev/null
+++ b/arch/s390/kvm/ap-config.c
@@ -0,0 +1,9 @@
+/*
+ * Adjunct Processor (AP) configuration management for KVM guests
+ *
+ * Copyright IBM Corp. 2017
+ *
+ * Author(s): Tony Krowiak <[email protected]>
+ */
+
+#include <asm/ap-config.h>
--
1.7.1


From 1584367599228607752@xxx Sat Nov 18 02:04:47 +0000 2017
X-GM-THRID: 1584367599228607752
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-10-13 17:47:52

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 03/19] s390/zcrypt: new AP matrix bus

Introduces an AP matrix bus. The sysfs location of the
AP matrix bus is:

/sys/bus/ap_matrix

The AP matrix bus will create an AP matrix device that will
hold the AP queues reserved for use by KVM guests.

Signed-off-by: Tony Krowiak <[email protected]>
---
MAINTAINERS | 8 +++++
drivers/s390/crypto/Makefile | 4 +-
drivers/s390/crypto/ap_matrix_bus.c | 52 +++++++++++++++++++++++++++++++++++
drivers/s390/crypto/ap_matrix_bus.h | 15 ++++++++++
4 files changed, 77 insertions(+), 2 deletions(-)
create mode 100644 drivers/s390/crypto/ap_matrix_bus.c
create mode 100644 drivers/s390/crypto/ap_matrix_bus.h

diff --git a/MAINTAINERS b/MAINTAINERS
index ef23cf5..cbd6f7c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11711,6 +11711,14 @@ W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported
F: drivers/s390/crypto/

+S390 VFIO AP MATRIX DRIVER
+M: Tony Krowiak <[email protected]>
+L: [email protected]
+W: http://www.ibm.com/developerworks/linux/linux390/
+S: Supported
+F: drivers/s390/crypto/ap_matrix_bus.h
+F: drivers/s390/crypto/ap_matrix_bus.c
+
S390 ZFCP DRIVER
M: Steffen Maier <[email protected]>
M: Benjamin Block <[email protected]>
diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile
index be36f10..87646ca 100644
--- a/drivers/s390/crypto/Makefile
+++ b/drivers/s390/crypto/Makefile
@@ -2,7 +2,7 @@
# S/390 crypto devices
#

-ap-objs := ap_bus.o ap_card.o ap_queue.o
+ap-objs := ap_bus.o ap_card.o ap_queue.o ap_matrix_bus.o
obj-$(subst m,y,$(CONFIG_ZCRYPT)) += ap.o
# zcrypt_api.o and zcrypt_msgtype*.o depend on ap.o
zcrypt-objs := zcrypt_api.o zcrypt_card.o zcrypt_queue.o
@@ -13,4 +13,4 @@ obj-$(CONFIG_ZCRYPT) += zcrypt_pcixcc.o zcrypt_cex2a.o zcrypt_cex4.o

# pkey kernel module
pkey-objs := pkey_api.o
-obj-$(CONFIG_PKEY) += pkey.o
+obj-$(CONFIG_PKEY) += pkey.o
\ No newline at end of file
diff --git a/drivers/s390/crypto/ap_matrix_bus.c b/drivers/s390/crypto/ap_matrix_bus.c
new file mode 100644
index 0000000..fbae175
--- /dev/null
+++ b/drivers/s390/crypto/ap_matrix_bus.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright IBM Corp. 2017
+ * Author(s): Tony Krowiak <[email protected]>
+ *
+ * Adjunct processor matrix bus.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <asm/ap.h>
+
+#include "ap_matrix_bus.h"
+
+MODULE_AUTHOR("Tony Krowiak <[email protected]");
+MODULE_DESCRIPTION("AP Matrix, Copyright IBM Corp. 2017");
+MODULE_LICENSE("GPL v2");
+
+#define AP_MATRIX_BUS_NAME "ap_matrix"
+
+static struct device *ap_matrix_root_device;
+
+static struct bus_type ap_matrix_bus_type = {
+ .name = AP_MATRIX_BUS_NAME,
+};
+
+int __init ap_matrix_init(void)
+{
+ int ret;
+
+ ap_matrix_root_device = root_device_register(AP_MATRIX_BUS_NAME);
+ ret = PTR_RET(ap_matrix_root_device);
+ if (ret)
+ goto done;
+
+ ret = bus_register(&ap_matrix_bus_type);
+ if (ret)
+ goto bus_reg_err;
+
+ return 0;
+
+bus_reg_err:
+ root_device_unregister(ap_matrix_root_device);
+
+done:
+ return ret;
+}
+device_initcall(ap_matrix_init);
diff --git a/drivers/s390/crypto/ap_matrix_bus.h b/drivers/s390/crypto/ap_matrix_bus.h
new file mode 100644
index 0000000..58e116f
--- /dev/null
+++ b/drivers/s390/crypto/ap_matrix_bus.h
@@ -0,0 +1,15 @@
+/*
+ * Adjunct processor matrix bus header file
+ *
+ * Copyright IBM Corp. 2017
+ * Author(s): Tony Krowiak <[email protected]>
+ *
+ * Adjunct processor bus header file.
+ */
+
+#ifndef _AP_MATRIX_BUS_H_
+#define _AP_MATRIX_BUS_H_
+
+int ap_matrix_init(void);
+
+#endif /* _AP_MATRIX_BUS_H_ */
--
1.7.1


From 1584083965225486047@xxx Tue Nov 14 22:56:32 +0000 2017
X-GM-THRID: 1584083965225486047
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-10-13 17:45:40

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 02/19] KVM: s390: refactor crypto initialization

This patch introduces the following changes to crypto initialization.

* For key management operations support, the crypto control block
(CRYCB) referenced by the KVM guest's SIE state description is
formatted only if the Message-Security-Assist (MSA) extension 3
facility is installed (STFLE.76 is set). Virtualization of AP
facilities, however; requires that a CRYCB of the appropriate
format be made available to SIE regardless of the value of STFLE.76.

* The Execution Controls A (ECA) field bit 28 in the SIE block needs
to be set to enable interpretive execution mode of adjunct processor (AP)
instructions.

Signed-off-by: Tony Krowiak <[email protected]>
---
arch/s390/include/asm/kvm_host.h | 1 +
arch/s390/kvm/kvm-s390.c | 17 +++++++++++++----
2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 50a6b25..5683f18 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -188,6 +188,7 @@ struct kvm_s390_sie_block {
#define ECA_MVPGI 0x01000000
#define ECA_VX 0x00020000
#define ECA_PROTEXCI 0x00002000
+#define ECA_AP 0x00000008
#define ECA_SII 0x00000001
__u32 eca; /* 0x004c */
#define ICPT_INST 0x04
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 40d0a1a..e57fc9b 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1819,7 +1819,9 @@ static void kvm_s390_set_crycb_format(struct kvm *kvm)
{
kvm->arch.crypto.crycbd = (__u32)(unsigned long) kvm->arch.crypto.crycb;

- if (kvm_s390_apxa_installed())
+ if (!test_kvm_facility(kvm, 76))
+ kvm->arch.crypto.crycbd &= ~(CRYCB_FORMAT2); /* format 0 */
+ else if (kvm_s390_apxa_installed())
kvm->arch.crypto.crycbd |= CRYCB_FORMAT2;
else
kvm->arch.crypto.crycbd |= CRYCB_FORMAT1;
@@ -1836,12 +1838,12 @@ static u64 kvm_s390_get_initial_cpuid(void)

static void kvm_s390_crypto_init(struct kvm *kvm)
{
- if (!test_kvm_facility(kvm, 76))
- return;
-
kvm->arch.crypto.crycb = &kvm->arch.sie_page2->crycb;
kvm_s390_set_crycb_format(kvm);

+ if (!test_kvm_facility(kvm, 76))
+ return;
+
/* Enable AES/DEA protected key functions by default */
kvm->arch.crypto.aes_kw = 1;
kvm->arch.crypto.dea_kw = 1;
@@ -2366,8 +2368,15 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
vcpu->arch.enabled_gmap = vcpu->arch.gmap;
}

+static void kvm_s390_vcpu_set_crypto_exec_mode(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.sie_block->eca |= ECA_AP;
+}
+
static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
{
+ kvm_s390_vcpu_set_crypto_exec_mode(vcpu);
+
if (!test_kvm_facility(vcpu->kvm, 76))
return;

--
1.7.1


From 1584003374336424590@xxx Tue Nov 14 01:35:35 +0000 2017
X-GM-THRID: 1584003374336424590
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-10-13 17:43:47

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 16/19] KVM: s390: interface to configure KVM guest's AP matrix

Provides an interface to assign AP adapters, usage domains
and control domains to a KVM guest.

A KVM guest is started by executing the Start Interpretive Execution (SIE)
instruction. The SIE state description is a control block that contains the
state information for a KVM guest and is supplied as input to the SIE
instruction. The SIE state description contains a field that references
a Crypto Control Block (CRYCB). The CRYCB contains three bitmask fields
identifying the adapters, usage domains and control domains assigned to the
KVM guest:

* The AP Adapter Matrix (APM) field identifies the AP adapters assigned to
the KVM guest

* The AP Queue Matrix (AQM) field identifies the usage domains assigned to
the KVM guest

* The AP Domain matrix (ADM) field identifies the control domains
assigned to the KVM guest.

Each adapter, usage domain and control domain are identified by a number
from 0 to 255. The bits in each mask, from left to right, correspond to
the numbers 0-255. When a bit is set, the corresponding adapter,
usage domain or control domain will be assigned to the KVM guest.

This patch will set the bits in the APM, AQM and ADM fields of the
CRYCB referenced by the KVM guest's SIE state description. The process
used is:

1. Perform a logical AND of the AP matrix masks configured for the
mediated AP matrix device via its sysfs attributes files with
the matrix masks assigned to the LPAR in which the host linux
system is running to create the effective masks, EAPM, EAQM and
EADM.

2. Set the APM, AQM and ADM in the CRYCB from the EAPM, EAQM and
EADM calculated in step 1.

Signed-off-by: Tony Krowiak <[email protected]>
---
arch/s390/include/asm/ap-config.h | 7 ++
arch/s390/kvm/ap-config.c | 144 +++++++++++++++++++++++++++++++++++++
2 files changed, 151 insertions(+), 0 deletions(-)

diff --git a/arch/s390/include/asm/ap-config.h b/arch/s390/include/asm/ap-config.h
index 3064215..866f008 100644
--- a/arch/s390/include/asm/ap-config.h
+++ b/arch/s390/include/asm/ap-config.h
@@ -10,16 +10,23 @@
#define _ASM_KVM_AP_CONFIG_H_

#include <linux/types.h>
+#include <linux/kvm_host.h>

#define AP_MATRIX_MAX_MASK_BITS 256
#define AP_MATRIX_MASK_INDICES (AP_MATRIX_MAX_MASK_BITS / \
(sizeof(u64) * 8))
#define AP_MATRIX_MAX_MASK_BYTES (AP_MATRIX_MASK_INDICES * sizeof(u64))

+#define AP_MATRIX_MASK_TYPE_ADAPTER "adapter"
+#define AP_MATRIX_MASK_TYPE_DOMAIN "domain"
+#define AP_MATRIX_MASK_TYPE_CONTROL "control domain"
+
struct ap_config_masks {
u64 apm[AP_MATRIX_MASK_INDICES];
u64 aqm[AP_MATRIX_MASK_INDICES];
u64 adm[AP_MATRIX_MASK_INDICES];
};

+extern int ap_config_matrix(struct kvm *kvm, struct ap_config_masks *masks);
+
#endif /* _ASM_KVM_AP_CONFIG_H_ */
diff --git a/arch/s390/kvm/ap-config.c b/arch/s390/kvm/ap-config.c
index 84fdf43..dc79798 100644
--- a/arch/s390/kvm/ap-config.c
+++ b/arch/s390/kvm/ap-config.c
@@ -7,3 +7,147 @@
*/

#include <asm/ap-config.h>
+#include <asm/ap.h>
+#include <linux/bitops.h>
+
+static inline int is_format2_crycb(struct kvm *kvm)
+{
+ int fmt2_mask = kvm->arch.crypto.crycbd & CRYCB_FORMAT2;
+
+ return (fmt2_mask == CRYCB_FORMAT2);
+}
+
+static inline u64 *ap_config_get_crycb_apm(struct kvm *kvm)
+{
+ u64 *apm;
+
+ if (is_format2_crycb(kvm))
+ apm = kvm->arch.crypto.crycb->apcb1.apm;
+ else
+ apm = kvm->arch.crypto.crycb->apcb0.apm;
+
+ return apm;
+}
+
+static inline u64 *ap_config_get_crycb_aqm(struct kvm *kvm)
+{
+ u64 *aqm;
+
+ if (is_format2_crycb(kvm))
+ aqm = kvm->arch.crypto.crycb->apcb1.aqm;
+ else
+ aqm = kvm->arch.crypto.crycb->apcb0.aqm;
+
+ return aqm;
+}
+
+static inline u64 *ap_config_get_crycb_adm(struct kvm *kvm)
+{
+ u64 *adm;
+
+ if (is_format2_crycb(kvm))
+ adm = kvm->arch.crypto.crycb->apcb1.adm;
+ else
+ adm = kvm->arch.crypto.crycb->apcb0.adm;
+
+ return adm;
+}
+
+static void ap_config_set_crycb_masks(struct kvm *kvm,
+ struct ap_config_masks *masks)
+{
+ size_t i;
+ size_t masksz;
+ u64 *mask = ap_config_get_crycb_apm(kvm);
+
+ masksz = (is_format2_crycb(kvm)) ? APCB1_MASK_SIZE : APCB0_MASK_SIZE;
+
+ for (i = 0; i < masksz; i++)
+ mask[i] = masks->apm[i];
+
+ mask = ap_config_get_crycb_aqm(kvm);
+
+ for (i = 0; i < masksz; i++)
+ mask[i] = masks->aqm[i];
+
+ mask = ap_config_get_crycb_adm(kvm);
+
+ for (i = 0; i < masksz; i++)
+ mask[i] = masks->adm[i];
+}
+
+static int ap_config_set_emask(const char *mask_type, unsigned long *mask,
+ unsigned long *cfgmask)
+{
+ unsigned long id;
+ unsigned long nbits = AP_MATRIX_MAX_MASK_BITS;
+
+ id = find_first_bit_inv(mask, nbits);
+ while (id < nbits) {
+ if (!test_bit_inv(id, cfgmask)) {
+ clear_bit_inv(id, mask);
+ pr_err("%s: %s %02lx is not installed on the host system",
+ __func__, mask_type, id);
+ return -ENODEV;
+ }
+
+ id = find_next_bit_inv(mask, nbits, id + 1);
+ }
+
+ return 0;
+}
+
+static int ap_config_get_emasks(struct ap_config_masks *masks)
+{
+ int ret;
+ struct ap_config_info config;
+
+ ret = ap_query_configuration(&config);
+ if (ret) {
+ if (ret == -EOPNOTSUPP) {
+ pr_err("%s: Query AP configuration not supported",
+ __func__);
+
+ return ret;
+ }
+
+ pr_err("%s: Query AP configuration failed with rc=%d",
+ __func__, ret);
+
+ return ret;
+ }
+
+ ret = ap_config_set_emask(AP_MATRIX_MASK_TYPE_ADAPTER,
+ (unsigned long *)masks->apm,
+ (unsigned long *)config.apm);
+ if (ret)
+ return ret;
+
+ ret = ap_config_set_emask(AP_MATRIX_MASK_TYPE_DOMAIN,
+ (unsigned long *)masks->aqm,
+ (unsigned long *)config.aqm);
+ if (ret)
+ return ret;
+
+ ret = ap_config_set_emask(AP_MATRIX_MASK_TYPE_CONTROL,
+ (unsigned long *)masks->adm,
+ (unsigned long *)config.adm);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int ap_config_matrix(struct kvm *kvm, struct ap_config_masks *masks)
+{
+ int ret;
+
+ ret = ap_config_get_emasks(masks);
+ if (ret)
+ return ret;
+
+ ap_config_set_crycb_masks(kvm, masks);
+
+ return 0;
+}
+EXPORT_SYMBOL(ap_config_matrix);
--
1.7.1


From 1585293703614587570@xxx Tue Nov 28 07:24:49 +0000 2017
X-GM-THRID: 1585264315113244510
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-10-13 17:43:13

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 18/19] KVM: s390: New ioctl to configure KVM guest's AP matrix

Implements an ioctl to configure the adapters, usage domains
and control domains to which a KVM guest will be granted
access. The ioctl is invoked using the VFIO mediated matrix
device's file descriptor.

Guest access to AP adapters, usage domains and control domains
is controlled by three bit masks referenced from the
guest's SIE state description: The AP Mask (APM) controls
access to the AP adapters; the AP Queue Mask (AQM) controls
access to the AP usage domains; and the AP Domain Mask (ADM)
controls access to the AP control domains. Each bit
in the APM represents an adapter, from left to right,
starting with adapter 0. Each bit in the AQM represents
a usage domain, from left to right, starting with domain 0.
Each bit in the ADM represents a control domain, from left
to right, starting with domain 0.

The APM, AQM and ADM bit masks will be populated from the
bit masks stored in the corresponding mediated matrix device's
sysfs files. The bit masks will also be returned by the ioctl
call to the caller.

Signed-off-by: Tony Krowiak <[email protected]>
---
drivers/s390/crypto/vfio_ap_matrix_ops.c | 68 +++++++++++++++++++++++++++++-
include/uapi/linux/vfio.h | 20 +++++++++
2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/s390/crypto/vfio_ap_matrix_ops.c b/drivers/s390/crypto/vfio_ap_matrix_ops.c
index 74ea8db..d81e3ab 100644
--- a/drivers/s390/crypto/vfio_ap_matrix_ops.c
+++ b/drivers/s390/crypto/vfio_ap_matrix_ops.c
@@ -160,8 +160,69 @@ static int ap_matrix_mdev_get_device_info(unsigned long arg)
return copy_to_user((void __user *)arg, &info, minsz);
}

-static ssize_t ap_matrix_mdev_ioctl(struct mdev_device *mdev,
- unsigned int cmd, unsigned long arg)
+static int ap_matrix_configure(struct mdev_device *mdev)
+{
+ int ret;
+ struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+
+ ret = ap_config_matrix(matrix_mdev->kvm, &matrix_mdev->masks);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ap_matrix_copy_to_user(struct mdev_device *mdev,
+ struct vfio_ap_matrix_config *mcfg,
+ unsigned long arg)
+{
+ size_t i;
+ struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+
+
+ for (i = 0; i < AP_MATRIX_MASK_INDICES; i++) {
+ if (i < VFIO_AP_MATRIX_MASK_INDICES) {
+ mcfg->apm[i] = matrix_mdev->masks.apm[i];
+ mcfg->aqm[i] = matrix_mdev->masks.aqm[i];
+ mcfg->adm[i] = matrix_mdev->masks.adm[i];
+ }
+ }
+
+ if (copy_to_user((void __user *)arg, &mcfg, sizeof(mcfg)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static ssize_t ap_matrix_mdev_configure(struct mdev_device *mdev,
+ unsigned long arg)
+{
+ int ret;
+ unsigned long minsz;
+ struct vfio_ap_matrix_config mcfg;
+
+ minsz = offsetofend(struct vfio_ap_matrix_config, adm);
+
+ if (copy_from_user(&mcfg, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (mcfg.argsz < minsz) {
+ pr_err("%s: Argument size %u less than min size %li",
+ VFIO_AP_MATRIX_MODULE_NAME, mcfg.argsz, minsz);
+ return -EINVAL;
+ }
+
+ ret = ap_matrix_configure(mdev);
+ if (ret)
+ return ret;
+
+ ret = ap_matrix_copy_to_user(mdev, &mcfg, arg);
+
+ return 0;
+}
+
+static long ap_matrix_mdev_ioctl(struct mdev_device *mdev,
+ unsigned int cmd, unsigned long arg)
{
int ret;

@@ -169,6 +230,9 @@ static ssize_t ap_matrix_mdev_ioctl(struct mdev_device *mdev,
case VFIO_DEVICE_GET_INFO:
ret = ap_matrix_mdev_get_device_info(arg);
break;
+ case VFIO_AP_MATRIX_CONFIGURE:
+ ret = ap_matrix_mdev_configure(mdev, arg);
+ break;
default:
pr_err("%s: ioctl command %d is not a supported command",
VFIO_AP_MATRIX_MODULE_NAME, cmd);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 08f1ab4..2d96c57 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -716,6 +716,26 @@ struct vfio_iommu_spapr_tce_remove {
};
#define VFIO_IOMMU_SPAPR_TCE_REMOVE _IO(VFIO_TYPE, VFIO_BASE + 20)

+/**
+ * VFIO_AP_MATRIX_CONFIGURE _IO(VFIO_TYPE, VFIO_BASE + 21
+ *
+ * Configure the AP matrix for a KVM guest.
+ */
+#define VFIO_AP_MATRIX_CONFIGURE _IO(VFIO_TYPE, VFIO_BASE + 21)
+
+#define VFIO_AP_MATRIX_MASK_INDICES 4
+#define VFIO_AP_MATTRIX_MASK_BYTES (VFIO_AP_MATRIX_MASK_INDICES * \
+ sizeof(__u64))
+#define VFIO_AP_MATRIX_MASK_BITS (VFIO_AP_MATTRIX_MASK_BYTES * 8)
+
+struct vfio_ap_matrix_config {
+ __u32 argsz;
+ __u32 flags;
+ /* out */
+ __u64 apm[VFIO_AP_MATRIX_MASK_INDICES];
+ __u64 aqm[VFIO_AP_MATRIX_MASK_INDICES];
+ __u64 adm[VFIO_AP_MATRIX_MASK_INDICES];
+};
/* ***************************************************************** */

#endif /* _UAPIVFIO_H */
--
1.7.1


From 1583036507186822015@xxx Fri Nov 03 09:27:38 +0000 2017
X-GM-THRID: 1582840593921048574
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-10-13 17:46:22

by Tony Krowiak

[permalink] [raw]
Subject: [RFC 01/19] KVM: s390: SIE considerations for AP Queue virtualization

The Crypto Control Block (CRYCB) is referenced by the SIE state
description and controls KVM guest access to the Adjunct
Processor (AP) adapters, usage domains and control domains.
This patch defines the AP control blocks to be used for
controlling guest access to the AP adapters and domains.

Signed-off-by: Tony Krowiak <[email protected]>
---
arch/s390/include/asm/kvm_host.h | 25 +++++++++++++++++++++----
1 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 51375e7..50a6b25 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -685,11 +685,28 @@ struct kvm_s390_crypto {
__u8 dea_kw;
};

+#define APCB0_MASK_SIZE 1
+struct kvm_s390_apcb0 {
+ __u64 apm[APCB0_MASK_SIZE]; /* 0x0000 */
+ __u64 aqm[APCB0_MASK_SIZE]; /* 0x0008 */
+ __u64 adm[APCB0_MASK_SIZE]; /* 0x0010 */
+ __u64 reserved18; /* 0x0018 */
+};
+
+#define APCB1_MASK_SIZE 4
+struct kvm_s390_apcb1 {
+ __u64 apm[APCB1_MASK_SIZE]; /* 0x0000 */
+ __u64 aqm[APCB1_MASK_SIZE]; /* 0x0020 */
+ __u64 adm[APCB1_MASK_SIZE]; /* 0x0040 */
+ __u64 reserved60[4]; /* 0x0060 */
+};
+
struct kvm_s390_crypto_cb {
- __u8 reserved00[72]; /* 0x0000 */
- __u8 dea_wrapping_key_mask[24]; /* 0x0048 */
- __u8 aes_wrapping_key_mask[32]; /* 0x0060 */
- __u8 reserved80[128]; /* 0x0080 */
+ struct kvm_s390_apcb0 apcb0; /* 0x0000 */
+ __u8 reserved20[40]; /* 0x0020 */
+ __u8 dea_wrapping_key_mask[24]; /* 0x0048 */
+ __u8 aes_wrapping_key_mask[32]; /* 0x0060 */
+ struct kvm_s390_apcb1 apcb1; /* 0x0080 */
};

/*
--
1.7.1


From 1589602856644389540@xxx Sun Jan 14 20:56:57 +0000 2018
X-GM-THRID: 1582987662738669896
X-Gmail-Labels: Inbox,Category Forums,Downloaded_2018-01