【问题标题】:Why rax is set to -ENOSYS before TRACE_IRQS_OFF为什么在 TRACE_IRQS_OFF 之前将 rax 设置为 -ENOSYS
【发布时间】:2020-02-20 22:54:08
【问题描述】:

https://elixir.bootlin.com/linux/v5.0.21/source/arch/x86/entry/entry_64.S#L168

  1. 为什么必须改变 RAX?
  2. 为什么选择 -ENOSYS?

从上面的链接复制:

ENTRY(entry_SYSCALL_64)
    UNWIND_HINT_EMPTY
    /*
     * Interrupts are off on entry.
     * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
     * it is too small to ever cause noticeable irq latency.
     */

    swapgs
    /* tss.sp2 is scratch space. */
    movq    %rsp, PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
    SWITCH_TO_KERNEL_CR3 scratch_reg=%rsp
    movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp

    /* Construct struct pt_regs on stack */
    pushq   $__USER_DS              /* pt_regs->ss */
    pushq   PER_CPU_VAR(cpu_tss_rw + TSS_sp2)   /* pt_regs->sp */
    pushq   %r11                    /* pt_regs->flags */
    pushq   $__USER_CS              /* pt_regs->cs */
    pushq   %rcx                    /* pt_regs->ip */
GLOBAL(entry_SYSCALL_64_after_hwframe)
    pushq   %rax                    /* pt_regs->orig_ax */

    PUSH_AND_CLEAR_REGS rax=$-ENOSYS

    TRACE_IRQS_OFF
...

【问题讨论】:

    标签: assembly linux-kernel x86-64


    【解决方案1】:

    PUSH_AND_CLEAR_REGS 的调用不会改变 RAX。事实上,它是少数未被宏清除(设置为 0)的通用寄存器之一。由于 RAX 保存正在调用的系统调用的系统调用号,因此它的值保持不变。在您显示的代码之后,它立即作为第一个参数传递给do_syscall_64

    设置为-ENOSYS 的是RAX 在堆栈上的保存值。也就是说,宏不保存 RAX 的实际值,而是保存-ENOSYS。当系统调用返回时,RAX 中的值将设置为-ENOSYS,除非do_syscall_64 将其更改为其他值。这大概是这样做的,如果传入的 RAX 值不是有效的系统调用号,do_syscall_64 可以简单地返回,而传出的 RAX 将是-ENOSYS,表示系统调用无效。

    【讨论】:

      猜你喜欢
      • 2019-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-12
      • 2011-08-12
      • 1970-01-01
      • 1970-01-01
      • 2021-06-17
      相关资源
      最近更新 更多