1. GPU Page Fault 处理机制概述
在Intel Xe架构的GPU驱动中,Page Fault处理是一个关键的内存管理机制。当GPU尝试访问一个无效或受保护的虚拟内存地址时,就会触发Page Fault异常。与CPU端的Page Fault类似,GPU端的Page Fault处理也需要经历异常检测、上下文保存、错误处理以及恢复执行等步骤。
Xe驱动中的Page Fault处理路径主要分为以下几个阶段:
- 硬件检测到非法内存访问并触发中断
- 驱动中断服务例程(ISR)捕获异常
- 分析故障地址和访问类型
- 执行适当的补救措施(如分配物理页或迁移内存)
- 恢复GPU执行上下文
这个机制对于实现GPU内存的按需分配、内存迁移和错误隔离至关重要。特别是在共享虚拟内存(SVM)场景下,GPU和CPU可能访问相同的虚拟地址空间,Page Fault处理更是保证系统稳定性的关键。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Xe驱动中的Page Fault处理路径
2.1 中断入口点处理
当GPU触发Page Fault时,首先会通过PCIe MSI中断通知系统。在Xe驱动中,这个中断的处理入口通常定义在xe_gpu_fault.c文件中:
c复制irqreturn_t xe_gpu_fault_handler(int irq, void *arg)
{
struct xe_device *xe = arg;
u32 fault_status;
/* 读取GPU故障状态寄存器 */
fault_status = XE_READ(xe, FAULT_STATUS_REG);
if (!(fault_status & FAULT_VALID_BIT))
return IRQ_NONE;
/* 检查是否为Page Fault类型 */
if (fault_status & FAULT_TYPE_PAGE) {
handle_page_fault(xe, fault_status);
}
/* 清除中断状态 */
XE_WRITE(xe, FAULT_STATUS_REG, fault_status);
return IRQ_HANDLED;
}
这个中断处理程序首先验证中断有效性,然后根据故障类型分发到具体的处理函数。对于Page Fault,会调用handle_page_fault()进行进一步处理。
2.2 故障地址和上下文提取
在handle_page_fault()函数中,驱动需要收集更多关于故障的详细信息:
c复制static void handle_page_fault(struct xe_device *xe, u32 fault_status)
{
struct xe_fault_info info = {0};
u64 fault_addr;
/* 读取故障地址寄存器 */
fault_addr = XE_READ64(xe, FAULT_ADDR_REG);
info.address = fault_addr & PAGE_MASK;
/* 解析访问类型 */
info.access_type = (fault_status & FAULT_ACCESS_MASK) >> FAULT_ACCESS_SHIFT;
/* 获取触发故障的GPU上下文 */
info.context_id = XE_READ(xe, FAULT_CONTEXT_REG);
/* 获取进程信息 */
info.pid = get_context_pid(xe, info.context_id);
/* 继续处理Page Fault */
process_page_fault(xe, &info);
}
这里收集的信息包括:
- 触发故障的虚拟地址(页对齐)
- 访问类型(读/写/执行)
- 触发故障的GPU上下文ID
- 关联的进程PID
这些信息对于后续的故障处理决策至关重要。
3. Page Fault的核心处理逻辑
3.1 虚拟地址空间查找
process_page_fault()函数开始实际的故障处理:
c复制static void process_page_fault(struct xe_device *xe, struct xe_fault_info *info)
{
struct xe_vm *vm;
struct xe_bo *bo;
int ret;
/* 根据上下文ID找到对应的地址空间 */
vm = find_vm_by_context(xe, info->context_id);
if (!vm) {
pr_err("Failed to find VM for context %u\n", info->context
