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)