Linux s390 vfio_ap 设备驱动锁机制详解:矩阵设备、KVM 与 PQAP Hook 四把锁的职责与加锁顺序
Linux s390 vfio_ap 设备驱动锁机制详解矩阵设备、KVM 与 PQAP Hook 四把锁的职责与加锁顺序【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux导读本文深入剖析 Linux 内核 s390 架构下 vfio_apAP 矩阵设备直通设备驱动为保证安全运行所依赖的四把核心锁Matrix Devices Lock矩阵设备锁、KVM Lock、Guests Lock客户机锁与 PQAP Hook Lock。它们分别守护 mediated device中介设备的状态数据、KVM 客户机状态、KVM 指针以及 PQAP(AQIC) 指令拦截回调共同保证 AP 适配器/域/控制域在直通进 KVM 客户机过程中不被并发访问破坏。读完本文你将掌握这四把锁各自的作用域、必须持锁的场景、正确的加锁/解锁顺序以及 PQAP 拦截路径上的锁使用细节可直接对照内核源码定位每一处加锁点。本文主体基于 Documentation/arch/s390/vfio-ap-locking.rst并结合仓库中 vfio_ap 驱动的实际实现drivers/s390/crypto/vfio_ap_ops.c、drivers/s390/crypto/vfio_ap_private.h与 KVM 侧拦截代码arch/s390/kvm/s390/priv.c展开印证。背景为什么 vfio_ap 驱动需要精密的锁机制vfio_ap 是 s390 平台上通过 VFIO 框架把 APAdjunct Processor密码协处理器适配器、域队列和控制域直通pass-through给 KVM 客户机的设备驱动。客户机内的 AP 指令如 PQAP(AQIC)、TAPQ会在宿主机上被拦截由驱动代为执行因此宿主机侧并发路径很多热插拔 AP 设备、扫描 AP 配置变更、客户机执行 PQAP 指令请求中断使能/禁用、客户机关闭时清理资源等。这些路径会并发访问 mediated device 的状态矩阵位图、KVM 指针、队列哈希表以及 KVM 客户机的 AP 控制块APCB。为了在“直通设备的并发生命周期管理”与“KVM 客户机状态更新”之间建立秩序驱动引入了四把锁。文中统一使用以下变量指代相关结构实例struct ap_matrix_dev *matrix_dev; struct ap_matrix_mdev *matrix_mdev; struct kvm *kvm;其中matrix_dev是驱动唯一的矩阵设备对象全局单例matrix_mdev是代表每个 mediated matrix device 的实例kvm是客户机状态容器。Matrix Devices Lock守护 mediated device 全部字段的全局互斥锁Matrix Devices Lockmatrix_dev-mdevs_lock定义在 drivers/s390/crypto/vfio_ap_private.h 中的struct ap_matrix_dev内struct ap_matrix_dev { ... struct list_head mdev_list; struct mutex mdevs_lock; /* serializes access to each ap_matrix_mdev */ ... };从源码注释看这把锁“每次操作 vfio_ap 驱动管理的状态时都要持有——无论是使用mdev_list还是写单个ap_matrix_mdev设备的状态”驱动作者也坦承它“相当粗粒度但预计不会有太多竞争”serializes access to each ap_matrix_mdev。它在 drivers/s390/crypto/vfio_ap_drv.c 中通过mutex_init(matrix_dev-mdevs_lock)初始化。使用规则锁被实现为包含在struct ap_matrix_dev单例对象内的全局互斥锁它控制对matrix_dev-mdev_list中每一个matrix_mdev实例内部所有字段的访问读取、写入或使用某个matrix_mdev实例内字段的数据时必须持有本锁。例如handle_pqap在操作队列中断使能/禁用前先执行mutex_lock(matrix_dev-mdevs_lock)结束后mutex_unlock(matrix_dev-mdevs_lock)见 vfio_ap_ops.c。代码佐证KVM 指针的写入同样在其保护下进行matrix_mdev-kvm指针的设置与清空都在 Matrix Devices Lock 保护下完成。在 vfio_ap_ops.c 附近驱动先取guests_lock再取mdevs_lock随后设置/清空matrix_mdev-kvm等状态。这也是后文“Guests Lock”必须与“Matrix Devices Lock”配合的原因。KVM Lock保护客户机 AP 状态更新的锁KVM Lockkvm-lock位于通用 KVM 结构体 include/linux/kvm_host.h 的struct kvm中struct kvm { ... struct mutex lock; ... }使用规则kvm-lock控制对 KVM 客户机状态数据的访问当驱动要把一个或多个 AP 适配器、域或控制域插入plug in或拔出unplug客户机时必须持有kvm-lock因为这一操作需要改写客户机的 APCBAP 控制块KVM 指针保存在对应的matrix_mdev实例中matrix_mdev-kvm kvm即保存了“已附加到 KVM 客户机的 mediated device”的状态。驱动通过检查matrix_mdev-kvm ! NULL判断该 mediated device 是否已直通给客户机。代码佐证动态更新 APCB 时锁定 KVM在 vfio_ap_ops.c 中get_update_locks_for_kvm()/release_update_locks_for_kvm()明确展示了“更新客户机 APCB”时的完整锁序static inline void get_update_locks_for_kvm(struct kvm *kvm) { mutex_lock(matrix_dev-guests_lock); if (kvm) { mutex_lock(kvm-lock); down_write(kvm-arch.crypto.pqap_hook_rwsem); } mutex_lock(matrix_dev-mdevs_lock); }注意这里kvm-lock与pqap_hook_rwsem仅在kvm非空时才获取即客户机存在时解锁顺序严格与加锁顺序相反mdevs_lock→pqap_hook_rwsem→kvm-lock→guests_lock。此外还有针对matrix_mdev的变体get_update_locks_for_mdev()以及通过 APQN 反查 mdev 再取锁的get_update_locks_by_apqn()vfio_ap_ops.c后者先遍历matrix_dev-mdev_list找到持有该 APQN 的 mdev再按同样顺序加锁——这就是文档强调“正确加锁顺序”的工程落地。Guests Lock保护 KVM 指针与 mdev 列表遍历Guests Lockmatrix_dev-guests_lock同样定义在struct ap_matrix_dev中紧邻mdevs_lockstruct ap_matrix_dev { ... struct list_head mdev_list; struct mutex guests_lock; /* serializes access to each KVM guest */ ... };源码注释将其职责描述为“控制对使用 vfio_ap 驱动直通 AP 设备的客户机的访问。当 AP 设备插入/拔出客户机以及ap_matrix_mdev被加入/移出mdev_list或列表被遍历时都要持有此锁。”在 drivers/s390/crypto/vfio_ap_drv.c 中通过mutex_init(matrix_dev-guests_lock)初始化。必须持有 Guests Lock 的两种场景使用 KVM 指针向客户机插入/拔出 AP 设备时matrix_mdev-kvm指针在驱动用它向 KVM 客户机插拔直通 AP 设备期间必须由guests_lock保护。因为一旦客户机被销毁或 detach指针会被并发清空继续使用便是悬垂指针。向matrix_dev-mdev_list添加或移除matrix_mdev实例时这保证了在遍历列表查找某个ap_matrix_mdev以便向客户机插拔 AP 设备时列表结构不会因并发的 add/remove 而损坏。文档给出的典型场景队列设备被移除文档用“队列设备从 vfio_ap 驱动被移除”举例说明了第二类场景的完整推理链当队列queue设备被移除时若其所属适配器已直通给 KVM 客户机就必须执行拔出unplug操作为判断适配器是否已直通需要先找到该队列所属的matrix_mdev对象再读取matrix_mdev-kvm指针判断 mediated device 是否已直通matrix_mdev-kvm ! NULL若是则拔出适配器。这一查找与判断过程依赖对mdev_list的稳定遍历与 KVM 指针的稳定读取因此必须持有guests_lock。在源码中get_update_locks_by_apqn()正是“持有guests_lock遍历列表、找到 mdev、再取kvm-lock与mdevs_lock”的实现。特例仅访问 KVM 指针而不插拔设备时文档特别澄清了一个容易混淆的点如果访问 KVM 指针的目的不是向客户机插拔直通设备则不必持有 Guests Lock——但此时仍必须持有 Matrix Devices Lock因为matrix_mdev-kvm的赋值与清空是在mdevs_lock保护下完成的。典型案例就是 PQAP(AQIC) 指令拦截处理函数它访问 KVM 指针仅用于设置或清除 IRQ中断资源并不插拔设备因此只需持有matrix_dev-mdevs_lock。源码验证了这一结论——vfio_ap_ops.c 中的handle_pqap只取了mdevs_lock并未获取guests_lock与kvm-lock。PQAP Hook Lock保护 PQAP 拦截回调的读写信号量PQAP Hook Lockpqap_hook_rwsem与前两把互斥锁不同它是一个读写信号量r/w semaphore定义在 s390 架构的 KVM 头文件 arch/s390/include/asm/kvm_host_s390.h 中typedef int (*crypto_hook)(struct kvm_vcpu *vcpu); struct kvm_s390_crypto { ... struct rw_semaphore pqap_hook_rwsem; crypto_hook *pqap_hook; ... };文档中给出的路径为arch/s390/include/asm/kvm_host.h当前内核版本中该结构体实际位于被其包含的arch/s390/include/asm/kvm_host_s390.h。它在 arch/s390/kvm/s390/s390.c 中通过init_rwsem(kvm-arch.crypto.pqap_hook_rwsem)初始化。使用规则pqap_hook_rwsem控制对回调函数指针(*kvm-arch.crypto.pqap_hook)的访问该指针指向“宿主机拦截到 PQAP(AQIC) 指令子功能时”要调用的处理函数写模式下持有当pqap_hook值被设置或清空时驱动注册/注销拦截回调见 vfio_ap_ops.c 的kvm-arch.crypto.pqap_hook matrix_mdev-pqap_hook;与 vfio_ap_ops.c 的清空操作读模式下持有当pqap_hook函数被调用时KVM 侧每次拦截 PQAP 都要先down_read。拦截路径上的锁使用KVM 侧KVM 的 PQAP 拦截处理函数 arch/s390/kvm/s390/priv.c 展示了读锁的用法handle_pqap完成一系列指令合法性校验AP 指令可用性、ECA_APIE、特权级、规格异常、facility 检查等后执行down_read(vcpu-kvm-arch.crypto.pqap_hook_rwsem); if (vcpu-kvm-arch.crypto.pqap_hook) { pqap_hook *vcpu-kvm-arch.crypto.pqap_hook; ret pqap_hook(vcpu); ... } up_read(vcpu-kvm-arch.crypto.pqap_hook_rwsem);若没有 hook 注册即没有 vfio 驱动为 SIE CRYCB 使能、没有队列直通则向客户机返回响应码0x01arch/s390/kvm/s390/priv.c。注意 KVM 侧取得函数指针后最终会调用 vfio_ap 驱动的handle_pqapmatrix_mdev-pqap_hook handle_pqap;见 vfio_ap_ops.c该回调内部再以container_of反解出matrix_mdev并在mdevs_lock保护下按 APQN 查找队列、依据通用寄存器 1 的 IR 位决定vfio_ap_irq_enable()还是vfio_ap_irq_disable()vfio_ap_ops.c。由此形成两层锁分工KVM 的pqap_hook_rwsem保证“回调指针本身”的读写安全vfio_ap 的mdevs_lock保证“回调执行期间访问的队列与 mdev 状态”的互斥。而驱动侧在动态更新 APCB向客户机插入/拔出设备可能同时改动 hook时则按guests_lock → kvm-lock → pqap_hook_rwsem → mdevs_lock的顺序全部取齐get_update_locks_for_kvm确保任何时刻都不会出现“一边改 hook、一边执行 hook”的竞态。四把锁的加锁顺序与死锁防护综合源码与文档vfio_ap 驱动在更新客户机 APCB 时遵循的规范加锁顺序为顺序锁保护对象对应源码1matrix_dev-guests_lockKVM 指针与 mdev 列表结构vfio_ap_ops.c2kvm-lockKVM 客户机状态 / APCBvfio_ap_ops.c3kvm-arch.crypto.pqap_hook_rwsem写PQAP 拦截回调指针vfio_ap_ops.c4matrix_dev-mdevs_lockmatrix_mdev 内全部字段vfio_ap_ops.c解锁顺序严格逆序。这一约定与 KVM 侧handle_pqap的“先down_read(pqap_hook_rwsem)、再在回调里取mdevs_lock”的嵌套方向一致从而避免 ABBA 型死锁。此外矩阵设备锁是访问一切 mdev 字段的底线无论何种路径只要读写matrix_mdev中的字段矩阵位图、KVM 指针、队列表、shadow APCB就必须持有mdevs_lockGuests Lock 与 KVM 锁只在涉及“客户机”时才需要例如仅在“使用 KVM 指针插拔设备”或“遍历 mdev 列表查找直通关系”时持有guests_lock仅在“更新 APCB / 修改 hook”时持有kvm-lock与pqap_hook_rwsem锁序注释即文档vfio_ap_ops.c 与 vfio_ap_ops.c 的函数头注释完整记录了上述顺序是阅读该文件时最直接的索引。总结vfio_ap 设备驱动的安全运行依赖四把职责清晰、顺序严格的锁matrix_dev-mdevs_lock守护全部 mediated device 字段kvm-lock守护客户机 APCB 更新matrix_dev-guests_lock守护 KVM 指针与 mdev 列表遍历kvm-arch.crypto.pqap_hook_rwsem以读写信号量形式保护 PQAP(AQIC) 拦截回调的注册、注销与调用。理解这四把锁的“保护对象—持锁场景—加锁顺序”三层关系是分析 AP 设备直通热插拔、PQAP 拦截中断使能与客户机生命周期管理等路径的正确起点也是在此基础上阅读 vfio_ap_ops.c 其余 2900 余行代码的钥匙。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

STM32G431 BLDC六步换相实战:从Hall信号到PWM波形全链路解析

STM32G431 BLDC六步换相实战:从Hall信号到PWM波形全链路解析

1. 这不是“抄代码”,而是让小白真正看懂BLDC换相逻辑的起点你搜“BLDC 6步换相”时,刷出来的要么是晦涩的数学推导,要么是直接甩出一串HAL库函数调用——连main函数里该先初始化哪个外设都得靠猜;你点开CubeMX教程,满…

2026/9/13 17:55:22 阅读更多 →
BART 详解:基于去噪自编码的序列到序列预训练模型在 unilm/IAD 仓库中的完整实践指南

BART 详解:基于去噪自编码的序列到序列预训练模型在 unilm/IAD 仓库中的完整实践指南

BART 详解:基于去噪自编码的序列到序列预训练模型在 unilm/IAD 仓库中的完整实践指南 【免费下载链接】unilm Large-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities 项目地址: https://gitcode.com/GitHub_Trending/un/unilm …

2026/9/13 17:55:22 阅读更多 →
VS Code+STM32嵌入式开发环境搭建:GCC/CMake/AI编程实战

VS Code+STM32嵌入式开发环境搭建:GCC/CMake/AI编程实战

1. 为什么 VS Code 会成为 STM32 开发的“新标配”1.1 Keil 和 IAR 用得好好的,为什么还要换?先说点实在话。很多干嵌入式三五年的老哥们,电脑里装的最多的就是 Keil MDK 和 IAR。这两个 IDE 不是不能用,而是当你开始尝试把 AI 编…

2026/9/13 17:55:22 阅读更多 →

最新新闻

基于YOLOv8的网球场识别系统:数据集、训练与部署实战

基于YOLOv8的网球场识别系统:数据集、训练与部署实战

简介:面向计算机视觉方向毕业设计或课程设计,提供一套基于YOLOv8的网球场识别系统,功能完整、简单部署即可运行,尤其适合深度学习、目标检测相关专业学生作为毕设或课设基础。资源共97个文件,以70个Python脚本和12个py…

2026/9/13 18:53:48 阅读更多 →
分布式唯一 ID 生成算法:从雪花算法到号段模式的权衡

分布式唯一 ID 生成算法:从雪花算法到号段模式的权衡

分布式唯一 ID 生成算法:从雪花算法到号段模式的权衡 在海量分布式存储、分布式数据库分库分表、以及全链路追踪系统中,分布式全局唯一 ID(Distributed Unique ID Generator) 是所有业务数据实体的物理身份证。 一个理想的分布式…

2026/9/13 18:53:48 阅读更多 →
网易2025年财报分析:多元业务协同与利润增长

网易2025年财报分析:多元业务协同与利润增长

1. 网易2025年财报核心数据解读2025年对网易而言是标志性的一年,全年营业利润达到358亿元,同比增长21%。这个数字背后反映的是网易在游戏、电商、音乐、教育等多元业务的协同发力。作为从业十余年的互联网分析师,我将从业务结构、增长驱动力和…

2026/9/13 18:53:48 阅读更多 →
Linux密码修改无效排查:认证源、缓存与脚本全解析

Linux密码修改无效排查:认证源、缓存与脚本全解析

前几天处理了一个挺典型的账户问题,现象一句话就能说清:某台设备里有个叫ctxsys的系统账户,运维按规范用passwd改了密码,命令也是正常执行完的,但结果完全没影响——用新密码登录被拒,旧密码却能进&#xf…

2026/9/13 18:53:48 阅读更多 →
基于 Google Cloud 语音识别与合成的实战指南:Chirp 3、Gemini TTS 与 Gemini 3.5 Transcribe 全解析

基于 Google Cloud 语音识别与合成的实战指南:Chirp 3、Gemini TTS 与 Gemini 3.5 Transcribe 全解析

基于 Google Cloud 语音识别与合成的实战指南:Chirp 3、Gemini TTS 与 Gemini 3.5 Transcribe 全解析 【免费下载链接】generative-ai Sample code and notebooks for Generative AI on Google Cloud, with Gemini Enterprise Agent Platform 项目地址: https://g…

2026/9/13 18:53:48 阅读更多 →
可编辑生成结果:AI 产出与人工介入协同交互

可编辑生成结果:AI 产出与人工介入协同交互

可编辑生成结果:AI 产出与人工介入协同交互在生成式 AI 工具进入真实企业业务流时,一个普遍的误区是认为“大模型应该一键完成 100% 的工作”。 但在真实的专业创作、代码编写或合同起草场景中,无论模型多么强大,它生成的初稿往往…

2026/9/13 18:52:47 阅读更多 →

日新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/13 0:00:24 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/13 0:00:24 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/13 0:00:24 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/13 0:00:24 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/13 0:00:24 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/13 0:00:24 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/13 16:51:11 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/12 18:29:34 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/12 19:02:44 阅读更多 →