More s390x updates:
- introduce support for vfio-ap (s390 crypto devices), including a Linux headers update to get the new interfaces - the usual fixing + cleanup -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEw9DWbcNiT/aowBjO3s9rk8bwL68FAlvAb14SHGNvaHVja0By ZWRoYXQuY29tAAoJEN7Pa5PG8C+vdL4P/3rl6yyQhtiyP4Dw3TWZvWdhXwuPAMIL kzzQt1CQdqcMu+rdvXeResbWUb2nf7uyfRanchmj+D9hw9BlDojo2e7ZWmAsSymr 37ZyPiRrOkxxShNRIlFk2w4lmwvN7n7JLXyBD5Z/ptrVvuNPyn8Wh8PCd+ieY4m9 o89dvZOv+o+3+ToL+9+jnjpfK6sECzs+ULFq//+cnhTBzz2jXrNy8PztB82N6d70 KUKIoab0BTRu2wkX73fcz14I+h/di4H0NFvwSxAo+CtsanP+qOkX5xaEfHyZE6QW cDz8oTRwtk5qckeYzBbp21SjK+OEaxXrtpRAUmpVm7mAMR7ba7z3PhIgZW5G+lk1 Yw+yD0RIGjDyG3PAQ9Qb/WJp8q/h7VluDKdddDrSqtFYbPAJS1w/3JzJJOeTpRfR aDuiFJGVmS/uDFP8GcugCllVqfCsAQJQqL0HKPNo8W5F14DbnX87IoUMz38HVdjb xv0cr1NHGaZnAhJsu8Tq+gGLuenqzDgOQgNCr0DNOitqu51RfXtS0OgzYDEDllwb xcGWQEGMe2B/QIFasdZt0JHTjKWbhnfzZ2afneEwJvRUx+9BTtAbayR3zxpg/LT8 qy1Ipk6OgGy39N61n0BxFtdJzPEF3Se4f3nJm+67LQp1iLjOnkXSsZmVhdXGikb6 SICPj5xVNzSv =Jztt -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20181012' into staging More s390x updates: - introduce support for vfio-ap (s390 crypto devices), including a Linux headers update to get the new interfaces - the usual fixing + cleanup # gpg: Signature made Fri 12 Oct 2018 10:54:38 BST # gpg: using RSA key DECF6B93C6F02FAF # gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>" # gpg: aka "Cornelia Huck <huckc@linux.vnet.ibm.com>" # gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>" # gpg: aka "Cornelia Huck <cohuck@kernel.org>" # gpg: aka "Cornelia Huck <cohuck@redhat.com>" # Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0 18CE DECF 6B93 C6F0 2FAF * remotes/cohuck/tags/s390x-20181012: hw/s390x: Include the tod-qemu also for builds with --disable-tcg s390: doc: detailed specifications for AP virtualization s390x/vfio: ap: Introduce VFIO AP device s390x/ap: base Adjunct Processor (AP) object model s390x/kvm: enable AP instruction interpretation for guest s390x/cpumodel: Set up CPU model for AP device support linux-headers: update target/s390x/excp_helper: Remove DPRINTF() macro Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						69ac8c4cb9
					
				
							
								
								
									
										16
									
								
								MAINTAINERS
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								MAINTAINERS
									
									
									
									
									
								
							@ -88,6 +88,7 @@ F: hw/char/terminal3270.c
 | 
			
		||||
F: hw/intc/s390_flic.c
 | 
			
		||||
F: hw/intc/s390_flic_kvm.c
 | 
			
		||||
F: hw/s390x/
 | 
			
		||||
F: hw/vfio/ap.c
 | 
			
		||||
F: hw/vfio/ccw.c
 | 
			
		||||
F: hw/watchdog/wdt_diag288.c
 | 
			
		||||
F: include/hw/s390x/
 | 
			
		||||
@ -95,6 +96,7 @@ F: include/hw/watchdog/wdt_diag288.h
 | 
			
		||||
F: pc-bios/s390-ccw/
 | 
			
		||||
F: pc-bios/s390-ccw.img
 | 
			
		||||
F: target/s390x/
 | 
			
		||||
F: docs/vfio-ap.txt
 | 
			
		||||
K: ^Subject:.*(?i)s390x?
 | 
			
		||||
T: git git://github.com/cohuck/qemu.git s390-next
 | 
			
		||||
L: qemu-s390x@nongnu.org
 | 
			
		||||
@ -1207,6 +1209,20 @@ F: include/hw/s390x/s390-ccw.h
 | 
			
		||||
T: git git://github.com/cohuck/qemu.git s390-next
 | 
			
		||||
L: qemu-s390x@nongnu.org
 | 
			
		||||
 | 
			
		||||
vfio-ap
 | 
			
		||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
 | 
			
		||||
M: Tony Krowiak <akrowiak@linux.ibm.com>
 | 
			
		||||
M: Halil Pasic <pasic@linux.ibm.com>
 | 
			
		||||
M: Pierre Morel <pmorel@linux.ibm.com>
 | 
			
		||||
S: Supported
 | 
			
		||||
F: hw/s390x/ap-device.c
 | 
			
		||||
F: hw/s390x/ap-bridge.c
 | 
			
		||||
F: include/hw/s390x/ap-device.h
 | 
			
		||||
F: include/hw/s390x/ap-bridge.h
 | 
			
		||||
F: hw/vfio/ap.c
 | 
			
		||||
F: docs/vfio-ap.txt
 | 
			
		||||
L: qemu-s390x@nongnu.org
 | 
			
		||||
 | 
			
		||||
vhost
 | 
			
		||||
M: Michael S. Tsirkin <mst@redhat.com>
 | 
			
		||||
S: Supported
 | 
			
		||||
 | 
			
		||||
@ -7,3 +7,4 @@ CONFIG_S390_FLIC=y
 | 
			
		||||
CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
 | 
			
		||||
CONFIG_VFIO_CCW=$(CONFIG_LINUX)
 | 
			
		||||
CONFIG_WDT_DIAG288=y
 | 
			
		||||
CONFIG_VFIO_AP=$(CONFIG_LINUX)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										825
									
								
								docs/vfio-ap.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										825
									
								
								docs/vfio-ap.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,825 @@
 | 
			
		||||
Adjunct Processor (AP) Device
 | 
			
		||||
=============================
 | 
			
		||||
 | 
			
		||||
Contents:
 | 
			
		||||
=========
 | 
			
		||||
* Introduction
 | 
			
		||||
* AP Architectural Overview
 | 
			
		||||
* Start Interpretive Execution (SIE) Instruction
 | 
			
		||||
* AP Matrix Configuration on Linux Host
 | 
			
		||||
* Starting a Linux Guest Configured with an AP Matrix
 | 
			
		||||
* Example: Configure AP Matrices for Three Linux Guests
 | 
			
		||||
 | 
			
		||||
Introduction:
 | 
			
		||||
============
 | 
			
		||||
The IBM Adjunct Processor (AP) Cryptographic Facility is comprised
 | 
			
		||||
of three AP instructions and from 1 to 256 PCIe cryptographic adapter cards.
 | 
			
		||||
These AP devices provide cryptographic functions to all CPUs assigned to a
 | 
			
		||||
linux system running in an IBM Z system LPAR.
 | 
			
		||||
 | 
			
		||||
On s390x, AP adapter cards are exposed via the AP bus. This document
 | 
			
		||||
describes how those cards may be made available to KVM guests using the
 | 
			
		||||
VFIO mediated device framework.
 | 
			
		||||
 | 
			
		||||
AP Architectural Overview:
 | 
			
		||||
=========================
 | 
			
		||||
In order understand the terminology used in the rest of this document, let's
 | 
			
		||||
start with some definitions:
 | 
			
		||||
 | 
			
		||||
* AP adapter
 | 
			
		||||
 | 
			
		||||
  An AP adapter is an IBM Z adapter card that can perform cryptographic
 | 
			
		||||
  functions. There can be from 0 to 256 adapters assigned to an LPAR depending
 | 
			
		||||
  on the machine model. Adapters assigned to the LPAR in which a linux host is
 | 
			
		||||
  running will be available to the linux host. Each adapter is identified by a
 | 
			
		||||
  number from 0 to 255; however, the maximum adapter number allowed is
 | 
			
		||||
  determined by machine model. When installed, an AP adapter is accessed by
 | 
			
		||||
  AP instructions executed by any CPU.
 | 
			
		||||
 | 
			
		||||
* AP domain
 | 
			
		||||
 | 
			
		||||
  An adapter is partitioned into domains. Each domain can be thought of as
 | 
			
		||||
  a set of hardware registers for processing AP instructions. An adapter can
 | 
			
		||||
  hold up to 256 domains; however, the maximum domain number allowed is
 | 
			
		||||
  determined by machine model. 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; for
 | 
			
		||||
      example, to set a secure private key for the domain.
 | 
			
		||||
 | 
			
		||||
* AP Queue
 | 
			
		||||
 | 
			
		||||
  An AP queue is the means by which an AP command-request message 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 (APID) and an AP queue index (APQI). The
 | 
			
		||||
  APQI corresponds to a given usage domain number 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-request message is to be sent for processing.
 | 
			
		||||
 | 
			
		||||
* 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 administer the queues
 | 
			
		||||
 | 
			
		||||
  AP instructions identify the domain that is targeted to process the AP
 | 
			
		||||
  command; this must be one of the usage domains. An AP command may modify a
 | 
			
		||||
  domain that is not one of the usage domains, but the modified domain
 | 
			
		||||
  must be one of the control domains.
 | 
			
		||||
 | 
			
		||||
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 satellite control block called
 | 
			
		||||
the Crypto Control Block (CRYCB). The CRYCB contains three fields to identify
 | 
			
		||||
the adapters, usage domains and control domains assigned to the KVM guest:
 | 
			
		||||
 | 
			
		||||
* The AP Mask (APM) field is a bit mask that identifies the AP adapters assigned
 | 
			
		||||
  to the KVM guest. Each bit in the mask, from left to right, corresponds to
 | 
			
		||||
  an APID from 0-255. If a bit is set, the corresponding adapter is valid for
 | 
			
		||||
  use by the KVM guest.
 | 
			
		||||
 | 
			
		||||
* The AP Queue Mask (AQM) field is a bit mask identifying the AP usage domains
 | 
			
		||||
  assigned to the KVM guest. Each bit in the mask, from left to right,
 | 
			
		||||
  corresponds to  an AP queue index (APQI) from 0-255. If a bit is set, the
 | 
			
		||||
  corresponding queue is valid for use by the KVM guest.
 | 
			
		||||
 | 
			
		||||
* The AP Domain Mask field is a bit mask that identifies the AP control domains
 | 
			
		||||
  assigned to the KVM guest. The ADM bit mask controls which domains can be
 | 
			
		||||
  changed by an AP command-request message sent to a usage domain from the
 | 
			
		||||
  guest. Each bit in the mask, from left to right, corresponds to a domain from
 | 
			
		||||
  0-255. If a bit is set, the corresponding domain can be modified by an AP
 | 
			
		||||
  command-request message sent to a usage domain.
 | 
			
		||||
 | 
			
		||||
If you recall from the description of an AP Queue, AP instructions include
 | 
			
		||||
an APQN to identify the AP adapter and AP queue 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
 | 
			
		||||
cross product of all assigned adapter numbers (APM) with all assigned queue
 | 
			
		||||
indexes (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 can provide secure key functionality - i.e., a private key is stored
 | 
			
		||||
on the adapter card for each of its domains - so each APQN must be assigned to
 | 
			
		||||
at most one guest or the linux host.
 | 
			
		||||
 | 
			
		||||
   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 APQNs (1,7) and (2,7).
 | 
			
		||||
 | 
			
		||||
   Example 2: Valid configuration:
 | 
			
		||||
   ------------------------------
 | 
			
		||||
   Guest1: adapters 1,2 domains 5,6
 | 
			
		||||
   Guest2: adapters 3,4 domains 5,6
 | 
			
		||||
 | 
			
		||||
   This is also valid because both guests have a unique set of APQNs:
 | 
			
		||||
      Guest1 has APQNs (1,5), (1,6), (2,5), (2,6);
 | 
			
		||||
      Guest2 has APQNs (3,5), (3,6), (4,5), (4,6)
 | 
			
		||||
 | 
			
		||||
   Example 3: 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
 | 
			
		||||
   APQN (1,6).
 | 
			
		||||
 | 
			
		||||
AP Matrix Configuration on Linux Host:
 | 
			
		||||
=====================================
 | 
			
		||||
A linux system is a guest of the LPAR in which it is running and has access to
 | 
			
		||||
the AP resources configured for the LPAR. The LPAR's AP matrix is
 | 
			
		||||
configured via its Activation Profile which can be edited on the HMC. When the
 | 
			
		||||
linux system is started, the AP bus will detect the AP devices assigned to the
 | 
			
		||||
LPAR and create the following in sysfs:
 | 
			
		||||
 | 
			
		||||
/sys/bus/ap
 | 
			
		||||
... [devices]
 | 
			
		||||
...... xx.yyyy
 | 
			
		||||
...... ...
 | 
			
		||||
...... cardxx
 | 
			
		||||
...... ...
 | 
			
		||||
 | 
			
		||||
Where:
 | 
			
		||||
    cardxx     is AP adapter number xx (in hex)
 | 
			
		||||
....xx.yyyy    is an APQN with xx specifying the APID and yyyy specifying the
 | 
			
		||||
               APQI
 | 
			
		||||
 | 
			
		||||
For example, if AP adapters 5 and 6 and domains 4, 71 (0x47), 171 (0xab) and
 | 
			
		||||
255 (0xff) are configured for the LPAR, the sysfs representation on the linux
 | 
			
		||||
host system would look like this:
 | 
			
		||||
 | 
			
		||||
/sys/bus/ap
 | 
			
		||||
... [devices]
 | 
			
		||||
...... 05.0004
 | 
			
		||||
...... 05.0047
 | 
			
		||||
...... 05.00ab
 | 
			
		||||
...... 05.00ff
 | 
			
		||||
...... 06.0004
 | 
			
		||||
...... 06.0047
 | 
			
		||||
...... 06.00ab
 | 
			
		||||
...... 06.00ff
 | 
			
		||||
...... card05
 | 
			
		||||
...... card06
 | 
			
		||||
 | 
			
		||||
A set of default device drivers are also created to control each type of AP
 | 
			
		||||
device that can be assigned to the LPAR on which a linux host is running:
 | 
			
		||||
 | 
			
		||||
/sys/bus/ap
 | 
			
		||||
... [drivers]
 | 
			
		||||
...... [cex2acard]        for Crypto Express 2/3 accelerator cards
 | 
			
		||||
...... [cex2aqueue]       for AP queues served by Crypto Express 2/3
 | 
			
		||||
                          accelerator cards
 | 
			
		||||
...... [cex4card]         for Crypto Express 4/5/6 accelerator and coprocessor
 | 
			
		||||
                          cards
 | 
			
		||||
...... [cex4queue]        for AP queues served by Crypto Express 4/5/6
 | 
			
		||||
                          accelerator and coprocessor cards
 | 
			
		||||
...... [pcixcccard]       for Crypto Express 2/3 coprocessor cards
 | 
			
		||||
...... [pcixccqueue]      for AP queues served by Crypto Express 2/3
 | 
			
		||||
                          coprocessor cards
 | 
			
		||||
 | 
			
		||||
Binding AP devices to device drivers
 | 
			
		||||
------------------------------------
 | 
			
		||||
There are two sysfs files that specify bitmasks marking a subset of the APQN
 | 
			
		||||
range as 'usable by the default AP queue device drivers' or 'not usable by the
 | 
			
		||||
default device drivers' and thus available for use by the alternate device
 | 
			
		||||
driver(s). The sysfs locations of the masks are:
 | 
			
		||||
 | 
			
		||||
   /sys/bus/ap/apmask
 | 
			
		||||
   /sys/bus/ap/aqmask
 | 
			
		||||
 | 
			
		||||
   The 'apmask' is a 256-bit mask that identifies a set of AP adapter IDs
 | 
			
		||||
   (APID). Each bit in the mask, from left to right (i.e., from most significant
 | 
			
		||||
   to least significant bit in big endian order), corresponds to an APID from
 | 
			
		||||
   0-255. If a bit is set, the APID is marked as usable only by the default AP
 | 
			
		||||
   queue device drivers; otherwise, the APID is usable by the vfio_ap
 | 
			
		||||
   device driver.
 | 
			
		||||
 | 
			
		||||
   The 'aqmask' is a 256-bit mask that identifies a set of AP queue indexes
 | 
			
		||||
   (APQI). Each bit in the mask, from left to right (i.e., from most significant
 | 
			
		||||
   to least significant bit in big endian order), corresponds to an APQI from
 | 
			
		||||
   0-255. If a bit is set, the APQI is marked as usable only by the default AP
 | 
			
		||||
   queue device drivers; otherwise, the APQI is usable by the vfio_ap device
 | 
			
		||||
   driver.
 | 
			
		||||
 | 
			
		||||
   Take, for example, the following mask:
 | 
			
		||||
 | 
			
		||||
      0x7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
 | 
			
		||||
 | 
			
		||||
    It indicates:
 | 
			
		||||
 | 
			
		||||
      1, 2, 3, 4, 5, and 7-255 belong to the default drivers' pool, and 0 and 6
 | 
			
		||||
      belong to the vfio_ap device driver's pool.
 | 
			
		||||
 | 
			
		||||
   The APQN of each AP queue device assigned to the linux host is checked by the
 | 
			
		||||
   AP bus against the set of APQNs derived from the cross product of APIDs
 | 
			
		||||
   and APQIs marked as usable only by the default AP queue device drivers. If a
 | 
			
		||||
   match is detected,  only the default AP queue device drivers will be probed;
 | 
			
		||||
   otherwise, the vfio_ap device driver will be probed.
 | 
			
		||||
 | 
			
		||||
   By default, the two masks are set to reserve all APQNs for use by the default
 | 
			
		||||
   AP queue device drivers. There are two ways the default masks can be changed:
 | 
			
		||||
 | 
			
		||||
   1. The sysfs mask files can be edited by echoing a string into the
 | 
			
		||||
      respective sysfs mask file in one of two formats:
 | 
			
		||||
 | 
			
		||||
      * An absolute hex string starting with 0x - like "0x12345678" - sets
 | 
			
		||||
        the mask. If the given string is shorter than the mask, it is padded
 | 
			
		||||
        with 0s on the right; for example, specifying a mask value of 0x41 is
 | 
			
		||||
        the same as specifying:
 | 
			
		||||
 | 
			
		||||
           0x4100000000000000000000000000000000000000000000000000000000000000
 | 
			
		||||
 | 
			
		||||
        Keep in mind that the mask reads from left to right (i.e., most
 | 
			
		||||
        significant to least significant bit in big endian order), so the mask
 | 
			
		||||
        above identifies device numbers 1 and 7 (01000001).
 | 
			
		||||
 | 
			
		||||
        If the string is longer than the mask, the operation is terminated with
 | 
			
		||||
        an error (EINVAL).
 | 
			
		||||
 | 
			
		||||
      * Individual bits in the mask can be switched on and off by specifying
 | 
			
		||||
        each bit number to be switched in a comma separated list. Each bit
 | 
			
		||||
        number string must be prepended with a ('+') or minus ('-') to indicate
 | 
			
		||||
        the corresponding bit is to be switched on ('+') or off ('-'). Some
 | 
			
		||||
        valid values are:
 | 
			
		||||
 | 
			
		||||
           "+0"    switches bit 0 on
 | 
			
		||||
           "-13"   switches bit 13 off
 | 
			
		||||
           "+0x41" switches bit 65 on
 | 
			
		||||
           "-0xff" switches bit 255 off
 | 
			
		||||
 | 
			
		||||
           The following example:
 | 
			
		||||
              +0,-6,+0x47,-0xf0
 | 
			
		||||
 | 
			
		||||
              Switches bits 0 and 71 (0x47) on
 | 
			
		||||
              Switches bits 6 and 240 (0xf0) off
 | 
			
		||||
 | 
			
		||||
        Note that the bits not specified in the list remain as they were before
 | 
			
		||||
        the operation.
 | 
			
		||||
 | 
			
		||||
   2. The masks can also be changed at boot time via parameters on the kernel
 | 
			
		||||
      command line like this:
 | 
			
		||||
 | 
			
		||||
         ap.apmask=0xffff ap.aqmask=0x40
 | 
			
		||||
 | 
			
		||||
         This would create the following masks:
 | 
			
		||||
 | 
			
		||||
            apmask:
 | 
			
		||||
            0xffff000000000000000000000000000000000000000000000000000000000000
 | 
			
		||||
 | 
			
		||||
            aqmask:
 | 
			
		||||
            0x4000000000000000000000000000000000000000000000000000000000000000
 | 
			
		||||
 | 
			
		||||
         Resulting in these two pools:
 | 
			
		||||
 | 
			
		||||
            default drivers pool:    adapter 0-15, domain 1
 | 
			
		||||
            alternate drivers pool:  adapter 16-255, domains 0, 2-255
 | 
			
		||||
 | 
			
		||||
Configuring an AP matrix for a linux guest.
 | 
			
		||||
------------------------------------------
 | 
			
		||||
The sysfs interfaces for configuring an AP matrix for a guest are built on the
 | 
			
		||||
VFIO mediated device framework. To configure an AP matrix for a guest, a
 | 
			
		||||
mediated matrix device must first be created for the /sys/devices/vfio_ap/matrix
 | 
			
		||||
device. When the vfio_ap device driver is loaded, it registers with the VFIO
 | 
			
		||||
mediated device framework. When the driver registers, the sysfs interfaces for
 | 
			
		||||
creating mediated matrix devices is created:
 | 
			
		||||
 | 
			
		||||
/sys/devices
 | 
			
		||||
... [vfio_ap]
 | 
			
		||||
......[matrix]
 | 
			
		||||
......... [mdev_supported_types]
 | 
			
		||||
............ [vfio_ap-passthrough]
 | 
			
		||||
............... create
 | 
			
		||||
............... [devices]
 | 
			
		||||
 | 
			
		||||
A mediated AP matrix device is created by writing a UUID to the attribute file
 | 
			
		||||
named 'create', for example:
 | 
			
		||||
 | 
			
		||||
   uuidgen > create
 | 
			
		||||
 | 
			
		||||
   or
 | 
			
		||||
 | 
			
		||||
   echo $uuid > create
 | 
			
		||||
 | 
			
		||||
When a mediated AP matrix device is created, a sysfs directory named after
 | 
			
		||||
the UUID is created in the 'devices' subdirectory:
 | 
			
		||||
 | 
			
		||||
/sys/devices
 | 
			
		||||
... [vfio_ap]
 | 
			
		||||
......[matrix]
 | 
			
		||||
......... [mdev_supported_types]
 | 
			
		||||
............ [vfio_ap-passthrough]
 | 
			
		||||
............... create
 | 
			
		||||
............... [devices]
 | 
			
		||||
.................. [$uuid]
 | 
			
		||||
 | 
			
		||||
There will also be three sets of attribute files created in the mediated
 | 
			
		||||
matrix device's sysfs directory to configure an AP matrix for the
 | 
			
		||||
KVM guest:
 | 
			
		||||
 | 
			
		||||
/sys/devices
 | 
			
		||||
... [vfio_ap]
 | 
			
		||||
......[matrix]
 | 
			
		||||
......... [mdev_supported_types]
 | 
			
		||||
............ [vfio_ap-passthrough]
 | 
			
		||||
............... create
 | 
			
		||||
............... [devices]
 | 
			
		||||
.................. [$uuid]
 | 
			
		||||
..................... assign_adapter
 | 
			
		||||
..................... assign_control_domain
 | 
			
		||||
..................... assign_domain
 | 
			
		||||
..................... matrix
 | 
			
		||||
..................... unassign_adapter
 | 
			
		||||
..................... unassign_control_domain
 | 
			
		||||
..................... unassign_domain
 | 
			
		||||
 | 
			
		||||
assign_adapter
 | 
			
		||||
   To assign an AP adapter to the mediated matrix device, its APID is written
 | 
			
		||||
   to the 'assign_adapter' file. This may be done multiple times to assign more
 | 
			
		||||
   than one adapter. The APID may be specified using conventional semantics
 | 
			
		||||
   as a decimal, hexadecimal, or octal number. For example, to assign adapters
 | 
			
		||||
   4, 5 and 16 to a mediated matrix device in decimal, hexadecimal and octal
 | 
			
		||||
   respectively:
 | 
			
		||||
 | 
			
		||||
       echo 4 > assign_adapter
 | 
			
		||||
       echo 0x5 > assign_adapter
 | 
			
		||||
       echo 020 > assign_adapter
 | 
			
		||||
 | 
			
		||||
   In order to successfully assign an adapter:
 | 
			
		||||
 | 
			
		||||
   * The adapter number specified must represent a value from 0 up to the
 | 
			
		||||
     maximum adapter number allowed by the machine model. If an adapter number
 | 
			
		||||
     higher than the maximum is specified, the operation will terminate with
 | 
			
		||||
     an error (ENODEV).
 | 
			
		||||
 | 
			
		||||
   * All APQNs that can be derived from the adapter ID being assigned and the
 | 
			
		||||
     IDs of the previously assigned domains must be bound to the vfio_ap device
 | 
			
		||||
     driver. If no domains have yet been assigned, then there must be at least
 | 
			
		||||
     one APQN with the specified APID bound to the vfio_ap driver. If no such
 | 
			
		||||
     APQNs are bound to the driver, the operation will terminate with an
 | 
			
		||||
     error (EADDRNOTAVAIL).
 | 
			
		||||
 | 
			
		||||
     No APQN that can be derived from the adapter ID and the IDs of the
 | 
			
		||||
     previously assigned domains can be assigned to another mediated matrix
 | 
			
		||||
     device. If an APQN is assigned to another mediated matrix device, the
 | 
			
		||||
     operation will terminate with an error (EADDRINUSE).
 | 
			
		||||
 | 
			
		||||
unassign_adapter
 | 
			
		||||
   To unassign an AP adapter, its APID is written to the 'unassign_adapter'
 | 
			
		||||
   file. This may also be done multiple times to unassign more than one adapter.
 | 
			
		||||
 | 
			
		||||
assign_domain
 | 
			
		||||
   To assign a usage domain, the domain number is written into the
 | 
			
		||||
   'assign_domain' file. This may be done multiple times to assign more than one
 | 
			
		||||
   usage domain. The domain number is specified using conventional semantics as
 | 
			
		||||
   a decimal, hexadecimal, or octal number. For example, to assign usage domains
 | 
			
		||||
   4, 8, and 71 to a mediated matrix device in decimal, hexadecimal and octal
 | 
			
		||||
   respectively:
 | 
			
		||||
 | 
			
		||||
      echo 4 > assign_domain
 | 
			
		||||
      echo 0x8 > assign_domain
 | 
			
		||||
      echo 0107 > assign_domain
 | 
			
		||||
 | 
			
		||||
   In order to successfully assign a domain:
 | 
			
		||||
 | 
			
		||||
   * The domain number specified must represent a value from 0 up to the
 | 
			
		||||
     maximum domain number allowed by the machine model. If a domain number
 | 
			
		||||
     higher than the maximum is specified, the operation will terminate with
 | 
			
		||||
     an error (ENODEV).
 | 
			
		||||
 | 
			
		||||
   * All APQNs that can be derived from the domain ID being assigned and the IDs
 | 
			
		||||
     of the previously assigned adapters must be bound to the vfio_ap device
 | 
			
		||||
     driver. If no domains have yet been assigned, then there must be at least
 | 
			
		||||
     one APQN with the specified APQI bound to the vfio_ap driver. If no such
 | 
			
		||||
     APQNs are bound to the driver, the operation will terminate with an
 | 
			
		||||
     error (EADDRNOTAVAIL).
 | 
			
		||||
 | 
			
		||||
     No APQN that can be derived from the domain ID being assigned and the IDs
 | 
			
		||||
     of the previously assigned adapters can be assigned to another mediated
 | 
			
		||||
     matrix device. If an APQN is assigned to another mediated matrix device,
 | 
			
		||||
     the operation will terminate with an error (EADDRINUSE).
 | 
			
		||||
 | 
			
		||||
unassign_domain
 | 
			
		||||
   To unassign a usage domain, the domain number is written into the
 | 
			
		||||
   'unassign_domain' file. This may be done multiple times to unassign more than
 | 
			
		||||
   one usage domain.
 | 
			
		||||
 | 
			
		||||
assign_control_domain
 | 
			
		||||
   To assign a control domain, the domain number is written into the
 | 
			
		||||
   'assign_control_domain' file. This may be done multiple times to
 | 
			
		||||
   assign more than one control domain. The domain number may be specified using
 | 
			
		||||
   conventional semantics as a decimal, hexadecimal, or octal number. For
 | 
			
		||||
   example, to assign  control domains 4, 8, and 71 to  a mediated matrix device
 | 
			
		||||
   in decimal, hexadecimal and octal respectively:
 | 
			
		||||
 | 
			
		||||
      echo 4 > assign_domain
 | 
			
		||||
      echo 0x8 > assign_domain
 | 
			
		||||
      echo 0107 > assign_domain
 | 
			
		||||
 | 
			
		||||
   In order to successfully assign a control domain, the domain number
 | 
			
		||||
   specified must represent a value from 0 up to the maximum domain number
 | 
			
		||||
   allowed by the machine model. If a control domain number higher than the
 | 
			
		||||
   maximum is specified, the operation will terminate with an error (ENODEV).
 | 
			
		||||
 | 
			
		||||
unassign_control_domain
 | 
			
		||||
   To unassign a control domain, the domain number is written into the
 | 
			
		||||
   'unassign_domain' file. This may be done multiple times to unassign more than
 | 
			
		||||
   one control domain.
 | 
			
		||||
 | 
			
		||||
Notes: Hot plug/unplug is not currently supported for mediated AP matrix
 | 
			
		||||
devices, so no changes to the AP matrix will be allowed while a guest using
 | 
			
		||||
the mediated matrix device is running. Attempts to assign an adapter,
 | 
			
		||||
domain or control domain will be rejected and an error (EBUSY) returned.
 | 
			
		||||
 | 
			
		||||
Starting a Linux Guest Configured with an AP Matrix:
 | 
			
		||||
===================================================
 | 
			
		||||
To provide a mediated matrix device for use by a guest, the following option
 | 
			
		||||
must be specified on the QEMU command line:
 | 
			
		||||
 | 
			
		||||
   -device vfio_ap,sysfsdev=$path-to-mdev
 | 
			
		||||
 | 
			
		||||
The sysfsdev parameter specifies the path to the mediated matrix device.
 | 
			
		||||
There are a number of ways to specify this path:
 | 
			
		||||
 | 
			
		||||
/sys/devices/vfio_ap/matrix/$uuid
 | 
			
		||||
/sys/bus/mdev/devices/$uuid
 | 
			
		||||
/sys/bus/mdev/drivers/vfio_mdev/$uuid
 | 
			
		||||
/sys/devices/vfio_ap/matrix/mdev_supported_types/vfio_ap-passthrough/devices/$uuid
 | 
			
		||||
 | 
			
		||||
When the linux guest is started, the guest will open the mediated
 | 
			
		||||
matrix device's file descriptor to get information about the mediated matrix
 | 
			
		||||
device. The vfio_ap device driver will update the APM, AQM, and ADM fields in
 | 
			
		||||
the guest's CRYCB with the adapter, usage domain and control domains assigned
 | 
			
		||||
via the mediated matrix device's sysfs attribute files. Programs running on the
 | 
			
		||||
linux guest will then:
 | 
			
		||||
 | 
			
		||||
1. Have direct access to the APQNs derived from the cross product of the AP
 | 
			
		||||
   adapter numbers (APID) and queue indexes (APQI) specified in the APM and AQM
 | 
			
		||||
   fields of the guests's CRYCB respectively. These APQNs identify the AP queues
 | 
			
		||||
   that are valid for use by the guest; meaning, AP commands can be sent by the
 | 
			
		||||
   guest to any of these queues for processing.
 | 
			
		||||
 | 
			
		||||
2. Have authorization to process AP commands to change a control domain
 | 
			
		||||
   identified in the ADM field of the guest's CRYCB. The AP command must be sent
 | 
			
		||||
   to a valid APQN (see 1 above).
 | 
			
		||||
 | 
			
		||||
CPU model features:
 | 
			
		||||
 | 
			
		||||
Three CPU model features are available for controlling guest access to AP
 | 
			
		||||
facilities:
 | 
			
		||||
 | 
			
		||||
1. AP facilities feature
 | 
			
		||||
 | 
			
		||||
   The AP facilities feature indicates that AP facilities are installed on the
 | 
			
		||||
   guest. This feature will be exposed for use only if the AP facilities
 | 
			
		||||
   are installed on the host system. The feature is s390-specific and is
 | 
			
		||||
   represented as a parameter of the -cpu option on the QEMU command line:
 | 
			
		||||
 | 
			
		||||
      qemu-system-s390x -cpu $model,ap=on|off
 | 
			
		||||
 | 
			
		||||
      Where:
 | 
			
		||||
 | 
			
		||||
         $model is the CPU model defined for the guest (defaults to the model of
 | 
			
		||||
                the host system if not specified).
 | 
			
		||||
 | 
			
		||||
         ap=on|off indicates whether AP facilities are installed (on) or not
 | 
			
		||||
                   (off). The default for CPU models zEC12 or newer
 | 
			
		||||
                   is ap=on. AP facilities must be installed on the guest if a
 | 
			
		||||
                   vfio-ap device (-device vfio-ap,sysfsdev=$path) is configured
 | 
			
		||||
                   for the guest, or the guest will fail to start.
 | 
			
		||||
 | 
			
		||||
2. Query Configuration Information (QCI) facility
 | 
			
		||||
 | 
			
		||||
   The QCI facility is used by the AP bus running on the guest to query the
 | 
			
		||||
   configuration of the AP facilities. This facility will be available
 | 
			
		||||
   only if the QCI facility is installed on the host system. The feature is
 | 
			
		||||
   s390-specific and is represented as a parameter of the -cpu option on the
 | 
			
		||||
   QEMU command line:
 | 
			
		||||
 | 
			
		||||
      qemu-system-s390x -cpu $model,apqci=on|off
 | 
			
		||||
 | 
			
		||||
      Where:
 | 
			
		||||
 | 
			
		||||
         $model is the CPU model defined for the guest
 | 
			
		||||
 | 
			
		||||
         apqci=on|off indicates whether the QCI facility is installed (on) or
 | 
			
		||||
                      not (off). The default for CPU models zEC12 or newer
 | 
			
		||||
                      is apqci=on; for older models, QCI will not be installed.
 | 
			
		||||
 | 
			
		||||
                      If QCI is installed (apqci=on) but AP facilities are not
 | 
			
		||||
                      (ap=off), an error message will be logged, but the guest
 | 
			
		||||
                      will be allowed to start. It makes no sense to have QCI
 | 
			
		||||
                      installed if the AP facilities are not; this is considered
 | 
			
		||||
                      an invalid configuration.
 | 
			
		||||
 | 
			
		||||
                      If the QCI facility is not installed, APQNs with an APQI
 | 
			
		||||
                      greater than 15 will not be detected by the AP bus
 | 
			
		||||
                      running on the guest.
 | 
			
		||||
 | 
			
		||||
3. Adjunct Process Facility Test (APFT) facility
 | 
			
		||||
 | 
			
		||||
   The APFT facility is used by the AP bus running on the guest to test the
 | 
			
		||||
   AP facilities available for a given AP queue. This facility will be available
 | 
			
		||||
   only if the APFT facility is installed on the host system. The feature is
 | 
			
		||||
   s390-specific and is represented as a parameter of the -cpu option on the
 | 
			
		||||
   QEMU command line:
 | 
			
		||||
 | 
			
		||||
      qemu-system-s390x -cpu $model,apft=on|off
 | 
			
		||||
 | 
			
		||||
      Where:
 | 
			
		||||
 | 
			
		||||
         $model is the CPU model defined for the guest (defaults to the model of
 | 
			
		||||
                the host system if not specified).
 | 
			
		||||
 | 
			
		||||
         apft=on|off indicates whether the APFT facility is installed (on) or
 | 
			
		||||
                     not (off). The default for CPU models zEC12 and
 | 
			
		||||
                     newer is apft=on for older models, APFT will not be
 | 
			
		||||
                     installed.
 | 
			
		||||
 | 
			
		||||
                     If APFT is installed (apft=on) but AP facilities are not
 | 
			
		||||
                     (ap=off), an error message will be logged, but the guest
 | 
			
		||||
                     will be allowed to start. It makes no sense to have APFT
 | 
			
		||||
                     installed if the AP facilities are not; this is considered
 | 
			
		||||
                     an invalid configuration.
 | 
			
		||||
 | 
			
		||||
                     It also makes no sense to turn APFT off because the AP bus
 | 
			
		||||
                     running on the guest will not detect CEX4 and newer devices
 | 
			
		||||
                     without it. Since only CEX4 and newer devices are supported
 | 
			
		||||
                     for guest usage, no AP devices can be made accessible to a
 | 
			
		||||
                     guest started without APFT installed.
 | 
			
		||||
 | 
			
		||||
Example: Configure AP Matrixes for Three Linux Guests:
 | 
			
		||||
=====================================================
 | 
			
		||||
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
 | 
			
		||||
three 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 (5,4), (5,171), (6,4), (6,171),
 | 
			
		||||
 | 
			
		||||
Guest3
 | 
			
		||||
------
 | 
			
		||||
CARD.DOMAIN TYPE  MODE
 | 
			
		||||
------------------------------
 | 
			
		||||
06          CEX5A Accelerator
 | 
			
		||||
06.0047     CEX5A Accelerator
 | 
			
		||||
06.00ff     CEX5A Accelerator
 | 
			
		||||
 | 
			
		||||
These are the steps:
 | 
			
		||||
 | 
			
		||||
1. Install the vfio_ap module on the linux host. The dependency chain for the
 | 
			
		||||
   vfio_ap module is:
 | 
			
		||||
   * iommu
 | 
			
		||||
   * s390
 | 
			
		||||
   * zcrypt
 | 
			
		||||
   * vfio
 | 
			
		||||
   * vfio_mdev
 | 
			
		||||
   * vfio_mdev_device
 | 
			
		||||
   * KVM
 | 
			
		||||
 | 
			
		||||
   To build the vfio_ap module, the kernel build must be configured with the
 | 
			
		||||
   following Kconfig elements selected:
 | 
			
		||||
   * IOMMU_SUPPORT
 | 
			
		||||
   * S390
 | 
			
		||||
   * ZCRYPT
 | 
			
		||||
   * S390_AP_IOMMU
 | 
			
		||||
   * VFIO
 | 
			
		||||
   * VFIO_MDEV
 | 
			
		||||
   * VFIO_MDEV_DEVICE
 | 
			
		||||
   * KVM
 | 
			
		||||
 | 
			
		||||
   If using make menuconfig select the following to build the vfio_ap module:
 | 
			
		||||
   -> Device Drivers
 | 
			
		||||
      -> IOMMU Hardware Support
 | 
			
		||||
         select S390 AP IOMMU Support
 | 
			
		||||
      -> VFIO Non-Privileged userspace driver framework
 | 
			
		||||
         -> Mediated device driver frramework
 | 
			
		||||
            -> VFIO driver for Mediated devices
 | 
			
		||||
   -> I/O subsystem
 | 
			
		||||
      -> VFIO support for AP devices
 | 
			
		||||
 | 
			
		||||
2. Secure the AP queues to be used by the three guests so that the host can not
 | 
			
		||||
   access them. To secure the AP queues 05.0004, 05.0047, 05.00ab, 05.00ff,
 | 
			
		||||
   06.0004, 06.0047, 06.00ab, and 06.00ff for use by the vfio_ap device driver,
 | 
			
		||||
   the corresponding APQNs must be removed from the default queue drivers pool
 | 
			
		||||
   as follows:
 | 
			
		||||
 | 
			
		||||
      echo -5,-6 > /sys/bus/ap/apmask
 | 
			
		||||
 | 
			
		||||
      echo -4,-0x47,-0xab,-0xff > /sys/bus/ap/aqmask
 | 
			
		||||
 | 
			
		||||
   This will result in AP queues 05.0004, 05.0047, 05.00ab, 05.00ff, 06.0004,
 | 
			
		||||
   06.0047, 06.00ab, and 06.00ff getting bound to the vfio_ap device driver. The
 | 
			
		||||
   sysfs directory for the vfio_ap device driver will now contain symbolic links
 | 
			
		||||
   to the AP queue devices bound to it:
 | 
			
		||||
 | 
			
		||||
   /sys/bus/ap
 | 
			
		||||
   ... [drivers]
 | 
			
		||||
   ...... [vfio_ap]
 | 
			
		||||
   ......... [05.0004]
 | 
			
		||||
   ......... [05.0047]
 | 
			
		||||
   ......... [05.00ab]
 | 
			
		||||
   ......... [05.00ff]
 | 
			
		||||
   ......... [06.0004]
 | 
			
		||||
   ......... [06.0047]
 | 
			
		||||
   ......... [06.00ab]
 | 
			
		||||
   ......... [06.00ff]
 | 
			
		||||
 | 
			
		||||
   Keep in mind that only type 10 and newer adapters (i.e., CEX4 and later)
 | 
			
		||||
   can be bound to the vfio_ap device driver. The reason for this is to
 | 
			
		||||
   simplify the implementation by not needlessly complicating the design by
 | 
			
		||||
   supporting older devices that will go out of service in the relatively near
 | 
			
		||||
   future, and for which there are few older systems on which to test.
 | 
			
		||||
 | 
			
		||||
   The administrator, therefore, must take care to secure only AP queues that
 | 
			
		||||
   can be bound to the vfio_ap device driver. The device type for a given AP
 | 
			
		||||
   queue device can be read from the parent card's sysfs directory. For example,
 | 
			
		||||
   to see the hardware type of the queue 05.0004:
 | 
			
		||||
 | 
			
		||||
   cat /sys/bus/ap/devices/card05/hwtype
 | 
			
		||||
 | 
			
		||||
   The hwtype must be 10 or higher (CEX4 or newer) in order to be bound to the
 | 
			
		||||
   vfio_ap device driver.
 | 
			
		||||
 | 
			
		||||
3. Create the mediated devices needed to configure the AP matrixes for the
 | 
			
		||||
   three guests and to provide an interface to the vfio_ap driver for
 | 
			
		||||
   use by the guests:
 | 
			
		||||
 | 
			
		||||
   /sys/devices/vfio_ap/matrix/
 | 
			
		||||
   --- [mdev_supported_types]
 | 
			
		||||
   ------ [vfio_ap-passthrough] (passthrough mediated matrix device type)
 | 
			
		||||
   --------- create
 | 
			
		||||
   --------- [devices]
 | 
			
		||||
 | 
			
		||||
   To create the mediated devices for the three guests:
 | 
			
		||||
 | 
			
		||||
       uuidgen > create
 | 
			
		||||
       uuidgen > create
 | 
			
		||||
       uuidgen > create
 | 
			
		||||
 | 
			
		||||
        or
 | 
			
		||||
 | 
			
		||||
        echo $uuid1 > create
 | 
			
		||||
        echo $uuid2 > create
 | 
			
		||||
        echo $uuid3 > create
 | 
			
		||||
 | 
			
		||||
   This will create three mediated devices in the [devices] subdirectory named
 | 
			
		||||
   after the UUID used to create the mediated device. We'll call them $uuid1,
 | 
			
		||||
   $uuid2 and $uuid3 and this is the sysfs directory structure after creation:
 | 
			
		||||
 | 
			
		||||
   /sys/devices/vfio_ap/matrix/
 | 
			
		||||
   --- [mdev_supported_types]
 | 
			
		||||
   ------ [vfio_ap-passthrough]
 | 
			
		||||
   --------- [devices]
 | 
			
		||||
   ------------ [$uuid1]
 | 
			
		||||
   --------------- assign_adapter
 | 
			
		||||
   --------------- assign_control_domain
 | 
			
		||||
   --------------- assign_domain
 | 
			
		||||
   --------------- matrix
 | 
			
		||||
   --------------- unassign_adapter
 | 
			
		||||
   --------------- unassign_control_domain
 | 
			
		||||
   --------------- unassign_domain
 | 
			
		||||
 | 
			
		||||
   ------------ [$uuid2]
 | 
			
		||||
   --------------- assign_adapter
 | 
			
		||||
   --------------- assign_control_domain
 | 
			
		||||
   --------------- assign_domain
 | 
			
		||||
   --------------- matrix
 | 
			
		||||
   --------------- unassign_adapter
 | 
			
		||||
   ----------------unassign_control_domain
 | 
			
		||||
   ----------------unassign_domain
 | 
			
		||||
 | 
			
		||||
   ------------ [$uuid3]
 | 
			
		||||
   --------------- assign_adapter
 | 
			
		||||
   --------------- assign_control_domain
 | 
			
		||||
   --------------- assign_domain
 | 
			
		||||
   --------------- matrix
 | 
			
		||||
   --------------- unassign_adapter
 | 
			
		||||
   ----------------unassign_control_domain
 | 
			
		||||
   ----------------unassign_domain
 | 
			
		||||
 | 
			
		||||
4. The administrator now needs to configure the matrixes for the mediated
 | 
			
		||||
   devices $uuid1 (for Guest1), $uuid2 (for Guest2) and $uuid3 (for Guest3).
 | 
			
		||||
 | 
			
		||||
   This is how the matrix is configured for Guest1:
 | 
			
		||||
 | 
			
		||||
      echo 5 > assign_adapter
 | 
			
		||||
      echo 6 > assign_adapter
 | 
			
		||||
      echo 4 > assign_domain
 | 
			
		||||
      echo 0xab > assign_domain
 | 
			
		||||
 | 
			
		||||
      Control domains can similarly be assigned using the assign_control_domain
 | 
			
		||||
      sysfs file.
 | 
			
		||||
 | 
			
		||||
      If a mistake is made configuring an adapter, domain or control domain,
 | 
			
		||||
      you can use the unassign_xxx interfaces to unassign the adapter, domain or
 | 
			
		||||
      control domain.
 | 
			
		||||
 | 
			
		||||
      To display the matrix configuration for Guest1:
 | 
			
		||||
 | 
			
		||||
         cat matrix
 | 
			
		||||
 | 
			
		||||
         The output will display the APQNs in the format xx.yyyy, where xx is
 | 
			
		||||
         the adapter number and yyyy is the domain number. The output for Guest1
 | 
			
		||||
         will look like this:
 | 
			
		||||
 | 
			
		||||
         05.0004
 | 
			
		||||
         05.00ab
 | 
			
		||||
         06.0004
 | 
			
		||||
         06.00ab
 | 
			
		||||
 | 
			
		||||
   This is how the matrix is configured for Guest2:
 | 
			
		||||
 | 
			
		||||
      echo 5 > assign_adapter
 | 
			
		||||
      echo 0x47 > assign_domain
 | 
			
		||||
      echo 0xff > assign_domain
 | 
			
		||||
 | 
			
		||||
   This is how the matrix is configured for Guest3:
 | 
			
		||||
 | 
			
		||||
      echo 6 > assign_adapter
 | 
			
		||||
      echo 0x47 > assign_domain
 | 
			
		||||
      echo 0xff > assign_domain
 | 
			
		||||
 | 
			
		||||
5. Start Guest1:
 | 
			
		||||
 | 
			
		||||
   /usr/bin/qemu-system-s390x ... -cpu host,ap=on,apqci=on,apft=on \
 | 
			
		||||
      -device vfio-ap,sysfsdev=/sys/devices/vfio_ap/matrix/$uuid1 ...
 | 
			
		||||
 | 
			
		||||
7. Start Guest2:
 | 
			
		||||
 | 
			
		||||
   /usr/bin/qemu-system-s390x ... -cpu host,ap=on,apqci=on,apft=on \
 | 
			
		||||
      -device vfio-ap,sysfsdev=/sys/devices/vfio_ap/matrix/$uuid2 ...
 | 
			
		||||
 | 
			
		||||
7. Start Guest3:
 | 
			
		||||
 | 
			
		||||
   /usr/bin/qemu-system-s390x ... -cpu host,ap=on,apqci=on,apft=on \
 | 
			
		||||
      -device vfio-ap,sysfsdev=/sys/devices/vfio_ap/matrix/$uuid3 ...
 | 
			
		||||
 | 
			
		||||
When the guest is shut down, the mediated matrix devices may be removed.
 | 
			
		||||
 | 
			
		||||
Using our example again, to remove the mediated matrix device $uuid1:
 | 
			
		||||
 | 
			
		||||
   /sys/devices/vfio_ap/matrix/
 | 
			
		||||
      --- [mdev_supported_types]
 | 
			
		||||
      ------ [vfio_ap-passthrough]
 | 
			
		||||
      --------- [devices]
 | 
			
		||||
      ------------ [$uuid1]
 | 
			
		||||
      --------------- remove
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   echo 1 > remove
 | 
			
		||||
 | 
			
		||||
   This will remove all of the mdev matrix device's sysfs structures including
 | 
			
		||||
   the mdev device itself. To recreate and reconfigure the mdev matrix device,
 | 
			
		||||
   all of the steps starting with step 3 will have to be performed again. Note
 | 
			
		||||
   that the remove will fail if a guest using the mdev is still running.
 | 
			
		||||
 | 
			
		||||
   It is not necessary to remove an mdev matrix device, but one may want to
 | 
			
		||||
   remove it if no guest will use it during the remaining lifetime of the linux
 | 
			
		||||
   host. If the mdev matrix device is removed, one may want to also reconfigure
 | 
			
		||||
   the pool of adapters and queues reserved for use by the default drivers.
 | 
			
		||||
 | 
			
		||||
Limitations
 | 
			
		||||
===========
 | 
			
		||||
* The KVM/kernel interfaces do not provide a way to prevent restoring an APQN
 | 
			
		||||
  to the default drivers pool of a queue that is still assigned to a mediated
 | 
			
		||||
  device in use by a guest. It is incumbent upon the administrator to
 | 
			
		||||
  ensure there is no mediated device in use by a guest to which the APQN is
 | 
			
		||||
  assigned lest the host be given access to the private data of the AP queue
 | 
			
		||||
  device, such as a private key configured specifically for the guest.
 | 
			
		||||
 | 
			
		||||
* Dynamically modifying the AP matrix for a running guest (which would amount to
 | 
			
		||||
  hot(un)plug of AP devices for the guest) is currently not supported
 | 
			
		||||
 | 
			
		||||
* Live guest migration is not supported for guests using AP devices.
 | 
			
		||||
@ -26,8 +26,10 @@ obj-$(call lnot,$(CONFIG_PCI)) += s390-pci-stub.o
 | 
			
		||||
obj-y += s390-skeys.o
 | 
			
		||||
obj-y += s390-stattrib.o
 | 
			
		||||
obj-y += tod.o
 | 
			
		||||
obj-y += tod-qemu.o
 | 
			
		||||
obj-$(CONFIG_KVM) += tod-kvm.o
 | 
			
		||||
obj-$(CONFIG_TCG) += tod-qemu.o
 | 
			
		||||
obj-$(CONFIG_KVM) += s390-skeys-kvm.o
 | 
			
		||||
obj-$(CONFIG_KVM) += s390-stattrib-kvm.o
 | 
			
		||||
obj-y += s390-ccw.o
 | 
			
		||||
obj-y += ap-device.o
 | 
			
		||||
obj-y += ap-bridge.o
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										78
									
								
								hw/s390x/ap-bridge.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								hw/s390x/ap-bridge.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ap bridge
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2018 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 | 
			
		||||
 * your option) any later version. See the COPYING file in the top-level
 | 
			
		||||
 * directory.
 | 
			
		||||
 */
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include "qapi/error.h"
 | 
			
		||||
#include "hw/sysbus.h"
 | 
			
		||||
#include "qemu/bitops.h"
 | 
			
		||||
#include "hw/s390x/ap-bridge.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
 | 
			
		||||
static char *ap_bus_get_dev_path(DeviceState *dev)
 | 
			
		||||
{
 | 
			
		||||
    /* at most one */
 | 
			
		||||
    return g_strdup_printf("/1");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ap_bus_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
{
 | 
			
		||||
    BusClass *k = BUS_CLASS(oc);
 | 
			
		||||
 | 
			
		||||
    k->get_dev_path = ap_bus_get_dev_path;
 | 
			
		||||
    /* More than one ap device does not make sense */
 | 
			
		||||
    k->max_dev = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo ap_bus_info = {
 | 
			
		||||
    .name = TYPE_AP_BUS,
 | 
			
		||||
    .parent = TYPE_BUS,
 | 
			
		||||
    .instance_size = 0,
 | 
			
		||||
    .class_init = ap_bus_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void s390_init_ap(void)
 | 
			
		||||
{
 | 
			
		||||
    DeviceState *dev;
 | 
			
		||||
 | 
			
		||||
    /* If no AP instructions then no need for AP bridge */
 | 
			
		||||
    if (!s390_has_feat(S390_FEAT_AP)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Create bridge device */
 | 
			
		||||
    dev = qdev_create(NULL, TYPE_AP_BRIDGE);
 | 
			
		||||
    object_property_add_child(qdev_get_machine(), TYPE_AP_BRIDGE,
 | 
			
		||||
                              OBJECT(dev), NULL);
 | 
			
		||||
    qdev_init_nofail(dev);
 | 
			
		||||
 | 
			
		||||
    /* Create bus on bridge device */
 | 
			
		||||
    qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS);
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
static void ap_bridge_class_init(ObjectClass *oc, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(oc);
 | 
			
		||||
 | 
			
		||||
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo ap_bridge_info = {
 | 
			
		||||
    .name          = TYPE_AP_BRIDGE,
 | 
			
		||||
    .parent        = TYPE_SYS_BUS_DEVICE,
 | 
			
		||||
    .instance_size = 0,
 | 
			
		||||
    .class_init    = ap_bridge_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void ap_register(void)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&ap_bridge_info);
 | 
			
		||||
    type_register_static(&ap_bus_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type_init(ap_register)
 | 
			
		||||
							
								
								
									
										38
									
								
								hw/s390x/ap-device.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								hw/s390x/ap-device.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Adjunct Processor (AP) matrix device
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2018 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 | 
			
		||||
 * your option) any later version. See the COPYING file in the top-level
 | 
			
		||||
 * directory.
 | 
			
		||||
 */
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include "qemu/module.h"
 | 
			
		||||
#include "qapi/error.h"
 | 
			
		||||
#include "hw/qdev.h"
 | 
			
		||||
#include "hw/s390x/ap-device.h"
 | 
			
		||||
 | 
			
		||||
static void ap_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    dc->desc = "AP device class";
 | 
			
		||||
    dc->hotpluggable = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo ap_device_info = {
 | 
			
		||||
    .name = AP_DEVICE_TYPE,
 | 
			
		||||
    .parent = TYPE_DEVICE,
 | 
			
		||||
    .instance_size = sizeof(APDevice),
 | 
			
		||||
    .class_size = sizeof(DeviceClass),
 | 
			
		||||
    .class_init = ap_class_init,
 | 
			
		||||
    .abstract = true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void ap_device_register(void)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&ap_device_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type_init(ap_device_register)
 | 
			
		||||
@ -32,6 +32,7 @@
 | 
			
		||||
#include "ipl.h"
 | 
			
		||||
#include "hw/s390x/s390-virtio-ccw.h"
 | 
			
		||||
#include "hw/s390x/css-bridge.h"
 | 
			
		||||
#include "hw/s390x/ap-bridge.h"
 | 
			
		||||
#include "migration/register.h"
 | 
			
		||||
#include "cpu_models.h"
 | 
			
		||||
#include "hw/nmi.h"
 | 
			
		||||
@ -263,6 +264,9 @@ static void ccw_init(MachineState *machine)
 | 
			
		||||
    /* init the SIGP facility */
 | 
			
		||||
    s390_init_sigp();
 | 
			
		||||
 | 
			
		||||
    /* create AP bridge and bus(es) */
 | 
			
		||||
    s390_init_ap();
 | 
			
		||||
 | 
			
		||||
    /* get a BUS */
 | 
			
		||||
    css_bus = virtual_css_bus_init();
 | 
			
		||||
    s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline,
 | 
			
		||||
 | 
			
		||||
@ -6,4 +6,5 @@ obj-$(CONFIG_SOFTMMU) += platform.o
 | 
			
		||||
obj-$(CONFIG_VFIO_XGMAC) += calxeda-xgmac.o
 | 
			
		||||
obj-$(CONFIG_VFIO_AMD_XGBE) += amd-xgbe.o
 | 
			
		||||
obj-$(CONFIG_SOFTMMU) += spapr.o
 | 
			
		||||
obj-$(CONFIG_VFIO_AP) += ap.o
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										181
									
								
								hw/vfio/ap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								hw/vfio/ap.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,181 @@
 | 
			
		||||
/*
 | 
			
		||||
 * VFIO based AP matrix device assignment
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2018 IBM Corp.
 | 
			
		||||
 * Author(s): Tony Krowiak <akrowiak@linux.ibm.com>
 | 
			
		||||
 *            Halil Pasic <pasic@linux.ibm.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 | 
			
		||||
 * your option) any later version. See the COPYING file in the top-level
 | 
			
		||||
 * directory.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/vfio.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include "qemu/osdep.h"
 | 
			
		||||
#include "qapi/error.h"
 | 
			
		||||
#include "hw/sysbus.h"
 | 
			
		||||
#include "hw/vfio/vfio.h"
 | 
			
		||||
#include "hw/vfio/vfio-common.h"
 | 
			
		||||
#include "hw/s390x/ap-device.h"
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
#include "qemu/queue.h"
 | 
			
		||||
#include "qemu/option.h"
 | 
			
		||||
#include "qemu/config-file.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "kvm_s390x.h"
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "hw/s390x/ap-bridge.h"
 | 
			
		||||
#include "exec/address-spaces.h"
 | 
			
		||||
 | 
			
		||||
#define VFIO_AP_DEVICE_TYPE      "vfio-ap"
 | 
			
		||||
 | 
			
		||||
typedef struct VFIOAPDevice {
 | 
			
		||||
    APDevice apdev;
 | 
			
		||||
    VFIODevice vdev;
 | 
			
		||||
} VFIOAPDevice;
 | 
			
		||||
 | 
			
		||||
#define VFIO_AP_DEVICE(obj) \
 | 
			
		||||
        OBJECT_CHECK(VFIOAPDevice, (obj), VFIO_AP_DEVICE_TYPE)
 | 
			
		||||
 | 
			
		||||
static void vfio_ap_compute_needs_reset(VFIODevice *vdev)
 | 
			
		||||
{
 | 
			
		||||
    vdev->needs_reset = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * We don't need vfio_hot_reset_multi and vfio_eoi operations for
 | 
			
		||||
 * vfio-ap device now.
 | 
			
		||||
 */
 | 
			
		||||
struct VFIODeviceOps vfio_ap_ops = {
 | 
			
		||||
    .vfio_compute_needs_reset = vfio_ap_compute_needs_reset,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void vfio_ap_put_device(VFIOAPDevice *vapdev)
 | 
			
		||||
{
 | 
			
		||||
    g_free(vapdev->vdev.name);
 | 
			
		||||
    vfio_put_base_device(&vapdev->vdev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VFIOGroup *vfio_ap_get_group(VFIOAPDevice *vapdev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    GError *gerror = NULL;
 | 
			
		||||
    char *symlink, *group_path;
 | 
			
		||||
    int groupid;
 | 
			
		||||
 | 
			
		||||
    symlink = g_strdup_printf("%s/iommu_group", vapdev->vdev.sysfsdev);
 | 
			
		||||
    group_path = g_file_read_link(symlink, &gerror);
 | 
			
		||||
    g_free(symlink);
 | 
			
		||||
 | 
			
		||||
    if (!group_path) {
 | 
			
		||||
        error_setg(errp, "%s: no iommu_group found for %s: %s",
 | 
			
		||||
                   VFIO_AP_DEVICE_TYPE, vapdev->vdev.sysfsdev, gerror->message);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sscanf(basename(group_path), "%d", &groupid) != 1) {
 | 
			
		||||
        error_setg(errp, "vfio: failed to read %s", group_path);
 | 
			
		||||
        g_free(group_path);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_free(group_path);
 | 
			
		||||
 | 
			
		||||
    return vfio_get_group(groupid, &address_space_memory, errp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vfio_ap_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    char *mdevid;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
    VFIOGroup *vfio_group;
 | 
			
		||||
    APDevice *apdev = AP_DEVICE(dev);
 | 
			
		||||
    VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
 | 
			
		||||
 | 
			
		||||
    vfio_group = vfio_ap_get_group(vapdev, &local_err);
 | 
			
		||||
    if (!vfio_group) {
 | 
			
		||||
        goto out_err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vapdev->vdev.ops = &vfio_ap_ops;
 | 
			
		||||
    vapdev->vdev.type = VFIO_DEVICE_TYPE_AP;
 | 
			
		||||
    mdevid = basename(vapdev->vdev.sysfsdev);
 | 
			
		||||
    vapdev->vdev.name = g_strdup_printf("%s", mdevid);
 | 
			
		||||
    vapdev->vdev.dev = dev;
 | 
			
		||||
 | 
			
		||||
    ret = vfio_get_device(vfio_group, mdevid, &vapdev->vdev, &local_err);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        goto out_get_dev_err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
out_get_dev_err:
 | 
			
		||||
    vfio_ap_put_device(vapdev);
 | 
			
		||||
    vfio_put_group(vfio_group);
 | 
			
		||||
out_err:
 | 
			
		||||
    error_propagate(errp, local_err);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vfio_ap_unrealize(DeviceState *dev, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    APDevice *apdev = AP_DEVICE(dev);
 | 
			
		||||
    VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
 | 
			
		||||
    VFIOGroup *group = vapdev->vdev.group;
 | 
			
		||||
 | 
			
		||||
    vfio_ap_put_device(vapdev);
 | 
			
		||||
    vfio_put_group(group);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property vfio_ap_properties[] = {
 | 
			
		||||
    DEFINE_PROP_STRING("sysfsdev", VFIOAPDevice, vdev.sysfsdev),
 | 
			
		||||
    DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void vfio_ap_reset(DeviceState *dev)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    APDevice *apdev = AP_DEVICE(dev);
 | 
			
		||||
    VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
 | 
			
		||||
 | 
			
		||||
    ret = ioctl(vapdev->vdev.fd, VFIO_DEVICE_RESET);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        error_report("%s: failed to reset %s device: %s", __func__,
 | 
			
		||||
                     vapdev->vdev.name, strerror(ret));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vfio_ap_vmstate = {
 | 
			
		||||
    .name = VFIO_AP_DEVICE_TYPE,
 | 
			
		||||
    .unmigratable = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void vfio_ap_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    dc->props = vfio_ap_properties;
 | 
			
		||||
    dc->vmsd = &vfio_ap_vmstate;
 | 
			
		||||
    dc->desc = "VFIO-based AP device assignment";
 | 
			
		||||
    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 | 
			
		||||
    dc->realize = vfio_ap_realize;
 | 
			
		||||
    dc->unrealize = vfio_ap_unrealize;
 | 
			
		||||
    dc->hotpluggable = false;
 | 
			
		||||
    dc->reset = vfio_ap_reset;
 | 
			
		||||
    dc->bus_type = TYPE_AP_BUS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo vfio_ap_info = {
 | 
			
		||||
    .name = VFIO_AP_DEVICE_TYPE,
 | 
			
		||||
    .parent = AP_DEVICE_TYPE,
 | 
			
		||||
    .instance_size = sizeof(VFIOAPDevice),
 | 
			
		||||
    .class_init = vfio_ap_class_init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void vfio_ap_type_init(void)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&vfio_ap_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type_init(vfio_ap_type_init)
 | 
			
		||||
							
								
								
									
										19
									
								
								include/hw/s390x/ap-bridge.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								include/hw/s390x/ap-bridge.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ap bridge
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2018 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 | 
			
		||||
 * your option) any later version. See the COPYING file in the top-level
 | 
			
		||||
 * directory.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef HW_S390X_AP_BRIDGE_H
 | 
			
		||||
#define HW_S390X_AP_BRIDGE_H
 | 
			
		||||
 | 
			
		||||
#define TYPE_AP_BRIDGE "ap-bridge"
 | 
			
		||||
#define TYPE_AP_BUS "ap-bus"
 | 
			
		||||
 | 
			
		||||
void s390_init_ap(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										22
									
								
								include/hw/s390x/ap-device.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								include/hw/s390x/ap-device.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Adjunct Processor (AP) matrix device interfaces
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2018 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 | 
			
		||||
 * your option) any later version. See the COPYING file in the top-level
 | 
			
		||||
 * directory.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef HW_S390X_AP_DEVICE_H
 | 
			
		||||
#define HW_S390X_AP_DEVICE_H
 | 
			
		||||
 | 
			
		||||
#define AP_DEVICE_TYPE       "ap-device"
 | 
			
		||||
 | 
			
		||||
typedef struct APDevice {
 | 
			
		||||
    DeviceState parent_obj;
 | 
			
		||||
} APDevice;
 | 
			
		||||
 | 
			
		||||
#define AP_DEVICE(obj) \
 | 
			
		||||
    OBJECT_CHECK(APDevice, (obj), AP_DEVICE_TYPE)
 | 
			
		||||
 | 
			
		||||
#endif /* HW_S390X_AP_DEVICE_H */
 | 
			
		||||
@ -37,6 +37,7 @@ enum {
 | 
			
		||||
    VFIO_DEVICE_TYPE_PCI = 0,
 | 
			
		||||
    VFIO_DEVICE_TYPE_PLATFORM = 1,
 | 
			
		||||
    VFIO_DEVICE_TYPE_CCW = 2,
 | 
			
		||||
    VFIO_DEVICE_TYPE_AP = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct VFIOMmap {
 | 
			
		||||
 | 
			
		||||
@ -267,10 +267,11 @@ struct input_mask {
 | 
			
		||||
/*
 | 
			
		||||
 * MT_TOOL types
 | 
			
		||||
 */
 | 
			
		||||
#define MT_TOOL_FINGER		0
 | 
			
		||||
#define MT_TOOL_PEN		1
 | 
			
		||||
#define MT_TOOL_PALM		2
 | 
			
		||||
#define MT_TOOL_MAX		2
 | 
			
		||||
#define MT_TOOL_FINGER		0x00
 | 
			
		||||
#define MT_TOOL_PEN		0x01
 | 
			
		||||
#define MT_TOOL_PALM		0x02
 | 
			
		||||
#define MT_TOOL_DIAL		0x0a
 | 
			
		||||
#define MT_TOOL_MAX		0x0f
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Values describing the status of a force-feedback effect
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@
 | 
			
		||||
#define __KVM_HAVE_GUEST_DEBUG
 | 
			
		||||
#define __KVM_HAVE_IRQ_LINE
 | 
			
		||||
#define __KVM_HAVE_READONLY_MEM
 | 
			
		||||
#define __KVM_HAVE_VCPU_EVENTS
 | 
			
		||||
 | 
			
		||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 | 
			
		||||
 | 
			
		||||
@ -125,6 +126,18 @@ struct kvm_sync_regs {
 | 
			
		||||
struct kvm_arch_memory_slot {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET/SET_VCPU_EVENTS */
 | 
			
		||||
struct kvm_vcpu_events {
 | 
			
		||||
	struct {
 | 
			
		||||
		__u8 serror_pending;
 | 
			
		||||
		__u8 serror_has_esr;
 | 
			
		||||
		/* Align it to 8 bytes */
 | 
			
		||||
		__u8 pad[6];
 | 
			
		||||
		__u64 serror_esr;
 | 
			
		||||
	} exception;
 | 
			
		||||
	__u32 reserved[12];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* If you need to interpret the index values, here is the key: */
 | 
			
		||||
#define KVM_REG_ARM_COPROC_MASK		0x000000000FFF0000
 | 
			
		||||
#define KVM_REG_ARM_COPROC_SHIFT	16
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@
 | 
			
		||||
#define __KVM_HAVE_GUEST_DEBUG
 | 
			
		||||
#define __KVM_HAVE_IRQ_LINE
 | 
			
		||||
#define __KVM_HAVE_READONLY_MEM
 | 
			
		||||
#define __KVM_HAVE_VCPU_EVENTS
 | 
			
		||||
 | 
			
		||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 | 
			
		||||
 | 
			
		||||
@ -154,6 +155,18 @@ struct kvm_sync_regs {
 | 
			
		||||
struct kvm_arch_memory_slot {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET/SET_VCPU_EVENTS */
 | 
			
		||||
struct kvm_vcpu_events {
 | 
			
		||||
	struct {
 | 
			
		||||
		__u8 serror_pending;
 | 
			
		||||
		__u8 serror_has_esr;
 | 
			
		||||
		/* Align it to 8 bytes */
 | 
			
		||||
		__u8 pad[6];
 | 
			
		||||
		__u64 serror_esr;
 | 
			
		||||
	} exception;
 | 
			
		||||
	__u32 reserved[12];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* If you need to interpret the index values, here is the key: */
 | 
			
		||||
#define KVM_REG_ARM_COPROC_MASK		0x000000000FFF0000
 | 
			
		||||
#define KVM_REG_ARM_COPROC_SHIFT	16
 | 
			
		||||
 | 
			
		||||
@ -160,6 +160,8 @@ struct kvm_s390_vm_cpu_subfunc {
 | 
			
		||||
#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW	1
 | 
			
		||||
#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW	2
 | 
			
		||||
#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW	3
 | 
			
		||||
#define KVM_S390_VM_CRYPTO_ENABLE_APIE		4
 | 
			
		||||
#define KVM_S390_VM_CRYPTO_DISABLE_APIE		5
 | 
			
		||||
 | 
			
		||||
/* kvm attributes for migration mode */
 | 
			
		||||
#define KVM_S390_VM_MIGRATION_STOP	0
 | 
			
		||||
 | 
			
		||||
@ -377,6 +377,7 @@ struct kvm_sync_regs {
 | 
			
		||||
 | 
			
		||||
#define KVM_X86_QUIRK_LINT0_REENABLED	(1 << 0)
 | 
			
		||||
#define KVM_X86_QUIRK_CD_NW_CLEARED	(1 << 1)
 | 
			
		||||
#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE	(1 << 2)
 | 
			
		||||
 | 
			
		||||
#define KVM_STATE_NESTED_GUEST_MODE	0x00000001
 | 
			
		||||
#define KVM_STATE_NESTED_RUN_PENDING	0x00000002
 | 
			
		||||
 | 
			
		||||
@ -951,6 +951,8 @@ struct kvm_ppc_resize_hpt {
 | 
			
		||||
#define KVM_CAP_HYPERV_TLBFLUSH 155
 | 
			
		||||
#define KVM_CAP_S390_HPAGE_1M 156
 | 
			
		||||
#define KVM_CAP_NESTED_STATE 157
 | 
			
		||||
#define KVM_CAP_ARM_INJECT_SERROR_ESR 158
 | 
			
		||||
#define KVM_CAP_MSR_PLATFORM_INFO 159
 | 
			
		||||
 | 
			
		||||
#ifdef KVM_CAP_IRQ_ROUTING
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -200,6 +200,7 @@ struct vfio_device_info {
 | 
			
		||||
#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)	/* vfio-platform device */
 | 
			
		||||
#define VFIO_DEVICE_FLAGS_AMBA  (1 << 3)	/* vfio-amba device */
 | 
			
		||||
#define VFIO_DEVICE_FLAGS_CCW	(1 << 4)	/* vfio-ccw device */
 | 
			
		||||
#define VFIO_DEVICE_FLAGS_AP	(1 << 5)	/* vfio-ap device */
 | 
			
		||||
	__u32	num_regions;	/* Max region index + 1 */
 | 
			
		||||
	__u32	num_irqs;	/* Max IRQ index + 1 */
 | 
			
		||||
};
 | 
			
		||||
@ -215,6 +216,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_STRING		"vfio-ap"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8,
 | 
			
		||||
 | 
			
		||||
@ -176,7 +176,7 @@ struct vhost_memory {
 | 
			
		||||
#define VHOST_BACKEND_F_IOTLB_MSG_V2 0x1
 | 
			
		||||
 | 
			
		||||
#define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64)
 | 
			
		||||
#define VHOST_GET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x26, __u64)
 | 
			
		||||
#define VHOST_GET_BACKEND_FEATURES _IOR(VHOST_VIRTIO, 0x26, __u64)
 | 
			
		||||
 | 
			
		||||
/* VHOST_NET specific defines */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -39,8 +39,10 @@ static const S390FeatDef s390_features[] = {
 | 
			
		||||
    FEAT_INIT("srs", S390_FEAT_TYPE_STFL, 9, "Sense-running-status facility"),
 | 
			
		||||
    FEAT_INIT("csske", S390_FEAT_TYPE_STFL, 10, "Conditional-SSKE facility"),
 | 
			
		||||
    FEAT_INIT("ctop", S390_FEAT_TYPE_STFL, 11, "Configuration-topology facility"),
 | 
			
		||||
    FEAT_INIT("apqci", S390_FEAT_TYPE_STFL, 12, "Query AP Configuration Information facility"),
 | 
			
		||||
    FEAT_INIT("ipter", S390_FEAT_TYPE_STFL, 13, "IPTE-range facility"),
 | 
			
		||||
    FEAT_INIT("nonqks", S390_FEAT_TYPE_STFL, 14, "Nonquiescing key-setting facility"),
 | 
			
		||||
    FEAT_INIT("apft", S390_FEAT_TYPE_STFL, 15, "AP Facilities Test facility"),
 | 
			
		||||
    FEAT_INIT("etf2", S390_FEAT_TYPE_STFL, 16, "Extended-translation facility 2"),
 | 
			
		||||
    FEAT_INIT("msa-base", S390_FEAT_TYPE_STFL, 17, "Message-security-assist facility (excluding subfunctions)"),
 | 
			
		||||
    FEAT_INIT("ldisp", S390_FEAT_TYPE_STFL, 18, "Long-displacement facility"),
 | 
			
		||||
@ -129,6 +131,7 @@ static const S390FeatDef s390_features[] = {
 | 
			
		||||
 | 
			
		||||
    FEAT_INIT_MISC("dateh2", "DAT-enhancement facility 2"),
 | 
			
		||||
    FEAT_INIT_MISC("cmm", "Collaborative-memory-management facility"),
 | 
			
		||||
    FEAT_INIT_MISC("ap", "AP instructions installed"),
 | 
			
		||||
 | 
			
		||||
    FEAT_INIT("plo-cl", S390_FEAT_TYPE_PLO, 0, "PLO Compare and load (32 bit in general registers)"),
 | 
			
		||||
    FEAT_INIT("plo-clg", S390_FEAT_TYPE_PLO, 1, "PLO Compare and load (64 bit in parameter list)"),
 | 
			
		||||
 | 
			
		||||
@ -27,8 +27,10 @@ typedef enum {
 | 
			
		||||
    S390_FEAT_SENSE_RUNNING_STATUS,
 | 
			
		||||
    S390_FEAT_CONDITIONAL_SSKE,
 | 
			
		||||
    S390_FEAT_CONFIGURATION_TOPOLOGY,
 | 
			
		||||
    S390_FEAT_AP_QUERY_CONFIG_INFO,
 | 
			
		||||
    S390_FEAT_IPTE_RANGE,
 | 
			
		||||
    S390_FEAT_NONQ_KEY_SETTING,
 | 
			
		||||
    S390_FEAT_AP_FACILITIES_TEST,
 | 
			
		||||
    S390_FEAT_EXTENDED_TRANSLATION_2,
 | 
			
		||||
    S390_FEAT_MSA,
 | 
			
		||||
    S390_FEAT_LONG_DISPLACEMENT,
 | 
			
		||||
@ -119,6 +121,7 @@ typedef enum {
 | 
			
		||||
    /* Misc */
 | 
			
		||||
    S390_FEAT_DAT_ENH_2,
 | 
			
		||||
    S390_FEAT_CMM,
 | 
			
		||||
    S390_FEAT_AP,
 | 
			
		||||
 | 
			
		||||
    /* PLO */
 | 
			
		||||
    S390_FEAT_PLO_CL,
 | 
			
		||||
 | 
			
		||||
@ -786,6 +786,8 @@ static void check_consistency(const S390CPUModel *model)
 | 
			
		||||
        { S390_FEAT_PRNO_TRNG_QRTCR, S390_FEAT_MSA_EXT_5 },
 | 
			
		||||
        { S390_FEAT_PRNO_TRNG, S390_FEAT_MSA_EXT_5 },
 | 
			
		||||
        { S390_FEAT_SIE_KSS, S390_FEAT_SIE_F2 },
 | 
			
		||||
        { S390_FEAT_AP_QUERY_CONFIG_INFO, S390_FEAT_AP },
 | 
			
		||||
        { S390_FEAT_AP_FACILITIES_TEST, S390_FEAT_AP },
 | 
			
		||||
    };
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -33,23 +33,6 @@
 | 
			
		||||
#include "hw/s390x/s390_flic.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* #define DEBUG_S390 */
 | 
			
		||||
/* #define DEBUG_S390_STDOUT */
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_S390
 | 
			
		||||
#ifdef DEBUG_S390_STDOUT
 | 
			
		||||
#define DPRINTF(fmt, ...) \
 | 
			
		||||
    do { fprintf(stderr, fmt, ## __VA_ARGS__); \
 | 
			
		||||
         if (qemu_log_separate()) { qemu_log(fmt, ##__VA_ARGS__); } } while (0)
 | 
			
		||||
#else
 | 
			
		||||
#define DPRINTF(fmt, ...) \
 | 
			
		||||
    do { qemu_log(fmt, ## __VA_ARGS__); } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
#define DPRINTF(fmt, ...) \
 | 
			
		||||
    do { } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
 | 
			
		||||
                                              int ilen, uintptr_t ra)
 | 
			
		||||
{
 | 
			
		||||
@ -128,8 +111,8 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int size,
 | 
			
		||||
    uint64_t asc;
 | 
			
		||||
    int prot;
 | 
			
		||||
 | 
			
		||||
    DPRINTF("%s: address 0x%" VADDR_PRIx " rw %d mmu_idx %d\n",
 | 
			
		||||
            __func__, orig_vaddr, rw, mmu_idx);
 | 
			
		||||
    qemu_log_mask(CPU_LOG_MMU, "%s: addr 0x%" VADDR_PRIx " rw %d mmu_idx %d\n",
 | 
			
		||||
                  __func__, orig_vaddr, rw, mmu_idx);
 | 
			
		||||
 | 
			
		||||
    vaddr = orig_vaddr;
 | 
			
		||||
 | 
			
		||||
@ -158,8 +141,9 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int size,
 | 
			
		||||
    if (!address_space_access_valid(&address_space_memory, raddr,
 | 
			
		||||
                                    TARGET_PAGE_SIZE, rw,
 | 
			
		||||
                                    MEMTXATTRS_UNSPECIFIED)) {
 | 
			
		||||
        DPRINTF("%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__,
 | 
			
		||||
                (uint64_t)raddr, (uint64_t)ram_size);
 | 
			
		||||
        qemu_log_mask(CPU_LOG_MMU,
 | 
			
		||||
                      "%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n",
 | 
			
		||||
                      __func__, (uint64_t)raddr, (uint64_t)ram_size);
 | 
			
		||||
        trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
@ -217,8 +201,10 @@ static void do_program_interrupt(CPUS390XState *env)
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilen=%d\n",
 | 
			
		||||
                  __func__, env->int_pgm_code, ilen);
 | 
			
		||||
    qemu_log_mask(CPU_LOG_INT,
 | 
			
		||||
                  "%s: code=0x%x ilen=%d psw: %" PRIx64 " %" PRIx64 "\n",
 | 
			
		||||
                  __func__, env->int_pgm_code, ilen, env->psw.mask,
 | 
			
		||||
                  env->psw.addr);
 | 
			
		||||
 | 
			
		||||
    lowcore = cpu_map_lowcore(env);
 | 
			
		||||
 | 
			
		||||
@ -240,10 +226,6 @@ static void do_program_interrupt(CPUS390XState *env)
 | 
			
		||||
 | 
			
		||||
    cpu_unmap_lowcore(lowcore);
 | 
			
		||||
 | 
			
		||||
    DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__,
 | 
			
		||||
            env->int_pgm_code, ilen, env->psw.mask,
 | 
			
		||||
            env->psw.addr);
 | 
			
		||||
 | 
			
		||||
    load_psw(env, mask, addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -334,9 +316,6 @@ static void do_ext_interrupt(CPUS390XState *env)
 | 
			
		||||
 | 
			
		||||
    cpu_unmap_lowcore(lowcore);
 | 
			
		||||
 | 
			
		||||
    DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
 | 
			
		||||
            env->psw.mask, env->psw.addr);
 | 
			
		||||
 | 
			
		||||
    load_psw(env, mask, addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -365,8 +344,6 @@ static void do_io_interrupt(CPUS390XState *env)
 | 
			
		||||
    cpu_unmap_lowcore(lowcore);
 | 
			
		||||
    g_free(io);
 | 
			
		||||
 | 
			
		||||
    DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, env->psw.mask,
 | 
			
		||||
            env->psw.addr);
 | 
			
		||||
    load_psw(env, mask, addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -408,9 +385,6 @@ static void do_mchk_interrupt(CPUS390XState *env)
 | 
			
		||||
 | 
			
		||||
    cpu_unmap_lowcore(lowcore);
 | 
			
		||||
 | 
			
		||||
    DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
 | 
			
		||||
            env->psw.mask, env->psw.addr);
 | 
			
		||||
 | 
			
		||||
    load_psw(env, mask, addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -421,8 +395,8 @@ void s390_cpu_do_interrupt(CPUState *cs)
 | 
			
		||||
    CPUS390XState *env = &cpu->env;
 | 
			
		||||
    bool stopped = false;
 | 
			
		||||
 | 
			
		||||
    qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n",
 | 
			
		||||
                  __func__, cs->exception_index, env->psw.addr);
 | 
			
		||||
    qemu_log_mask(CPU_LOG_INT, "%s: %d at psw=%" PRIx64 ":%" PRIx64 "\n",
 | 
			
		||||
                  __func__, cs->exception_index, env->psw.mask, env->psw.addr);
 | 
			
		||||
 | 
			
		||||
try_deliver:
 | 
			
		||||
    /* handle machine checks */
 | 
			
		||||
 | 
			
		||||
@ -447,6 +447,9 @@ static uint16_t full_GEN12_GA1[] = {
 | 
			
		||||
    S390_FEAT_ADAPTER_INT_SUPPRESSION,
 | 
			
		||||
    S390_FEAT_EDAT_2,
 | 
			
		||||
    S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2,
 | 
			
		||||
    S390_FEAT_AP_QUERY_CONFIG_INFO,
 | 
			
		||||
    S390_FEAT_AP_FACILITIES_TEST,
 | 
			
		||||
    S390_FEAT_AP,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static uint16_t full_GEN12_GA2[] = {
 | 
			
		||||
 | 
			
		||||
@ -2299,11 +2299,26 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp)
 | 
			
		||||
        error_setg(errp, "KVM: host CPU model could not be identified");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    /* for now, we can only provide the AP feature with HW support */
 | 
			
		||||
    if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO,
 | 
			
		||||
        KVM_S390_VM_CRYPTO_ENABLE_APIE)) {
 | 
			
		||||
        set_bit(S390_FEAT_AP, model->features);
 | 
			
		||||
    }
 | 
			
		||||
    /* strip of features that are not part of the maximum model */
 | 
			
		||||
    bitmap_and(model->features, model->features, model->def->full_feat,
 | 
			
		||||
               S390_FEAT_MAX);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_s390_configure_apie(bool interpret)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t attr = interpret ? KVM_S390_VM_CRYPTO_ENABLE_APIE :
 | 
			
		||||
                                KVM_S390_VM_CRYPTO_DISABLE_APIE;
 | 
			
		||||
 | 
			
		||||
    if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) {
 | 
			
		||||
        kvm_s390_set_attr(attr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void kvm_s390_apply_cpu_model(const S390CPUModel *model, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    struct kvm_s390_vm_cpu_processor prop  = {
 | 
			
		||||
@ -2353,6 +2368,10 @@ void kvm_s390_apply_cpu_model(const S390CPUModel *model, Error **errp)
 | 
			
		||||
    if (test_bit(S390_FEAT_CMM, model->features)) {
 | 
			
		||||
        kvm_s390_enable_cmma();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (test_bit(S390_FEAT_AP, model->features)) {
 | 
			
		||||
        kvm_s390_configure_apie(true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void kvm_s390_restart_interrupt(S390CPU *cpu)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user