辅助处理器 (AP) 设施

简介

辅助处理器 (AP) 设施是一种 IBM Z 加密设施,由三个 AP 指令和 1 到 256 个 PCIe 加密适配器卡组成。AP 设备为分配给在 IBM Z 系统 LPAR 中运行的 linux 系统的所有 CPU 提供加密功能。

AP 适配器卡通过 AP 总线暴露。vfio-ap 的初衷是使用 VFIO 中介设备 (mediated device) 框架使 AP 卡对 KVM 客户机可用。此实现很大程度上依赖于 s390 虚拟化设施,这些设施完成了提供 AP 设备直接访问的大部分繁重工作。

AP 架构概览

为了便于理解设计,让我们从一些定义开始

  • AP 适配器

    AP 适配器是能够执行加密功能的 IBM Z 适配器卡。一个 LPAR 最多可以分配 0 到 256 个适配器。分配给运行 linux 主机的 LPAR 的适配器将对该 linux 主机可用。每个适配器由 0 到 255 的数字标识;但是,最大适配器数量由机器型号和/或适配器类型决定。安装后,AP 适配器可由任何 CPU 执行的 AP 指令访问。

    AP 适配器卡通过系统的激活配置文件 (Activation Profile) 分配给指定的 LPAR,该配置文件可以通过 HMC 进行编辑。当 linux 主机系统在 LPAR 中 IPL(初始程序加载)时,AP 总线会检测分配给该 LPAR 的 AP 适配器卡,并为每个分配的适配器创建一个 sysfs 设备。例如,如果 AP 适配器 4 和 10 (0x0a) 被分配给该 LPAR,AP 总线将创建以下 sysfs 设备条目

    /sys/devices/ap/card04
    /sys/devices/ap/card0a
    

    这些设备的符号链接也将创建在 AP 总线设备的子目录中

    /sys/bus/ap/devices/[card04]
    /sys/bus/ap/devices/[card04]
    
  • AP 域

    一个适配器被划分为多个域。根据适配器类型和硬件配置,一个适配器最多可持有 256 个域。域由 0 到 255 的数字标识;但是,最大域数由机器型号和/或适配器类型决定。域可以被看作是一组用于处理 AP 命令的硬件寄存器和内存。域可以配置用于明文加密的安全私钥。根据访问方式的不同,域分为以下两种类型

    • 使用域 (Usage domains) 是 AP 指令的目标,用于处理 AP 命令。

    • 控制域 (Control domains) 是通过发送到使用域的 AP 命令进行更改的域;例如,为控制域设置安全私钥。

    AP 使用域和控制域通过系统的激活配置文件分配给给定的 LPAR,该文件可通过 HMC 编辑。当 linux 主机系统在 LPAR 中 IPL 时,AP 总线模块检测分配给该 LPAR 的 AP 使用域和控制域。每个使用域的域号和每个 AP 适配器的适配器号组合在一起创建 AP 队列设备(见下文 AP 队列部分)。每个控制域的域号将表示在位掩码中,并存储在 sysfs 文件 /sys/bus/ap/ap_control_domain_mask 中。掩码中的位从最高有效位到最低有效位依次对应域 0-255。

  • AP 队列

    AP 队列是将 AP 命令发送到特定适配器内部的使用域的手段。AP 队列由包含 AP 适配器 ID (APID) 和 AP 队列索引 (APQI) 的元组标识。APQI 对应于适配器内给定的使用域编号。该元组形成一个唯一标识 AP 队列的 AP 队列编号 (APQN)。AP 指令包含一个包含 APQN 的字段,以标识要发送 AP 命令进行处理的 AP 队列。

    AP 总线将为每个 APQN 创建一个 sysfs 设备,这些 APQN 是从加载 AP 总线模块时检测到的 AP 适配器和使用域编号的笛卡尔积中推导出来的。例如,如果适配器 4 和 10 (0x0a) 以及使用域 6 和 71 (0x47) 被分配给 LPAR,AP 总线将创建以下 sysfs 条目

    /sys/devices/ap/card04/04.0006
    /sys/devices/ap/card04/04.0047
    /sys/devices/ap/card0a/0a.0006
    /sys/devices/ap/card0a/0a.0047
    

    指向这些设备的以下符号链接将在 AP 总线设备子目录中创建

    /sys/bus/ap/devices/[04.0006]
    /sys/bus/ap/devices/[04.0047]
    /sys/bus/ap/devices/[0a.0006]
    /sys/bus/ap/devices/[0a.0047]
    
  • AP 指令

    有三条 AP 指令

    • NQAP:将 AP 命令请求消息入队到队列中

    • DQAP:从队列中出队一个 AP 命令响应消息

    • PQAP:管理队列

    AP 指令标识目标处理 AP 命令的域;这必须是使用域之一。AP 命令可能会修改非使用域的域,但被修改的域必须是控制域之一。

AP 和 SIE

现在让我们来看看在客户机上执行的 AP 指令是如何被硬件解释的。

一个名为加密控制块 (CRYCB) 的附属控制块被附加到我们的主硬件虚拟化控制块上。CRYCB 包含一个 AP 控制块 (APCB),它有三个字段来标识分配给 KVM 客户机的适配器、使用域和控制域

  • AP 掩码 (APM) 字段是一个位掩码,标识分配给 KVM 客户机的 AP 适配器。掩码中的每一位从左到右对应一个 0-255 的 APID。如果设置了某一位,则相应的适配器对 KVM 客户机有效。

  • AP 队列掩码 (AQM) 字段是一个位掩码,标识分配给 KVM 客户机的 AP 使用域。掩码中的每一位从左到右对应一个 0-255 的 AP 队列索引 (APQI)。如果设置了某一位,则相应的队列对 KVM 客户机有效。

  • AP 域掩码 (ADM) 字段是一个位掩码,标识分配给 KVM 客户机的 AP 控制域。ADM 位掩码控制哪些域可以通过从客户机发送到使用域的 AP 命令请求消息进行更改。掩码中的每一位从左到右对应一个 0-255 的域。如果设置了某一位,则相应的域可以通过发送到使用域的 AP 命令请求消息进行修改。

如果您还记得对 AP 队列的描述,AP 指令包含一个 APQN,用于标识要发送 AP 命令请求消息的 AP 队列(NQAP 和 PQAP 指令),或从中接收命令响应消息的 AP 队列(DQAP 指令)。APQN 的有效性由 APM 和 AQM 计算出的矩阵定义;它是所有分配的适配器编号 (APM) 与所有分配的队列索引 (AQM) 的笛卡尔积。例如,如果适配器 1 和 2 以及使用域 5 和 6 被分配给客户机,那么 APQN (1,5)、(1,6)、(2,5) 和 (2,6) 对该客户机有效。

APQN 可以提供安全密钥功能——即,适配器卡为其每个域存储一个私钥——因此每个 APQN 必须最多分配给一个客户机或 linux 主机

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), (2,6);
   Guest2 has APQNs (1,7), (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).

设计

该设计引入了三个新对象

  1. AP 矩阵设备

  2. VFIO AP 设备驱动程序 (vfio_ap.ko)

  3. VFIO AP 中介透传设备

VFIO AP 设备驱动程序

VFIO AP (vfio_ap) 设备驱动程序用于以下目的

  1. 提供锁定 APQN 以供 KVM 客户机独占使用的接口。

  2. 设置 VFIO 中介设备接口以管理 vfio_ap 中介设备,并创建 sysfs 接口用于分配组成 KVM 客户机矩阵的适配器、使用域和控制域。

  3. 在 KVM 客户机的 SIE 状态描述所引用的 CRYCB 中的 APCB 中配置 APM、AQM 和 ADM,以授予客户机访问 AP 设备矩阵的权限

为 KVM 客户机独占使用保留 APQN

以下方框图说明了保留 APQN 的机制

                              +------------------+
               7 remove       |                  |
         +--------------------> cex4queue driver |
         |                    |                  |
         |                    +------------------+
         |
         |
         |                    +------------------+          +----------------+
         |  5 register driver |                  | 3 create |                |
         |   +---------------->   Device core    +---------->  matrix device |
         |   |                |                  |          |                |
         |   |                +--------^---------+          +----------------+
         |   |                         |
         |   |                         +-------------------+
         |   | +-----------------------------------+       |
         |   | |      4 register AP driver         |       | 2 register device
         |   | |                                   |       |
+--------+---+-v---+                      +--------+-------+-+
|                  |                      |                  |
|      ap_bus      +--------------------- >  vfio_ap driver  |
|                  |       8 probe        |                  |
+--------^---------+                      +--^--^------------+
6 edit   |                                   |  |
  apmask |     +-----------------------------+  | 11 mdev create
  aqmask |     |           1 modprobe           |
+--------+-----+---+           +----------------+-+         +----------------+
|                  |           |                  |10 create|     mediated   |
|      admin       |           | VFIO device core |--------->     matrix     |
|                  +           |                  |         |     device     |
+------+-+---------+           +--------^---------+         +--------^-------+
       | |                              |                            |
       | | 9 create vfio_ap-passthrough |                            |
       | +------------------------------+                            |
       +-------------------------------------------------------------+
                   12  assign adapter/domain/control domain

为 KVM 客户机使用保留 AP 队列的过程如下

  1. 管理员加载 vfio_ap 设备驱动程序

  2. vfio-ap 驱动程序在初始化期间将向设备核心注册一个“matrix”设备。这将作为所有用于为客户机配置 AP 矩阵的 vfio_ap 中介设备的父设备。

  3. /sys/devices/vfio_ap/matrix 设备由设备核心创建

  4. vfio_ap 设备驱动程序将向 AP 总线注册类型为 10 及更高(CEX4 及更新版本)的 AP 队列设备。该驱动程序将提供 vfio_ap 驱动程序的 probe 和 remove 回调接口。不支持早于 CEX4 队列的设备,是为了简化实现,避免因支持即将在不久的将来停止服务且周围几乎没有旧系统可供测试的旧设备而使设计变得不必要的复杂。

  5. AP 总线向设备核心注册 vfio_ap 设备驱动程序

  6. 管理员编辑 AP 适配器和队列掩码,以为 vfio_ap 设备驱动程序保留 AP 队列。

  7. AP 总线从默认的 zcrypt cex4queue 驱动程序中移除为 vfio_ap 驱动程序保留的 AP 队列。

  8. AP 总线探测 (probe) vfio_ap 设备驱动程序,以绑定为其保留的队列。

  9. 管理员创建一个透传类型的 vfio_ap 中介设备,供客户机使用

  10. 管理员分配由客户机独占使用的适配器、使用域和控制域。

设置 VFIO 中介设备接口

VFIO AP 设备驱动程序利用 VFIO 中介设备核心驱动程序的通用接口来

  • 注册一个 AP 中介总线驱动程序,以便在 VFIO 组中添加或移除 vfio_ap 中介设备。

  • 创建和销毁 vfio_ap 中介设备

  • 将 vfio_ap 中介设备添加到 AP 中介总线驱动程序或从中移除

  • 将 vfio_ap 中介设备添加到 IOMMU 组或从中移除

以下高级方框图显示了 VFIO AP 中介设备驱动程序的主要组件和接口

+-------------+
|             |
| +---------+ | mdev_register_driver() +--------------+
| |  Mdev   | +<-----------------------+              |
| |  bus    | |                        | vfio_mdev.ko |
| | driver  | +----------------------->+              |<-> VFIO user
| +---------+ |    probe()/remove()    +--------------+    APIs
|             |
|  MDEV CORE  |
|   MODULE    |
|   mdev.ko   |
| +---------+ | mdev_register_parent() +--------------+
| |Physical | +<-----------------------+              |
| | device  | |                        |  vfio_ap.ko  |<-> matrix
| |interface| +----------------------->+              |    device
| +---------+ |       callback         +--------------+
+-------------+

在 vfio_ap 模块初始化期间,matrix 设备通过一个 'mdev_parent_ops' 结构进行注册,该结构提供 sysfs 属性结构、mdev 函数和回调接口,用于管理中介矩阵设备。

  • sysfs 属性结构

    supported_type_groups

    VFIO 中介设备框架支持创建用户定义的中介设备类型。当向中介设备框架注册设备时,这些中介设备类型通过 'supported_type_groups' 结构指定。注册过程会在被注册设备的 'mdev_supported_types' 子目录中为每个指定的中介设备类型创建 sysfs 结构。随设备类型一起提供的还有中介设备类型的 sysfs 属性。

    VFIO AP 设备驱动程序将为透传设备注册一种中介设备类型

    /sys/devices/vfio_ap/matrix/mdev_supported_types/vfio_ap-passthrough

    仅提供 VFIO mdev 框架所需的只读属性

    ... name
    ... device_api
    ... available_instances
    ... device_api
    

    其中:

    • name

      指定中介设备类型的名称

    • device_api

      中介设备类型的 API

    • available_instances

      可以创建的 vfio_ap 中介透传设备数量

    • device_api

      指定 VFIO API

    mdev_attr_groups

    该属性组标识中介设备的用户定义 sysfs 属性。当向 VFIO 中介设备框架注册设备时,'mdev_attr_groups' 结构中标识的 sysfs 属性文件将在 vfio_ap 中介设备的目录中创建。vfio_ap 中介设备的 sysfs 属性为

    assign_adapter / unassign_adapter

    用于向 vfio_ap 中介设备分配/取消分配 AP 适配器的只写属性。要分配/取消分配适配器,将适配器的 APID 写入相应的属性文件中。

    assign_domain / unassign_domain

    用于向 vfio_ap 中介设备分配/取消分配 AP 使用域的只写属性。要分配/取消分配域,将使用域的域号写入相应的属性文件中。

    matrix

    一个只读文件,用于显示从分配给 vfio_ap 中介设备的适配器编号和域编号的笛卡尔积中推导出的 APQN。

    guest_matrix

    一个只读文件,用于显示从分别分配给 KVM 客户机 CRYCB 的 APM 和 AQM 字段的适配器和域编号的笛卡尔积中推导出的 APQN。如果任何 APQN 未引用绑定到 vfio_ap 设备驱动程序的队列设备(即队列不在主机的 AP 配置中),则这可能与分配给 vfio_ap 中介设备的 APQN 不同。

    assign_control_domain / unassign_control_domain

    用于向 vfio_ap 中介设备分配/取消分配 AP 控制域的只写属性。要分配/取消分配控制域,将要分配/取消分配的域 ID 写入相应的属性文件中。

    control_domains

    一个只读文件,用于显示分配给 vfio_ap 中介设备的控制域编号。

    ap_config

    一个读/写文件,写入该文件时,可以一次性替换 vfio_ap 中介设备的所有三个 ap 矩阵掩码。提供三个掩码,一个用于适配器,一个用于域,一个用于控制域。如果给定的状态无法设置,则不会对 vfio-ap 中介设备进行任何更改。

    写入 ap_config 的数据格式如下:{amask},{dmask},{cmask}n

    n 是换行符。

    amask、dmask 和 cmask 是标识应分配给中介设备的适配器、域和控制域的掩码。

    掩码格式如下:0xNN..NN

    其中 NN..NN 是代表 256 位值的 64 个十六进制字符。最左边(最高阶)位代表适配器/域 0。

    要获取代表您 mdev 当前配置的示例掩码集,只需查看 ap_config 的内容。

    设置大于系统允许的最大值的适配器或域号将导致错误。

    此属性旨在由自动化工具使用。最终用户最好使用适配器、域和控制域各自的分配/取消分配属性。

  • functions

    create

    分配 vfio_ap 驱动程序使用的 ap_matrix_mdev 结构,以

    • 存储对使用该 mdev 的客户机的 KVM 结构的引用

    • 存储通过相应 sysfs 属性文件分配的适配器、域和控制域的 AP 矩阵配置

    • 存储客户机可用的适配器、域和控制域的 AP 矩阵配置。客户机可能无法访问引用不存在或未绑定到 vfio_ap 设备驱动程序的队列设备的 APQN。

    remove

    取消分配 vfio_ap 中介设备的 ap_matrix_mdev 结构。仅在运行中的客户机未使用该 mdev 时才允许此操作。

  • 回调接口

    open_device

    userspace 调用 open_device 回调,将矩阵 mdev 设备的 VFIO iommu 组连接到 MDEV 总线。该回调检索用于配置 KVM 客户机的 KVM 结构,并配置客户机对通过 vfio_ap 中介设备的 sysfs 属性文件定义的 AP 矩阵的访问。

    close_device

    此回调取消配置客户机的 AP 矩阵。

    ioctl

    此回调处理 vfio 框架定义的 VFIO_DEVICE_GET_INFO 和 VFIO_DEVICE_RESET ioctl。

配置客户机的 AP 资源

为 KVM 客户机配置 AP 资源将在 open_deviceclose_device 时执行。客户机的 AP 资源通过其 APCB 进行配置,方式如下:

  • 在 APM 中设置对应于通过其 ‘assign_adapter’ 接口分配给 vfio_ap 中介设备的 APID 的位。

  • 在 AQM 中设置对应于通过其 ‘assign_domain’ 接口分配给 vfio_ap 中介设备的域的位。

  • 在 ADM 中设置对应于通过其 ‘assign_control_domains’ 接口分配给 vfio_ap 中介设备的域 dID 的位。

linux 设备模型排除了将未绑定到透传驱动程序的设备透传给 KVM 客户机的可能性。因此,未引用绑定到 vfio_ap 设备驱动程序的队列设备的 APQN 将不会分配给 KVM 客户机的矩阵。然而,AP 架构并未提供从客户机矩阵中过滤单个 APQN 的手段,因此,在为客户机提供 AP 配置之前,将对通过其 sysfs ‘assign_adapter’、‘assign_domain’ 和 ‘assign_control_domain’ 接口分配给 vfio_ap 中介设备的适配器、域和控制域进行过滤

  • 分配给矩阵 mdev 但未分配给主机 AP 配置的适配器的 APID、域的 APQI 和控制域的域号将被过滤掉。

  • 检查由分配给 vfio_ap mdev 的 APID 和 APQI 的笛卡尔积得出的每个 APQN,如果其中任何一个未引用绑定到 vfio_ap 设备驱动程序的队列设备,则该适配器将不会接入到客户机(即,客户机 APCB 的 APM 中对应其 APID 的位将不被设置)。

面向 AP 的 CPU 模型功能

AP 堆栈依赖于 AP 指令的存在以及三个设施:AP 设施测试 (APFT) 设施;AP 查询配置信息 (QCI) 设施;以及 AP 队列中断控制设施。这些功能/设施通过以下 CPU 模型功能提供给 KVM 客户机

  1. ap:指示客户机上是否安装了 AP 指令。仅当主机上安装了 AP 指令时,KVM 才会启用此功能。

  2. apft:指示客户机上是否有 APFT 设施可用。仅当主机上可用(即设施位 15 已设置)时,该设施才能对客户机可用。

  3. apqci:指示客户机上是否有 AP QCI 设施可用。仅当主机上可用(即设施位 12 已设置)时,该设施才能对客户机可用。

  4. apqi:指示客户机上是否有 AP 队列中断控制设施可用。仅当主机上可用(即设施位 65 已设置)时,该设施才能对客户机可用。

注意:如果用户选择为 QEMU 指定不同于 ‘host’ 模型的 CPU 模型,则需要显式开启 CPU 模型功能和设施;例如

/usr/bin/qemu-system-s390x ... -cpu z13,ap=on,apqci=on,apft=on,apqi=on

通过显式关闭 AP 功能/设施,可以阻止客户机使用它们;例如

/usr/bin/qemu-system-s390x ... -cpu host,ap=off,apqci=off,apft=off,apqi=off

注意:如果为客户机关闭了 APFT 设施 (apft=off),客户机将看不到任何 AP 设备。客户机上注册 10 型及更新 AP 设备(即 cex4card 和 cex4queue 设备驱动程序)的 zcrypt 设备驱动程序需要 APFT 设施来确定安装在给定 AP 设备上的设施。如果客户机上未安装 APFT 设施,则在客户机上运行的 AP 总线将不会创建任何适配器或域设备,因为只有 10 型及更新的设备才能配置供客户机使用。

示例

现在让我们提供一个示例,说明如何给予 KVM 客户机访问 AP 设施的权限。在本例中,我们将展示如何配置三个客户机,使在客户机上执行 lszcrypt 命令的结果如下

Guest1

卡.域

类型

模式

05

CEX5C

CCA-协处理器

05.0004

CEX5C

CCA-协处理器

05.00ab

CEX5C

CCA-协处理器

06

CEX5A

加速器

06.0004

CEX5A

加速器

06.00ab

CEX5A

加速器

Guest2

卡.域

类型

模式

05

CEX5C

CCA-协处理器

05.0047

CEX5C

CCA-协处理器

05.00ff

CEX5C

CCA-协处理器

Guest3

卡.域

类型

模式

06

CEX5A

加速器

06.0047

CEX5A

加速器

06.00ff

CEX5A

加速器

步骤如下

  1. 在 linux 主机上安装 vfio_ap 模块。vfio_ap 模块的依赖链为:* iommu * s390 * zcrypt * vfio * vfio_mdev * vfio_mdev_device * KVM

    要编译 vfio_ap 模块,内核编译必须配置以下选定的 Kconfig 元素:* IOMMU_SUPPORT * S390 * AP * VFIO * KVM

    如果使用 make menuconfig,请选择以下项以编译 vfio_ap 模块

    -> 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. 锁定供三个客户机使用的 AP 队列,以便主机无法访问它们。为了锁定它们,有两个 sysfs 文件指定了位掩码,将 APQN 范围的一个子集标记为仅供默认 AP 队列设备驱动程序使用。所有剩余的 APQN 都可供任何其他设备驱动程序使用。vfio_ap 设备驱动程序目前是唯一的非默认设备驱动程序。包含掩码的 sysfs 文件位置为

    /sys/bus/ap/apmask
    /sys/bus/ap/aqmask
    

    ‘apmask’ 是一个 256 位掩码,标识一组 AP 适配器 ID (APID)。掩码中的每一位从左到右对应一个 0-255 的 APID。如果设置了某一位,则该 APID 属于被标记为仅对默认 AP 队列设备驱动程序可用的 APQN 子集。

    ‘aqmask’ 是一个 256 位掩码,标识一组 AP 队列索引 (APQI)。掩码中的每一位从左到右对应一个 0-255 的 APQI。如果设置了某一位,则该 APQI 属于被标记为仅对默认 AP 队列设备驱动程序可用的 APQN 子集。

    apmask 中设置的位对应的 APID 与 aqmask 中设置的位对应的 APQI 的笛卡尔积组成了仅供主机默认设备驱动程序使用的 APQN 子集。所有其他 APQN 都可供非默认设备驱动程序(如 vfio_ap 驱动程序)使用。

    以如下掩码为例

    apmask:
    0x7d00000000000000000000000000000000000000000000000000000000000000
    
    aqmask:
    0x8000000000000000000000000000000000000000000000000000000000000000
    

    掩码指示

    • 适配器 1、2、3、4、5 和 7 可供主机默认设备驱动程序使用。

    • 域 0 可供主机默认设备驱动程序使用

    • 仅供默认主机设备驱动程序使用的 APQN 子集为

      (1,0), (2,0), (3,0), (4.0), (5,0) 和 (7,0)

    • 所有其他 APQN 均可供非默认设备驱动程序使用。

    分配给 linux 主机的每个 AP 队列设备的 APQN 由 AP 总线根据 APID 和 APQI 笛卡尔积推导出的 APQN 集合(标记为对默认 AP 队列设备驱动程序可用)进行检查。如果检测到匹配,将仅探测默认 AP 队列设备驱动程序;否则,将探测 vfio_ap 设备驱动程序。

    默认情况下,两个掩码被设置为保留所有 APQN 供默认 AP 队列设备驱动程序使用。有两种方法可以更改默认掩码

    1. 可以通过将以下两种格式之一的字符串写入各自的 sysfs 掩码文件来编辑 sysfs 掩码文件

      • 以 0x 开头的绝对十六进制字符串——如 “0x12345678” —— 设置掩码。如果给定的字符串短于掩码,则在右侧补 0;例如,指定 0x41 的掩码值等同于指定

        0x4100000000000000000000000000000000000000000000000000000000000000
        

        请记住掩码是从左向右读取的,因此上面的掩码标识了设备号 1 和 7 (01000001)。

        如果字符串长于掩码,操作将因错误 (EINVAL) 而终止。

      • 掩码中的各个位可以通过在逗号分隔的列表中指定要切换的每个位编号来开启或关闭。每个位编号字符串必须前置加号 (‘+’) 或减号 (‘-’),以指示相应的位是要开启 (‘+’) 还是关闭 (‘-‘)。一些有效值包括

        • “+0” 开启第 0 位

        • “-13” 关闭第 13 位

        • “+0x41” 开启第 65 位

        • “-0xff” 关闭第 255 位

        以下示例

        +0,-6,+0x47,-0xf0

        开启第 0 位和第 71 位 (0x47)

        关闭第 6 位和第 240 位 (0xf0)

        请注意,列表中未指定的位保持操作前的状态。

    2. 也可以在启动时通过内核命令行参数更改掩码,如下所示

      ap.apmask=0xffff ap.aqmask=0x40

      这将创建以下掩码

      apmask:
      0xffff000000000000000000000000000000000000000000000000000000000000
      
      aqmask:
      0x4000000000000000000000000000000000000000000000000000000000000000
      

      导致产生这两个池

      default drivers pool:    adapter 0-15, domain 1
      alternate drivers pool:  adapter 16-255, domains 0, 2-255
      

    注意: 更改掩码导致一个或多个 APQN 从 vfio_ap 中介设备(见下文)中被取走时,操作将失败并报错 (EBUSY)。消息会被记录到内核环形缓冲区,可以使用 ‘dmesg’ 命令查看。输出标识了每个被标记为 ‘in use’(在使用中)的 APQN,并标识了分配给它的 vfio_ap 中介设备;例如

    Userspace may not re-assign queue 05.0054 already assigned to 62177883-f1bb-47f0-914d-32a22e3a8804 Userspace may not re-assign queue 04.0054 already assigned to cef03c3c-903d-4ecc-9a83-40694cb8aee4

为我们的示例锁定 APQN

为了锁定 AP 队列 05.0004, 05.0047, 05.00ab, 05.00ff, 06.0004, 06.0047, 06.00ab 和 06.00ff 供 vfio_ap 设备驱动程序使用,可以使用以下任一命令从默认掩码中移除相应的 APQN

echo -5,-6 > /sys/bus/ap/apmask

echo -4,-0x47,-0xab,-0xff > /sys/bus/ap/aqmask

或者可以按如下方式设置掩码

echo 0xf9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \
> apmask

echo 0xf7fffffffffffffffeffffffffffffffffffffffffeffffffffffffffffffffe \
> aqmask

这将导致 AP 队列 05.0004, 05.0047, 05.00ab, 05.00ff, 06.0004, 06.0047, 06.00ab 和 06.00ff 绑定到 vfio_ap 设备驱动程序。vfio_ap 设备驱动程序的 sysfs 目录现在将包含指向与其绑定的 AP 队列设备的符号链接

/sys/bus/ap
... [drivers]
...... [vfio_ap]
......... [05.0004]
......... [05.0047]
......... [05.00ab]
......... [05.00ff]
......... [06.0004]
......... [06.0047]
......... [06.00ab]
......... [06.00ff]

请记住,只有类型为 10 及更新的适配器(即 CEX4 及更高版本)才能绑定到 vfio_ap 设备驱动程序。其原因是简化实现,通过不支持在不久的将来停止服务且周围几乎没有旧系统可供测试的旧设备,来避免使设计变得不必要的复杂。

因此,管理员必须注意仅锁定可绑定到 vfio_ap 设备驱动程序的 AP 队列。给定 AP 队列设备的设备类型可以从父卡的 sysfs 目录中读取。例如,查看队列 05.0004 的硬件类型

cat /sys/bus/ap/devices/card05/hwtype

硬件类型 (hwtype) 必须为 10 或更高(CEX4 或更新版本)才能绑定到 vfio_ap 设备驱动程序。

  1. 创建为三个客户机配置 AP 矩阵所需的中介设备,并为 vfio_ap 驱动程序提供一个供客户机使用的接口

    /sys/devices/vfio_ap/matrix/
    --- [mdev_supported_types]
    ------ [vfio_ap-passthrough] (passthrough vfio_ap mediated device type)
    --------- create
    --------- [devices]
    

    为三个客户机创建中介设备

    uuidgen > create
    uuidgen > create
    uuidgen > create
    
    or
    
    echo $uuid1 > create
    echo $uuid2 > create
    echo $uuid3 > create
    

    这将在 [devices] 子目录中创建三个以写入 create 属性文件的 UUID 命名的中介设备。我们称它们为 $uuid1, $uuid2 和 $uuid3,这是创建后的 sysfs 目录结构

    /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
    
    注意 *:vfio_ap mdev 在重启后不会持久存在,除非

    使用 mdevctl 工具来创建并持久化它们。

  2. 管理员现在需要为中介设备 $uuid1 (Guest1), $uuid2 (Guest2) 和 $uuid3 (Guest3) 配置矩阵。

    以下是为 Guest1 配置矩阵的方法

    echo 5 > assign_adapter
    echo 6 > assign_adapter
    echo 4 > assign_domain
    echo 0xab > assign_domain
    

    可以同样使用 assign_control_domain sysfs 文件来分配控制域。

    如果配置适配器、域或控制域时出错,可以使用 unassign_xxx 文件来取消分配适配器、域或控制域。

    显示 Guest1 的矩阵配置

    cat matrix
    

    显示已经或将要分配给 Guest1 的矩阵

    cat guest_matrix
    

    以下是为 Guest2 配置矩阵的方法

    echo 5 > assign_adapter
    echo 0x47 > assign_domain
    echo 0xff > assign_domain
    

    以下是为 Guest3 配置矩阵的方法

    echo 6 > assign_adapter
    echo 0x47 > assign_domain
    echo 0xff > assign_domain
    

    为了成功分配适配器

    • 指定的适配器编号必须表示一个从 0 到为系统配置的最大适配器编号的值。如果指定的适配器编号高于最大值,操作将因错误 (ENODEV) 而终止。

      注意:最大适配器编号可以通过 sysfs

      /sys/bus/ap/ap_max_adapter_id 属性文件获取。

    • 从被分配适配器的 APID 与之前分配的域的 APQI 的笛卡尔积中推导出的每个 APQN

      • 必须仅对 vfio_ap 设备驱动程序可用,如 sysfs /sys/bus/ap/apmask 和 /sys/bus/ap/aqmask 属性文件中所指定的。即使只有一个 APQN 被保留供主机设备驱动程序使用,操作也将因错误 (EADDRNOTAVAIL) 而终止。

      • 必须不得分配给另一个 vfio_ap 中介设备。即使只有一个 APQN 被分配给另一个 vfio_ap 中介设备,操作也将因错误 (EBUSY) 而终止。

      • 在编辑 sysfs /sys/bus/ap/apmask 和 sys/bus/ap/aqmask 属性文件时,不得进行分配,否则操作可能因错误 (EBUSY) 而终止。

    为了成功分配域

    • 指定的域编号必须表示一个从 0 到为系统配置的最大域编号的值。如果指定的域编号高于最大值,操作将因错误 (ENODEV) 而终止。

      注意:最大域编号可以通过 sysfs

      /sys/bus/ap/ap_max_domain_id 属性文件获取。

    • 从被分配域的 APQI 与之前分配的适配器的 APID 的笛卡尔积中推导出的每个 APQN

    • 必须仅对 vfio_ap 设备驱动程序可用,如 sysfs /sys/bus/ap/apmask 和 /sys/bus/ap/aqmask 属性文件中所指定的。即使只有一个 APQN 被保留供主机设备驱动程序使用,操作也将因错误 (EADDRNOTAVAIL) 而终止。

    • 必须不得分配给另一个 vfio_ap 中介设备。即使只有一个 APQN 被分配给另一个 vfio_ap 中介设备,操作也将因错误 (EBUSY) 而终止。

    • 在编辑 sysfs /sys/bus/ap/apmask 和 sys/bus/ap/aqmask 属性文件时,不得进行分配,否则操作可能因错误 (EBUSY) 而终止。

    为了成功分配控制域

    • 指定的域编号必须表示一个从 0 到为系统配置的最大域编号的值。如果指定的控制域编号高于最大值,操作将因错误 (ENODEV) 而终止。

  3. 启动 Guest1

    /usr/bin/qemu-system-s390x ... -cpu host,ap=on,apqci=on,apft=on,apqi=on \
       -device vfio-ap,sysfsdev=/sys/devices/vfio_ap/matrix/$uuid1 ...
    
  1. 启动 Guest2

    /usr/bin/qemu-system-s390x ... -cpu host,ap=on,apqci=on,apft=on,apqi=on \
       -device vfio-ap,sysfsdev=/sys/devices/vfio_ap/matrix/$uuid2 ...
    
  1. 启动 Guest3

    /usr/bin/qemu-system-s390x ... -cpu host,ap=on,apqci=on,apft=on,apqi=on \
       -device vfio-ap,sysfsdev=/sys/devices/vfio_ap/matrix/$uuid3 ...
    

客户机关闭后,可以移除 vfio_ap 中介设备。

再次以我们的示例为例,要移除 vfio_ap 中介设备 $uuid1

/sys/devices/vfio_ap/matrix/
   --- [mdev_supported_types]
   ------ [vfio_ap-passthrough]
   --------- [devices]
   ------------ [$uuid1]
   --------------- remove
echo 1 > remove

这将移除矩阵 mdev 设备的所有 sysfs 结构,包括 mdev 设备本身。要重新创建并重新配置矩阵 mdev 设备,必须再次执行从第 3 步开始的所有步骤。请注意,如果仍有客户机正在使用该 vfio_ap mdev,移除操作将失败。

并非必须移除 vfio_ap mdev,但如果在 linux 主机的剩余生命周期内没有客户机会使用它,则可能需要将其移除。如果移除了 vfio_ap mdev,可能还需要重新配置保留供默认驱动程序使用的适配器和队列池。

热插拔支持:

如果满足以下条件,可以通过将适配器、域或控制域分配给客户机正在使用的 vfio_ap 中介设备,将其热插拔到运行中的 KVM 客户机中

  • 适配器、域或控制域也必须分配给主机的 AP 配置。

  • 从被分配适配器的 APID 和分配的域的 APQI 组成的笛卡尔积中推导出的每个 APQN 必须引用绑定到 vfio_ap 设备驱动程序的队列设备。

  • 要热插拔一个域,从被分配域的 APQI 和分配的适配器的 APID 组成的笛卡尔积中推导出的每个 APQN 必须引用绑定到 vfio_ap 设备驱动程序的队列设备。

通过从客户机正在使用的 vfio_ap 中介设备中取消分配,可以将适配器、域或控制域从运行中的 KVM 客户机中热拔出。

为 KVM 客户机超额配置 AP 队列:

本文中的超额配置定义为向 vfio_ap 中介设备分配未引用主机 AP 配置中 AP 设备的适配器或域。这里的思路是,当适配器或域变得可用时,只要接入产生的每个新 APQN 都引用了绑定到 vfio_ap 设备驱动程序的队列设备,它就会自动热插拔到使用其分配到的 vfio_ap 中介设备的 KVM 客户机中。

驱动程序功能

vfio_ap 驱动程序暴露了一个包含支持的功能的 sysfs 文件。这样做是为了让第三方工具(如 Libvirt 和 mdevctl)可以查询特定功能的可用性。

功能列表可以在这里找到:/sys/bus/matrix/devices/matrix/features

条目以空格分隔。每个条目由字母数字和下划线字符的组合组成。

示例:cat /sys/bus/matrix/devices/matrix/features guest_matrix dyn ap_config

展示了以下功能

---------------+---------------------------------------------------------------+ | 标志 | 描述 | +==============+===============================================================+ | guest_matrix | 存在 guest_matrix 属性。它报告了当 mdev 连接到客户机时,| | | 已经或将要透传给客户机的适配器和域的矩阵。| +--------------+---------------------------------------------------------------+ | dyn | 表示连接了该 mdev 的客户机支持 AP 适配器、域和控制域的 | | | 热插拔/热拔出。| +------------+-----------------------------------------------------------------+ | ap_config | 用于一次性修改 mdev 配置的 ap_config 接口 | +--------------+---------------------------------------------------------------+

限制

在没有系统管理员干预的情况下,不支持使用 AP 设备的客户机进行在线迁移。在迁移 KVM 客户机之前,必须先移除 vfio_ap 中介设备。遗憾的是,当 KVM 客户机正在使用 mdev 时,无法手动移除它(即 echo 1 > /sys/devices/vfio_ap/matrix/$UUID/remove)。如果客户机是由 QEMU 模拟的,可以通过以下两种方式之一将其 mdev 从客户机热拔出

  1. 如果 KVM 客户机是使用 libvirt 启动的,您可以通过以下命令热拔出 mdev

    virsh detach-device <guestname> <path-to-device-xml>

    例如,从名为 ‘my-guest’ 的客户机中热拔出 mdev 62177883-f1bb-47f0-914d-32a22e3a8804

    virsh detach-device my-guest ~/config/my-guest-hostdev.xml

    my-guest-hostdev.xml 的内容

      <hostdev mode='subsystem' type='mdev' managed='no' model='vfio-ap'>
        <source>
          <address uuid='62177883-f1bb-47f0-914d-32a22e3a8804'/>
        </source>
      </hostdev>


virsh qemu-monitor-command <guest-name> --hmp "device-del <device-id>"

For example, to hot unplug the vfio_ap mediated device identified on the
qemu command line with 'id=hostdev0' from the guest named 'my-guest':
virsh qemu-monitor-command my-guest --hmp "device_del hostdev0"
  1. 通过将 qemu monitor 连接到客户机并使用以下 qemu monitor 命令,可以热拔出 vfio_ap 中介设备

    (QEMU) device-del id=<device-id>

    例如,要热拔出在启动客户机时在 qemu 命令行上使用 ‘id=hostdev0’ 指定的 vfio_ap 中介设备

    (QEMU) device-del id=hostdev0

在 KVM 客户机在线迁移完成后,可以通过以下两种方式之一将目标系统上的 vfio_ap 中介设备热插拔到客户机,从而为 KVM 客户机恢复 AP 配置

  1. 如果 KVM 客户机是使用 libvirt 启动的,您可以通过以下 virsh 命令将矩阵中介设备热插拔到客户机中

    virsh attach-device <guestname> <path-to-device-xml>

    例如,将 mdev 62177883-f1bb-47f0-914d-32a22e3a8804 热插拔到名为 ‘my-guest’ 的客户机中

    virsh attach-device my-guest ~/config/my-guest-hostdev.xml

    my-guest-hostdev.xml 的内容

         <hostdev mode='subsystem' type='mdev' managed='no' model='vfio-ap'>
           <source>
             <address uuid='62177883-f1bb-47f0-914d-32a22e3a8804'/>
           </source>
         </hostdev>


virsh qemu-monitor-command <guest-name> --hmp \
"device_add vfio-ap,sysfsdev=<path-to-mdev>,id=<device-id>"

   For example, to hot plug the vfio_ap mediated device
   62177883-f1bb-47f0-914d-32a22e3a8804 into the guest named 'my-guest' with
   device-id hostdev0:

   virsh qemu-monitor-command my-guest --hmp \
   "device_add vfio-ap,\
   sysfsdev=/sys/devices/vfio_ap/matrix/62177883-f1bb-47f0-914d-32a22e3a8804,\
   id=hostdev0"
  1. 通过将 qemu monitor 连接到客户机并使用以下 qemu monitor 命令,可以热插拔 vfio_ap 中介设备

    (qemu) device_add “vfio-ap,sysfsdev=<path-to-mdev>,id=<device-id>”

    例如,将 ID 为 hostdev0 的 vfio_ap 中介设备 62177883-f1bb-47f0-914d-32a22e3a8804 接入到客户机

    (QEMU) device-add “vfio-ap,sysfsdev=/sys/devices/vfio_ap/matrix/62177883-f1bb-47f0-914d-32a22e3a8804,id=hostdev0”