md.jamal
md.jamal

Reputation: 4567

asmlinkage defined to nothing in Linux code

I was looking into asmlinkage tag.

From https://kernelnewbies.org/FAQ/asmlinkage

This is a #define for some gcc magic that tells the compiler that the function should not expect to find any of its arguments in registers (a common optimization), but only on the CPU's stack.

Looking into definition, it is defined to empty for x86_64:

#ifdef __cplusplus
#define CPP_ASMLINKAGE extern "C"
#else
#define CPP_ASMLINKAGE
#endif

#ifndef asmlinkage
#define asmlinkage CPP_ASMLINKAGE
#endif

Also, I read that the ABI spec says that we should place system call number in a register, and parameters in some other registers.

Then why we are looking for function parameters in stack. Is system call number also placed in stack?

Upvotes: 2

Views: 488

Answers (2)

Andrew Atrens
Andrew Atrens

Reputation: 509

System calls are not part of your userland program nor shared libraries, they are system services provided by the kernel and are executed in kernel space .. in order to move from user space to kernel space one needs to execute a few special assembly instructions to tell the processor to jump into supervisor mode and before that it will want to push a few bits of information in registers so that the kernel side knows what system call to execute - it has a table of function pointers which point to the various functions that 'service' each system call) -

#include "SYS.h"

ENTRY(syscall)
        pop     %ecx    /* rta */
        pop     %eax    /* syscall number */
        push    %ecx
        KERNCALL
        push    %ecx    /* need to push a word to keep stack frame intact
                           upon return; the word must be the return address. */
        jb      1f
        ret

where KERNCALL is architecture-dependent and is a few assembly language instructions that tell the cpu to jump into supervisor mode in kernel space -

./lib/libc/amd64/SYS.h:#define  KERNCALL    movq %rcx, %r10; syscall
./lib/libc/i386/SYS.h:#define   KERNCALL    int $0x80

So here's the thing .. when you compile a program the optimizer will occasionally throw a function's parameters in registers instead of putting them on the program's stack .. this optimization works because the compiler is emitting code for both the caller and the callee and so both sides are made aware of this slight-of-hand. Not so for the kernel however .. it has no idea what to look for in which register and so all parameters intended for a system call must be on the userland program's stack.

Upvotes: 3

Zig Razor
Zig Razor

Reputation: 3533

asmlinkage tells your compiler to look on the CPU stack for the function parameters, instead of registers

In fact, it uses GCC's regparam attribute (Function-Attributes), or syscall_linkage for IA64:

#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))

But your question is why this is necessary. System calls are services that userspace can call to request the kernel to perform something for them (and therefore execute in kernel space). These functions are quite unorthodox in the sense that you cannot expect them to behave like normal functions, where parameters are typically passed by writing to the program stack, but instead they are written to registers. While still in userspace, calling a syscall requires writing certain values to certain registers is translated. The system call number will always be written in eax, while the the rest of the parameters will go into ebx, ecx, etc. Now when a software interrupt occurs the CPU switches to kernel mode, to then execute system_call(). When the CPU switches to kernel mode it starts by saving all the registers in the CPU stack (eax, ebx, ecx, etc). After checking other things such as validating parameters, it will call the respective system call if everything is in order.So, since all the information about the parameters passed all the way from userspace to this point is nicely stored in the stack, the compiler must be instructed about this, hence the asmlinkage.

Another reason is that anyhow the kernel needs to save all the registers onto stack (in order to restore the environment before returning to the userspace) when handling the system call requests from userspace, so after that the parameters are available on stack, it doesn't need extra effort.

Upvotes: 2

Related Questions