Operating-System Kernels

the syscall fast path (syscall/sysret)

/ SIS-call /

A system call is how a user program asks the kernel to do something it is not privileged to do itself - read a file, send on a socket, create a process. But crossing from unprivileged user mode into the privileged kernel is not free; it requires switching privilege, finding the entry point, and saving state. Because programs make millions of system calls, CPUs added a dedicated, streamlined route for this crossing: a single fast instruction to get in (syscall) and a matching one to get back out (sysret). This pair is the syscall fast path - the optimized highway between user space and the kernel.

Here is what happens, simplified for x86-64. The program puts the system call's number in a register (rax) and its arguments in agreed-upon registers (rdi, rsi, rdx, and so on - this is the syscall calling convention), then executes the syscall instruction. The CPU, in one step, switches to privileged mode and jumps to a kernel entry point that was registered ahead of time (the kernel writes the entry address into a special register at boot). The kernel entry code saves the user registers, uses the number in rax to index the system-call table and call the right handler, then puts the result in rax and executes sysret, which atomically drops back to user privilege and resumes the program right after the syscall instruction. The 'fast' in fast path is the contrast with the older, slower way of entering the kernel via a software interrupt (int 0x80 on 32-bit), which did far more bookkeeping.

Why it matters: the cost of a system call is dominated by this boundary crossing, not just the work inside, which is why reducing the number of system calls (batching with writev, using io_uring) can speed real programs up dramatically. It also clarifies a common misconception: a 'system call' like read() is not an ordinary function call into a library - it is a controlled transition into a different privilege domain through this hardware mechanism, which is exactly why it can do things your own code cannot.

user: mov rax, 1 (write); set rdi/rsi/rdx args; 'syscall' -> CPU enters kernel entry point, saves regs, calls sys_write via the syscall table, sets rax = bytes written, 'sysret' -> back in user mode just past the syscall.

syscall enters the kernel in one fast step; sysret returns. The number in rax selects the handler via the syscall table.

A system call is NOT a normal function call - it is a privilege transition through dedicated hardware (syscall/sysret), which is why it costs far more than calling a local function. That fixed boundary cost, not the work inside, is why batching system calls or using io_uring matters for performance.

Also called
syscall instructionfast system callsyscall/sysret系統呼叫快路徑