`entry_SYSCALL64_slow_path` 和 `entry_SYSCALL64_fast_path` 的区别

The difference between `entry_SYSCALL64_slow_path` and `entry_SYSCALL64_fast_path`

我们知道系统调用会调用entry_64.S中的函数entry_SYSCALL_64。看源码的时候,发现寄存器准备后的调用有两种,一种是entry_SYSCALL64_slow_path,一种是entry_SYSCALL64_fast_path。你能说出这两个函数的区别吗?

进入 entry_SYSCALL_64 Linux 将:

  1. 交换 gs 以获得每个 cpu 参数。
  2. 根据上面的参数设置堆栈。
  3. 禁用 IRQ。
  4. 在堆栈上创建一个partial pt_regs结构。这会保存调用方上下文。
  5. 如果当前任务设置了_TIF_WORK_SYSCALL_ENTRY_TIF_ALLWORK_MASK,则进入慢路径
  6. 否则请输入快速路径

_TIF_WORK_SYSCALL_ENTRY 被定义为 here,注释说明:

/*
 * work to do in syscall_trace_enter().  Also includes TIF_NOHZ for
 * enter_from_user_mode()
 */

_TIF_ALLWORK_MASK 似乎没有为 x86 定义,MIPS 的定义是 here,注释为:

/* work to do on any return to u-space */

快速路径

Linux 将:

  1. 启用 IRQ。
  2. 检查系统调用号是否超出范围(注意 pt_regs 结构已经用 ENOSYSrax 的值创建)。
  3. 通过间接跳转调度到系统调用。
  4. 将系统调用的 return 值 (rax) 保存到堆栈上 pt_regs 中的 rax
  5. 再次检查当前任务是否设置了_TIF_ALLWORK_MASK,如果是则跳转到慢return路径.
  6. 恢复调用方上下文并发出 sysret

慢 return 路径

  1. 将之前没有保存的寄存器保存在pt_regs中(rbx,rbp,r12-r15).
  2. 调用syscall_return_slowpath,定义here.

请注意,第 2 点最终会调用 trace_sys_exit

慢路径

  1. 将之前没有保存的寄存器保存在pt_regs中(见上文)
  2. 调用do_syscall_64,定义here

点 2 将调用 syscall_trace_enter


所以慢速与快速路径与 ptrace 有关。我没有深入研究代码,但我想如果调用者不需要 ptrace,则整个机器都会被跳过。
这确实是一个重要的优化。