为什么在TRACE_IRQS_OFF之前将rax设置为-ENOSYS

问题描述 投票:0回答:1

请参见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个回答
0
投票

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

设置为-ENOSYS的是RAX在堆栈上的保存值。即,宏不保存RAX的实际值,而是保存-ENOSYS。当系统调用返回时,除非-ENOSYS将其更改为其他值,否则RAX中的值将设置为do_syscall_64。如果输入的RAX值不是有效的系统调用号码,则可以这样做,因此do_syscall_64可以简单地返回,而输出的RAX将为-ENOSYS,表明系统调用无效。

© www.soinside.com 2019 - 2024. All rights reserved.