The fastest Linux system call

On an Intel x86-64 system that supports syscalland sysretwhat is the fastest of the system calls from the 64-bit vanilla kernel user code?

In particular, it must be a system call that uses the syscall/ sysretuser transition of kernel 1 but does the least amount of work outside. This does not even need to be done by syscall itself: some early error that never goes to a specific call on the kernel side is fine if it doesn’t cause some kind of slow path.

Such a call can be used to evaluate raw resources syscalland sysretregardless of any work performed by the call.


1 In particular, this eliminates things that appear to be system calls but are implemented in VDSO (for example clock_gettime) or cached by the runtime (for example getpid).

+6
source share
4 answers

One that does not exist and therefore quickly returns -ENOSYS.

From arch / x86 / entry / entry_64.S:

#if __SYSCALL_MASK == ~0
    cmpq    $__NR_syscall_max, %rax
#else
    andl    $__SYSCALL_MASK, %eax
    cmpl    $__NR_syscall_max, %eax
#endif
    ja  1f              /* return -ENOSYS (already in pt_regs->ax) */
    movq    %r10, %rcx

    /*
     * This call instruction is handled specially in stub_ptregs_64.
     * It might end up jumping to the slow path.  If it jumps, RAX
     * and all argument registers are clobbered.
     */
#ifdef CONFIG_RETPOLINE
    movq    sys_call_table(, %rax, 8), %rax
    call    __x86_indirect_thunk_rax
#else
    call    *sys_call_table(, %rax, 8)
#endif
.Lentry_SYSCALL_64_after_fastpath_call:

    movq    %rax, RAX(%rsp)
1:
+8
source

Use an invalid system call number so that the send code is simply returned using eax = -ENOSYSinstead of sending the system call processing functions at all.

, ​​ iret sysret/sysexit. , , 17 , syscall(SYS_getpid), glibc ( errno), , . , sysret -ENOSYS.


sysenter, syscall. sysenter/sysret ( , sysexit sysenter, sysret syscall). sysenter 32- x86-64.

64- syscall . (, Meltdown/Spectre, - C do_syscall_64 4.16-rc2).


My , 32- int 0x80 Linux ABI 64- ? Q & A - ​​x86-64 (entry_64_compat.S). .

, Linux 4.12, Meltdown, .

int 0x80 sysenter . entry_SYSENTER_compat. AFAIK, sysenter , 64- . Linux __USER32_CS CS, 32- .

, struct pt_regs , TRACE_IRQS_OFF ( , ), call do_fast_syscall_32, C. ( 64- syscall asm, 32- C).

do_syscall_32_irqs_on arch/x86/entry/common.c : , ( , strace ptrace),

   ...
    if (likely(nr < IA32_NR_syscalls)) {
        regs->ax = ia32_sys_call_table[nr]( ... arg );
    }

    syscall_return_slowpath(regs);
}

AFAIK, ​​ sysexit .

, , , EAX , , , - , Spectre, .

sysenter/sysexit , Linux, , / .

, ABI, (, syscall ) , Linux sysenter ABI; get_user() EIP, .


, , eax, -ENOSYS; , - 32- .

+4

user-> , vdso (7).

, VDSO (, time (2) ,...) . , "" .

, (, - , 0, hello world, . ) .

( ), getpid (2) , , , . AFAIK, , VDSO. syscall (2), , libc .

( ): . , syscall (2), getpid, ( , ). , getpid ( getppid).

+2

( , ) close(999) ( - fd ).

+2

Source: https://habr.com/ru/post/1693943/


All Articles