Adding a System Call
This document describes how to add a system call to User-mode Linux to 3.2.X kernels, specifically this is based on the 3.2.1 kernel.
Define the entry point
The first thing you need to do is modify the
file unistd_32.h
in the directory arch/x86/include/asm/
. 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_process_vm_writev 348 #define __NR_hellokernel 349 #ifdef __KERNEL__ #define NR_syscalls 350
Next, you must add and entry refering to your call in the system calls table. To do this, modify syscall_table_32.S
file in arch/x86/kernel/
and edit the following colored line:
.long sys_process_vm_readv .long sys_process_vm_writev .long 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:
#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.):
#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 init_task.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 uaccess.o \ um_arch.o umid.o hellokernel.o skas/
Now you have to recompile the kernel. Change to the kernel source root directory and recompile :
cd ~/dm510/linux-3.2.1 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/asm/unistd_32.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.2.1
Execute the program. The result should be similar to the following:
dm510:/mnt/tmp/linux-3.2.1# ./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].