Windows驱动调试(三):BSOD 0xCA PNP_DETECTED_FATAL_ERROR IOMMU问题分析

Windows 驱动调试(三):BSOD 0xCA PNP_DETECTED_FATAL_ERROR IOMMU 问题分析

日期: 2026-03-21
问题编号: BSOD 0xCA
影响设备: Bayhub SD Host Controller (PCI\VEN_1217&DEV_8621)
驱动服务: bhtsddr
状态: ✅ 已分析


1. 问题概述

1.1 问题现象

在 Windows 系统启动过程中,设备初始化阶段发生蓝屏死机 (BSOD),错误码为 0xCA (PNP_DETECTED_FATAL_ERROR)。

1.2 关键信息

项目 值 说明
BSOD 代码 0xCA PNP_DETECTED_FATAL_ERROR
Arg1 0x13 IOMMU operation failure
Arg2 0x1000 Unblock operation
Arg3 0xFFFFFFFFC0350066 NT Status Code
Arg4 0xFFFFB986629AFC40 DevNode 地址
设备路径 PCI\VEN_1217&DEV_8621 Bayhub SD Host Controller
服务名 bhtsddr Bayhub Storage Driver

1.3 系统环境

项目 值
OS 版本 Windows 10 (10.0.26100.1)
架构 x64
虚拟化 Hyper-V 已启用
HVCI SecureKernel.HalpHvciEnabled = 1

2. BSOD 0xCA 错误码解析

2.1 错误定义

1
2
3
4
PNP_DETECTED_FATAL_ERROR (ca)
PnP encountered a severe error, either as a result of a problem in a driver or
a problem in PnP itself. The first argument describes the nature of the problem,
the second argument is the address of the PDO.

2.2 参数详解

参数 值 含义
Arg1 0x13 (19) IOMMU operation failure - IOMMU 操作失败
Arg2 0x1000 Unblock operation - 解封操作
Arg3 0xFFFFFFFFC0350066 NT Status Code (具体错误码)
Arg4 0xFFFFB986629AFC40 DevNode 对象地址

2.3 故障函数

项目 值
BUCKET_ID 0xCA_13_nt!PiDmaGuardProcessPreStart
函数偏移 +0x10A7F6
模块 nt (ntkrnlmp.exe)

3. 设备状态分析

3.1 DevNode 状态

1
2
3
4
5
6
7
8
!devnode 输出:
DevNode 0xffffb986629afc40 for PDO 0xffffb98665085060
Parent 0xffffb986629adc40
Sibling 0000000000
Child 0000000000

Instance Path: PCI\VEN_1217&DEV_8621&SUBSYS_00021217&REV_01\4&32cd076f&0&0013
Service Name: bhtsddr

3.2 设备状态转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌─────────────────────────────────────────────────────────────────────┐
│ Device State Transitions │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ StateHistory[00] = DeviceNodeUninitialized (0x301) │
│ │ │
│ ▼ │
│ StateHistory[01] = DeviceNodeInitialized (0x304) │
│ │ │
│ ▼ │
│ StateHistory[02] = DeviceNodeDriversAdded (0x305) ← ⚠️ 上一个状态 │
│ │ │
│ ▼ │
│ Current State = DeviceNodeResourcesAssigned (0x306) ← 💥 崩溃发生 │
│ │ │
│ ▼ │
│ 💥 BSOD 0xCA │
│ │
└─────────────────────────────────────────────────────────────────────┘

3.3 状态说明

状态码 状态名 说明
0x301 DeviceNodeUninitialized 未初始化
0x304 DeviceNodeInitialized 已初始化
0x305 DeviceNodeDriversAdded 驱动已添加
0x306 DeviceNodeResourcesAssigned 资源已分配 ← 崩溃发生

4. 内核堆栈分析

4.1 完整调用堆栈

1
2
3
4
5
6
7
8
ffffdf84`8a6b7158 fffff801`9c8e5bca : nt!KeBugCheckEx
ffffdf84`8a6b7160 fffff801`9c7db310 : nt!PiDmaGuardProcessPreStart+0x10a7f6
ffffdf84`8a6b71a0 fffff801`9c697621 : nt!PipProcessStartPhase1+0x4c
ffffdf84`8a6b71e0 fffff801`9c8187a7 : nt!PiProcessDevNodeTree+0x645
ffffdf84`8a6b72b0 fffff801`9c2404bd : nt!PiProcessReenumeration+0x9f
ffffdf84`8a6b7300 fffff801`9c1249d2 : nt!PnpDeviceActionWorker+0x63d
ffffdf84`8a6b73c0 fffff801`9c25a9ea : nt!ExpWorkerThread+0x1b2
ffffdf84`8a6b7570 fffff801`9c4736f4 : nt!PspSystemThreadStartup+0x5a

4.2 堆栈解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ExpWorkerThread                    ← 系统工作线程
│
▼
PnpDeviceActionWorker ← PnP 设备操作工作线程
│
▼
PiProcessReenumeration ← 设备重新枚举
│
▼
PiProcessDevNodeTree ← 处理设备节点树
│
▼
PipProcessStartPhase1 ← 设备启动阶段1
│
▼
PiDmaGuardProcessPreStart ← ⚠️ DMA Guard 处理
│
▼
KeBugCheckEx ← 💥 系统崩溃

4.3 关键函数分析

函数 作用 说明
PiDmaGuardProcessPreStart DMA Guard 预启动处理 IOMMU/DMA 相关检查失败
PipProcessStartPhase1 PnP 启动阶段1 设备启动的第一个阶段
PiProcessDevNodeTree 处理设备节点树 遍历并处理设备树
PnpDeviceActionWorker PnP 设备操作工作线程 系统工作线程处理 PnP 请求

5. 根因分析

5.1 问题本质

IOMMU 操作失败发生在设备启动阶段,具体为 DMA Guard (DMA 保护) 机制检测到问题。

5.2 DMA Guard 机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌─────────────────────────────────────────────────────────────────────┐
│ DMA Guard (Kernel DMA Protection) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ DMA Guard 是 Windows Kernel DMA Protection 的一部分: │
│ │
│ 1. 当设备声明 DmaRemappingCompatible 时触发 │
│ 2. PnP 启动阶段会调用 PiDmaGuardProcessPreStart 进行检查 │
│ 3. 如果设备 DMA 配置有问题,系统直接 BSOD │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ PiDmaGuardProcessPreStart 失败原因: │ │
│ │ │ │
│ │ - 设备有未完成的 DMA 操作 │ │
│ │ - DMA 映射配置不正确 │ │
│ │ - 设备状态不一致 (D3/D0 转换期间有挂起的 I/O) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

5.3 具体问题

根据分析报告:

设备进入 D3/D0 以前需要 Complete 所有 I/O 请求(SRB),使用 Storport miniport 要求的 API

问题:

  • 在电源状态转换(D3↔D0)期间
  • 驱动没有正确完成所有挂起的 I/O 请求
  • 导致 DMA Guard 检测到设备仍有活动状态
  • IOMMU 操作失败,触发 BSOD 0xCA

5.4 NT Status Code 分析

Status Code 含义 可能原因
0xFFFFFFFFC0350066 IOMMU 操作失败 DMA 映射/解除映射失败
高位标志 客户定义状态 内部错误码

6. 解决方案

6.1 推荐的代码修改

核心原则: 在设备进入 D3/D0 电源状态前,必须完成所有挂起的 I/O 请求 (SRB)。

6.2 电源状态转换流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
┌─────────────────────────────────────────────────────────────────────┐
│ D0 → D3 电源转换流程 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ [设备运行中 - D0 状态] │
│ │ │
│ │ 收到 D3 请求 │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. Complete 所有挂起的 SRB │ │
│ │ ✓ StorPortNotification(RequestComplete, ...) │ │
│ │ ✗ 不使用 ScsiPortNotification(RequestComplete, ...) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 2. 等待所有 DMA 操作完成 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 3. 释放 DMA 资源 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ [设备低功耗 - D3 状态] │
│ │
└─────────────────────────────────────────────────────────────────────┘

6.3 API 使用注意事项

API 推荐度 说明
StorPortNotification(RequestComplete, ...) ✅ 推荐 Storport 官方推荐的 API
ScsiPortNotification(RequestComplete, ...) ❌ 不推荐 旧式 API,Storport 不推荐

Microsoft 官方说明:
“We do not recommend that writers of Storport miniport drivers use this particular Storport interface routine. Instead, the miniport driver should call StorPortNotification(RequestComplete) for each outstanding request.”

6.4 代码修改示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 电源状态转换前的 SRB 完成处理
void complete_all_pending_srbs(bht_dev_ext_t *pdx)
{
// 确保所有挂起的 SRB 都被完成
// 使用正确的 Storport API

// 遍历挂起的请求列表
for (int i = 0; i < MAX_PENDING_REQUESTS; i++) {
if (pending_srb[i] != NULL) {
// ✅ 使用正确的 API
StorPortNotification(RequestComplete, pdx, pending_srb[i]);
pending_srb[i] = NULL;
}
}
}

// D3 进入前调用
void enter_d3(bht_dev_ext_t *pdx)
{
// 1. 完成所有 SRB
complete_all_pending_srbs(pdx);

// 2. 等待 DMA 操作完成
wait_for_dma_completion(pdx);

// 3. 停止 DMA 引擎
stop_dma_engine(pdx);
}

7. Hyper-V 虚拟化环境影响

7.1 环境特征

从转储文件分析,系统运行在 Hyper-V 虚拟化环境:

1
2
3
Key : Hypervisor.Flags.AnyHypervisorPresent = 1
Key : Hypervisor.RootFlags.IsHyperV = 1
Key : SecureKernel.HalpHvciEnabled = 1

7.2 IOMMU 在虚拟化中的角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌─────────────────────────────────────────────────────────────────────┐
│ Hyper-V 环境中的 IOMMU │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Guest VM │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Bayhub SD Host Driver (bhtsddr.sys) │ │
│ │ │ │ │
│ │ ▼ DMA │ │
│ │ Virtual IOMMU (vIOMMU) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Hyper-V Hypervisor │
│ │ │
│ ▼ │
│ Physical IOMMU (pIOMMU / VT-d) │
│ │
└─────────────────────────────────────────────────────────────────────┘

7.3 DMA Guard 双重检查

在虚拟化环境中,DMA Guard 面临双重检查:

  1. Guest OS 级别: Windows PnP Manager
  2. Hypervisor 级别: Hyper-V DMA Guard

如果任一级别发现问题,都会触发 BSOD。


8. 与 BSOD 0xA 的对比

8.1 问题类型对比

项目 BSOD 0xA BSOD 0xCA
错误码 IRQL_NOT_LESS_OR_EQUAL PNP_DETECTED_FATAL_ERROR
问题类型 空指针访问 IOMMU 操作失败
发生阶段 驱动初始化 PnP 启动
根因 线程/事件初始化顺序 DMA/IOMMU 状态检查
设备状态 初始化中 ResourcesAssigned

8.2 问题关联

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌─────────────────────────────────────────────────────────────────────┐
│ 两个 BSOD 都与 DMA/IOMMU 相关 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ BSOD 0xA │
│ ├── 问题: Notify 线程空指针访问 │
│ └── 相关: Storport 框架事件同步 │
│ │
│ BSOD 0xCA │
│ ├── 问题: DMA Guard IOMMU 检查失败 │
│ └── 相关: 电源状态转换时的 SRB 完成 │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 共同点: │ │
│ │ - 都涉及 Storport Miniport 驱动 │ │
│ │ - 都发生在设备初始化/电源管理阶段 │ │
│ │ - 都与 DMA/IOMMU 配置相关 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

9. 调试检查清单

9.1 BSOD 0xCA 调试步骤

步骤 检查项 命令/方法
1 确认 BSOD 类型 !analyze -v
2 解析参数 检查 Arg1=0x13 表示 IOMMU 失败
3 定位设备 !devnode <Arg4>
4 分析堆栈 k 查看 PiDmaGuardProcessPreStart
5 检查设备状态 查看 StateHistory
6 分析 NT Status Arg3 的具体含义

9.2 代码审查检查表

  • 电源状态转换前是否完成所有 SRB
  • 是否使用 StorPortNotification 而非 ScsiPortNotification
  • DMA 资源是否正确释放
  • IOMMU 映射是否正确管理
  • 是否有未处理的挂起 I/O

10. 总结

10.1 问题回顾

项目 说明
BSOD 代码 0xCA (PNP_DETECTED_FATAL_ERROR)
Arg1 0x13 (IOMMU operation failure)
根因 DMA Guard 检测到 IOMMU 操作失败
触发点 PiDmaGuardProcessPreStart
设备状态 DeviceNodeResourcesAssigned → 崩溃

10.2 解决方案

  1. 电源状态转换前完成所有 SRB
  2. 使用正确的 Storport API
  3. 确保 DMA/IOMMU 状态一致

10.3 经验教训

  1. 电源管理是关键: D3/D0 转换期间的状态管理至关重要
  2. API 选择重要: Storport 必须使用 StorPortNotification 而非 ScsiPortNotification
  3. 虚拟化环境更严格: Hyper-V + DMA Guard 组合对驱动要求更高

参考资料

  1. Bug Check 0xCA: PNP_DETECTED_FATAL_ERROR
  2. Kernel DMA Protection
  3. StorPortNotification
  4. Device Power States

文档生成日期: 2026-03-21
问题编号: BSOD 0xCA
设备: PCI\VEN_1217&DEV_8621 (bhtsddr)