Issue
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
This is @Ian Abbott's comment which is the correct answer.(He doesn't post it as answer so I do)
The system call handler function definitions all start with a macro call of the form SYSCALL_DEFINE0(name), SYSCALL_DEFINE1(name, param1type, param1name), ..., SYSCALL_DEFINE6(name, param1type, param1name, param2type, param2name, param3type, param3name, param4type, param4name, param5type, param5name, param6type, param6name), followed by the function body. For ppoll, look in "fs/select.c" for SYSCALL_DEFINE5(ppoll,.
Answered By - Chan Kim Answer Checked By - Mary Flores (WPSolving Volunteer)