Search code examples
linux-kernelsystem-callsarm64

can't find the definition of __arm64_sys_ppoll function in linux source


I'm trying to boot a development board containing arm64 core using busybox, u-boot and linux-5.10.0-rc5. The boot process is almost complete but when it enters the shell program, it stops shortly after(with no kernel panic). It doesn't even show the '#' prompt (but with qemu model, the image and busybox works ok with normal shell at the end). I could see that before it stops, there are some system calls from the busybox coming to the kernel, and when it stopped, it was processing system call 73.
(You can follow from arch/arm64/kernel/syscall.c, do_el0_svc () -> el0_svc_common -> invoke_syscall -> __invoke_syscall -> syscall_fn By examining the files I could see syscall 73 is sys_ppoll. (in include/uapi/asm-generic/unistd.h). I found in include/uapi/asm-generic/unistd.h,

/* fs/select.c */
#if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32
#define __NR_pselect6 72
__SC_COMP_3264(__NR_pselect6, sys_pselect6_time32, sys_pselect6, compat_sys_pselect6_time32)
#define __NR_ppoll 73
__SC_COMP_3264(__NR_ppoll, sys_ppoll_time32, sys_ppoll, compat_sys_ppoll_time32)
#endif

The definition of __SC_COMP_3264 is at the first lines of the same file. To see what lines are selected and compiled by the #if/#endif macros, I tried adding a characters 'x' to cause compile error and I could see what lines are compiled. That is shown below.

#ifndef __SYSCALL
x                    <---- compile error, so compiled, and __SYSCALL(x,y) defined to be nothing?
#define __SYSCALL(x, y)
#endif

#if __BITS_PER_LONG == 32 || defined(__SYSCALL_COMPAT)
x                     <--------- no compile error, so not compiled
#define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _32)
#else
#define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _64)
#endif

#ifdef __SYSCALL_COMPAT
x                   <-------------- no compile error, so not compiled
#define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _comp)
#define __SC_COMP_3264(_nr, _32, _64, _comp) __SYSCALL(_nr, _comp)
#else
#define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _sys)
#define __SC_COMP_3264(_nr, _32, _64, _comp) __SC_3264(_nr, _32, _64)
#endif

So this means __SYSCALL(x, y) is defined to be doing nothing. But if that was true, all the other syscall would have done nothing and I figured __SYSCALL was defined previously and found in arch/arm64/kernel/sys.c

#undef __SYSCALL
#define __SYSCALL(nr, sym)  asmlinkage long __arm64_##sym(const struct pt_regs *);
#include <asm/unistd.h>

So the function definition becomes __arm64_sys_ppoll and I can see it in the System.map file. But I couldn't find the definition of __arm64_sys_ppoll. Where can I find the source? My another question is, how can below line be compiled and make error when I do make -j28?
#ifndef __SYSCALL x <---- compile error, so compiled, and __SYSCALL(x,y) defined to be nothing? #define __SYSCALL(x, y) #endif

By the way, this is what I see when I grep for sys_ppoll in the source(excluding all non-arm64 arch files).

./include/linux/compat.h:asmlinkage long compat_sys_ppoll_time32(struct pollfd __user *ufds,
./include/linux/compat.h:asmlinkage long compat_sys_ppoll_time64(struct pollfd __user *ufds,
./include/linux/syscalls.h:asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int,
./include/linux/syscalls.h:asmlinkage long sys_ppoll_time32(struct pollfd __user *, unsigned int,
./include/uapi/asm-generic/unistd.h:__SC_COMP_3264(__NR_ppoll, sys_ppoll_time32, sys_ppoll, compat_sys_ppoll_time32)
./include/uapi/asm-generic/unistd.h:__SC_COMP(__NR_ppoll_time64, sys_ppoll, compat_sys_ppoll_time64)
./tools/include/uapi/asm-generic/unistd.h:__SC_COMP_3264(__NR_ppoll, sys_ppoll_time32, sys_ppoll, compat_sys_ppoll_time32)
./tools/include/uapi/asm-generic/unistd.h:__SC_COMP(__NR_ppoll_time64, sys_ppoll, compat_sys_ppoll_time64)
./arch/arm64/include/asm/unistd32.h:__SYSCALL(__NR_ppoll, compat_sys_ppoll_time32)
./arch/arm64/include/asm/unistd32.h:__SYSCALL(__NR_ppoll_time64, compat_sys_ppoll_time64)

Thanks for reading and sorry for the long question.


Solution

  • For SYSCALL_DEFINE0, ..., SYSCALL_DEFINE6, first see @Ian Abbott's comment to my original question.

    In file include/uapi/asm-generic/unistd.h, you can see the syscall definitions.
    For example if you want to see the source code for shmat, you can use grep to see in the file these lines,

    /* ipc/shm.c */
    #define __NR_shmget 194
    __SYSCALL(__NR_shmget, sys_shmget)
    #define __NR_shmctl 195
    __SC_COMP(__NR_shmctl, sys_shmctl, compat_sys_shmctl)
    #define __NR_shmat 196
    __SC_COMP(__NR_shmat, sys_shmat, compat_sys_shmat)
    #define __NR_shmdt 197
    __SYSCALL(__NR_shmdt, sys_shmdt)
    

    So it says the definition is in file ipc/shm.c. There you can see these lines.

    SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)
    {
        unsigned long ret;
        long err;
    
        err = do_shmat(shmid, shmaddr, shmflg, &ret, SHMLBA);
        if (err)
            return err;
        force_successful_syscall_return();
        return (long)ret;
    }
    

    You can see the definition of shmat function with argments list.