With a mechanism in place to intercept process system calls and switch
between user and kernel mode and back, virtualizing system calls is
fairly straightforward.

The system call obviously must be annulled in the host kernel. This
is done by changing the register containing the system call number
to __NR_getpid. When this is done, the tracing thread
saves the process registers in the thread structure, and imposes some
previously saved state. This new state causes the process to start
executing the system call handler, which reads the system call and
arguments from its saved registers and calls the system call code.

When the system call is finished, the process stores the return value
in its saved registers, and requests that the tracing thread return
it to user mode. The tracing thread restores the saved registers,
and continues the process with system call tracing on.