Implementing Original Systemcalls
This is a tutorial of implementing new systemcalls.
System Setup
- Linux kernel 5.8.13
- CPU: x86_64
Step-by-step instructions
Register New Systemcall
Add a new entry in the arch/x86/entry/syscalls/syscall_64.tbl. You can use empty systemcall number and register hello_syscall as follows.
 437	common	openat2			sys_openat2
 438	common	pidfd_getfd		sys_pidfd_getfd
 439	common	faccessat2		sys_faccessat2
+440	common	hello_syscall	sys_hello_syscall
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
Implementing Body of New Systemcall
In this article, I wrote a new systemcall in the my_syscall/ directory. The body of hello_syscall is written in the my_syscalls/my_syscalls.c using SYSCALL_DEFINEk macro as follows. k indicates thw number of arguments.
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include "my_syscall.h"
SYSCALL_DEFINE0(hello_syscall)
{
    printk(KERN_INFO "hello_syscall: Hello world!\n");
    return 0;
}
If the systemcall has some arguments, it could be written as follows.
SYSCALL_DEFINE1(hello_syscall, int, arg)
{
    printk(KERN_INFO "hello_syscall: arg = %d\n", arg);
    return 0;
}
Then create header files (my_syscalls/my_syscalls.h) and modify include/linux/syscalls.h.
asmlinkage long sys_hello_syscall(void);
 asmlinkage long sys_pidfd_send_signal(int pidfd, int sig,
 				       unsigned int flags);
 asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags);
 
+/* my_syscalls/my_syscalls.c */
+asmlinkage long sys_hello_syscall(void);
+
 /*
  * Architecture-specific system calls
  */
Modifying Makefile
First, create my_syscalls/Makefile like this.
obj-y:=my_syscalls.o
Second, modify Makefile to add my_syscalls/ directory to kernel.
core-y		+= kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ my_syscalls/
Compile and Install
make -j8 && make modules_install && make install
grub-mkconfig -o /boot/grub/grub.cfg
reboot
Test
Test program:
#include <stdio.h>
#include <sys/syscall.h>
#define HELLO_SYSCALL   440
int main(int argc, char **argv)
{
    syscall(HELLO_SYSCALL);
    return 0;
}
Result:
user@host ~ $ dmesg -w
...
[  169.128284] hello_syscall: Hello world!