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,
ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.0.tar.gz 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.
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.




