ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

fault exc_page_fault

fault exc_page_fault DEFINE_IDTENTRY_RAW_ERRORCODE是 Linux 内核 x86 架构中用于定义原始异常入口函数的宏它封装了硬件异常处理入口的底层汇编粘合逻辑使开发者能直接编写 C 语言处理函数。宏的核心作用这个宏展开后会定义一个带有struct pt_regs *regs和unsigned long error_code参数的函数并自动生成对应的汇编入口代码。它的关键特性是“原始”RAW调用者不会自动执行idtentry_enter/exit()辅助函数这意味着中断是禁用的且需要调用者在函数体内自行处理进入/退出逻辑。宏定义与展开#define DEFINE_IDTENTRY_RAW_ERRORCODE(func) \ __visible noinstr void func(struct pt_regs *regs, \ unsigned long error_code)关键属性说明__visible确保符号对汇编代码可见因为汇编入口桩需要跳转到这个函数。noinstr禁止在函数中插入任何插桩代码如 kprobe、ftrace因为此时内核环境尚未完全就绪。与exc_page_fault的关系exc_page_fault正是通过这个宏定义的DEFINE_IDTENTRY_RAW_ERRORCODE(exc_page_fault)它在arch/x86/include/asm/idtentry.h中通过DECLARE_IDTENTRY_RAW_ERRORCODE(X86_TRAP_PF, exc_page_fault)声明。当 CPU 触发缺页异常向量 14时硬件会将错误码压栈然后跳转到汇编入口桩汇编桩再调用exc_page_fault。为什么缺页异常需要 “RAW” 模式缺页异常的处理路径非常特殊需要访问用户内存处理缺页时可能需要读取用户态指令如is_prefetch检测而标准的idtentry_enter()会改变某些状态可能干扰这一过程。中断状态敏感缺页处理中需要精确控制中断的启用/禁用时机因此不能由宏自动处理。FRED 兼容性在支持 FREDFlexible Return and Event Delivery的新架构上exc_page_fault会被替换为fred_exc_page_fault但两者最终都调用相同的page_fault_common逻辑。调用链概览CPU 触发缺页异常 (向量 14) ↓ 汇编入口桩 (asm_exc_page_fault) ↓ DEFINE_IDTENTRY_RAW_ERRORCODE(exc_page_fault) ↓ page_fault_common(regs, error_code, read_cr2()) ↓ handle_page_fault() 或 do_user_addr_fault() / do_kern_addr_fault()read_cr2()用于获取触发异常的地址因为缺页异常的错误码中不包含地址信息必须从 CR2 寄存器读取。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进