Operating Systems

DM510, Spring 2015

Daniel Merkle

Adding a System Call

This document describes how to add a system call to User-mode Linux to 3.18.X kernels, specifically this is based on the 3.18.2 kernel.

Define the entry point

The first thing you need to do is modify the file unistd_64.h in the directory arch/x86/include/generated/uapi/asm/unistd_64.h. In this file, you need to add a line providing an id for your system call. Locate the bunch of lines of the form #define __NR_somename, and add a new entry for your system call.

#define __NR_kexec_file_load 320
#define __NR_bpf 321
#define __NR_hellokernel               322

Next, you must add and entry refering to your call in the system calls table. To do this, modify syscall_64.tbl file in arch/x86/syscalls/ and edit the following colored line:

320     common  kexec_file_load         sys_kexec_file_load
321     common  bpf                     sys_bpf
322     common  hellokernel             sys_hellokernel

Now we will implement a system call.

Implementation code

First of all, create a header file hellokernel.h for your system call and place it in arch/um/include/asm as shown here:

Download: hellokernel.h
#ifndef __UML_HELLOKERNEL_H__
#define __UML_HELLOKERNEL_H__

extern int sys_hellokernel( int );

#endif

Then, write out the implementation hellokernel.c of your system call in arch/um/kernel/ as shown here. (Note the use of the asmlinkage modifier. This macro tells the compiler to pass all function arguments on the stack.):

Download: hellokernel.c
#include "linux/kernel.h"
#include "linux/unistd.h"

asmlinkage
int sys_hellokernel( int flag ) {
  printk("Your kernel greets you %d times! \n", flag);
  return 0;
}

Finally, modify the respective Makefile in arch/um/kernel and add somename.o to the list of build targets.

extra-y := vmlinux.lds
clean-files :=

obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
        physmem.o process.o ptrace.o reboot.o sigio.o \
        signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
        um_arch.o umid.o maccess.o hellokernel.o skas/

Now you have to recompile the kernel. Change to the kernel source root directory and recompile :

cd ~/dm510/linux-3.18.2
make ARCH=um linux

The next step is to use the new system call from a user-space application.

Creating a stub for your system call

You call the new functions as identified by their index through the syscall function. With the syscall function, you can call a system call by specifying. For example, the short application shown below calls your sys_hellokernel using its index. The program can be compiled with the command gcc -o testsystemcall testsystemcall.c.

#include <stdio.h>
#include <errno.h>
#include "arch/x86/include/generated/uapi/asm/unistd_64.h"

int main(int argc, char ** argv) {
	printf("Calling ... \n");
	syscall(__NR_hellokernel,42);
}

Run user mode linux

./linux

Login, and mount your home directory, and change to the directory where your newly compiled program is stored:

mount none /mnt/tmp -t hostfs -o /home/your_imada_login/dm510
cd /mnt/tmp/linux-3.18.2

Execute the program. The result should be similar to the following:

dm510:/mnt/tmp/linux-3.18.2# ./testsyscall 
Calling ... 
Your kernel greets you 42 times! 

Note that the kernel messages are maybe printed in another terminal than the messages that are printed by printf commands of the program. Besides of that, you will find the messages from the kernel in /var/log/kern.log.

Further information can be found here:

  • Kernel command using Linux system calls [html].
  • Adding a System Call to UML [html] (partially outdated).
  • Linux System Call Howto [html]. Note: this is for adding a system call to Linux in general, i.e., slightly different than what you have to do in UML.
  • How System Calls Are Implemented on i386 Architecture: [html].
Design by 1234.info | Modified by Daniel Merkle | CSS 2.0