oreilly.comSafari Books Online.Conferences.


Linux Compatibility on BSD for the PPC Platform
Pages: 1, 2, 3, 4

Translating syscalls

For this step, we will need the kernel sources of both NetBSD and Linux. NetBSD kernel sources can be found here, but if you plan to actually work on the kernel sources, you would do better using CVS (see the documentation to learn how to use CVS to track NetBSD-current). You can also browse the source files using CVSWeb.

Linux sources can be found on various FTP sites, for example, for the 2.4 kernel. Grab the latest kernel, which will certainly be something other than 2.4 when you read this paper. It is not mandatory to get the latest kernel, but it is better to do so.

First, let us have a look at NetBSD syscalls. They are defined in the machine-independent part of the kernel sources, in sys/kern/syscalls.master. This file is used to automatically create the files sys/kern/syscalls.c, sys/sys/syscall.h, and sys/sys/syscallargs.h. Each syscall in syscalls.master is basically the system call name with "sys_" prepended to it. Here are a few lines from the sys/kern/syscalls.master file:

0  INDIR { int sys_syscall(int number, ...); }
1  STD   { void sys_exit(int rval); }
2  STD   { int sys_fork(void); }
3  STD   { ssize_t sys_read(int fd, void *buf, size_t nbyte); }
4  STD   { ssize_t sys_write(int fd, const void *buf, \
          size_t nbyte); }

Now, the Linux syscalls: Here the job is a bit more complicated, since the system call definitions are architecture dependent on Linux. The different architectures supported by the Linux kernel are in linux/arch. Each architecture has its directory. For instance, the PowerPC port of Linux has its machine-dependent source code in linux/arch/ppc/. The syscalls definition file lives in the kern subdirectory of the architecture directory, but the name of the file is not the same on all Linux ports! If you are working on another LINUX_COMPAT port, you can find the file by greping on system call names, such as mmap() or uname(). For the PowerPC, the file is linux/arch/ppc/kernel/misc.S. Here are a few lines from that file :

.long sys_ni_syscall /* 0  -  old "setup()" system call */
.long sys_exit 
.long sys_fork 
.long sys_read
.long sys_write

This Linux file lists all the syscalls, using the syscall number order. The arguments to the syscalls are not shown. To find out the arguments of a given system call, you will have to grep for its name in linux/arch/ppc/kernel and/or linux/kernel, find the function implementing the system call, and look at the function parameters.

And now, let us move to the compat directory in the NetBSD sources, which is where we will have to write a few files. For Linux compatibility on the PowerPC, it is sys/compat/linux/arch/powerpc. Here we must create a syscalls.master file and fill it with the Linux system call numbers and the function that implements them in the NetBSD kernel. The easiest way is by grabbing the syscalls.master file from another port (I used the syscalls.master from i386 Linux compatibility, which can be found at sys/compat/linux/arch/i386/syscalls.master), and modify it so that it reflects Linux syscalls on our target port, here PowerPC.

Most Linux system calls have a wrapper function in NetBSD. For example, the open() system call (syscall #3) is implemented by the linux_sys_open() function. Here is the open() system call definition in Linux compatibility, from sys/compat/linux/arch/i386/syscalls.master:
5  STD  { int linux_sys_open(const char *path, int flags, \
          int mode); }

This linux_sys_open() wrapper function lives in a file in the sys/compat/linux/common directory. Its job is to do appropriate argument translation, and then to transfer control to the sys_open() function of the NetBSD kernel.

Other Linux system calls are implemented directly by the corresponding NetBSD system call. This is the case for exit() or fork() (syscalls #1 and #2), which are defined by the sys_exit() and sys_fork() kernel functions. Here are Linux exit() and fork() definitions, from sys/arch/compat/linux/i386/syscalls.master:

1  NOARGS      { int sys_exit(int rval); }
2  NOARGS      { int sys_fork(void); } 

Most of the job is quite straightforward: It is just about reordering system calls. But sometimes, you will find that a given syscall has no equivalent for the target port. This is true, for example, for the Linux/i386 vm86() system call, which is left unimplemented in the sys/compat/linux/arc/powerpc/syscalls.master, using the UNIMPL option in the second column of the file.

Pages: 1, 2, 3, 4

Next Pagearrow

Sponsored by: