Adding system call to UML - Different instructions
Adding a System Call to UML
This document describes how to add a system call to User-mode Linux. The original version was written by Alexandros Karypidis. The version presented here is slightly modified to handle 2.6 kernels, specifically this is based on the 2.6.10 kernel. Furthermore, we use output from diff
to show what to change.
Further information can be found here:
- Adding a System Call to UML [pdf, html]. Note: This is the original version of the document you are looking at now.
- Linux System Call Howto [html (mirror), html (original)]. 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.
Define the entry point
The first thing you need to do is modify the file unistd.h
in include/asm/arch
. 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. Further, you should increment the total number of available system calls as defined by NR_syscalls
.
--- old/include/asm-i386/unistd.h 2005-01-10 09:08:18.000000000 +0100
+++ new/include/asm-i386/unistd.h 2005-03-03 14:33:25.366255000 +0100
@@ -294,8 +294,9 @@
#define __NR_add_key 286
#define __NR_request_key 287
#define __NR_keyctl 288
+#define __NR_somename 289
-#define NR_syscalls 289
+#define NR_syscalls 290
/*
* user-visible error numbers are in the range -1 - -128: see
Next, you must add and entry refering to your call in the system calls table. To do this, modify sys_call_table.c
file in arch/um/kernel
and edit the following lines:
--- old/arch/um/kernel/sys_call_table.c 2005-01-10 09:08:18.000000000 +0100
+++ new/arch/um/kernel/sys_call_table.c 2005-03-03 14:21:00.580270000 +0100
@@ -19,7 +19,7 @@
#define NFSSERVCTL sys_ni_syscall
#endif
-#define LAST_GENERIC_SYSCALL __NR_vserver
+#define LAST_GENERIC_SYSCALL __NR_somename
#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
#define LAST_SYSCALL LAST_GENERIC_SYSCALL
@@ -51,8 +51,12 @@
extern syscall_handler_t old_select;
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_rt_sigsuspend;
+extern syscall_handler_t sys_somename;
syscall_handler_t *sys_call_table[] = {
+ /* The following line ensures that we do not get any problems with */
+ /* undefined system calls. */
+ [ 0 ... LAST_GENERIC_SYSCALL ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall,
[ __NR_exit ] (syscall_handler_t *) sys_exit,
[ __NR_fork ] (syscall_handler_t *) sys_fork,
@@ -306,6 +310,7 @@
[ __NR_utimes ] (syscall_handler_t *) sys_utimes,
[ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64,
[ __NR_vserver ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_somename ] (syscall_handler_t *) sys_somename,
ARCH_SYSCALLS
[ LAST_SYSCALL + 1 ... NR_syscalls ] =
LAST_GENERIC_SYSCALL
must be changed such that your new system call's id is considered to be within the allowable range.
Next, we add a declaration for your system call in the area where all the other system calls are defined.
The line with [ 0 ... LAST_GENERIC_SYSCALL ] = (syscall_handler_t *) sys_ni_syscall,
ensures that system calls which are in the normal kernel, but not in User-mode Linux are defined as not implemented. At least the 2.6.10 kernel are missing more than 10 system calls, and without this change, the kernel could segfault if one of the missing system calls were used.
The last change adds your system call to the system call table, such that it can be called from user space.
Having done all these, an attempt to compile the kernel should fail during linking, as the sys_somename
function must now be implemented.
Implementation code
First of all, create a header file somename.h
for your system call and place it in arch/um/include
as shown here:
/*
* somename.h
*/
#ifndef __UML_SOMENAME_H__
#define __UML_SOMENAME_H__
extern int sys_somename(int flag);
#endif
Then, write out the implementation somename.c
of your system call in arch/um/kernel
as shown here:
/*
* somename.c
*/
#include "linux/kernel.h"
#include "linux/unistd.h"
asmlinkage
int sys_somename(int flag) {
printk("Hello from somename! flag=%d.\n", flag);
return 0;
}
Finally, modify the respective Makefile
in arch/um/kernel
and add somename.o to the list of build targets.
--- old/arch/um/kernel/Makefile 2005-01-10 09:08:18.000000000 +0100
+++ new/arch/um/kernel/Makefile 2005-02-09 15:59:14.185985000 +0100
@@ -9,13 +9,13 @@
obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o physmem.o process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o - um_arch.o umid.o user_util.o
+ um_arch.o umid.o user_util.o somename.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_TTY_LOG) += tty_log.o
Creating a stub for your system call
The listing below shows a program which uses the _syscall
macro to create a stub for the system call. It then proceeds to call the stub function. When compiling, be sure to specify the -I option so that gcc will look at the modified version of unistd.h
. In the example, the preprocessor looks for the file in asm/arch/unistd.h
, so if the UML code is in the directory /uml-code
you should compile with -I/uml-code/include
.
/*
* test_somename.c
*
* Note: should be compiled with:
* gcc -I path.to.kernel.tree/linux-2.6.10/include -o test_somename test_somename.c
*/
#include
#include
#include "asm/arch/unistd.h"
_syscall1(int, somename, int, flag);
int main(int argc, char** argv) {
printf("Calling...\n");
somename(1);
}
0 Comments:
Post a Comment
<< Home