Syscalls, Upcalls, and Hypercalls
Software Components Communication
Do you know the difference between these three types of calls? If no, this article is for you. It presents these three terms in the context of computer systems: operating systems and virtual machines. These operations allow independent parts of the system to call each other.
It is short for System Call. It allows the user-space to request a service from the kernel-space. Indeed most operating systems are split into two spaces. The user-space is where common applications execute. They have no particular privileges. The kernel space is where the critical operations of the system are executed. Open(), read(), write(), close(), fork() are example of system calls.
Ultimately, a system call is an assembly instruction that takes at least one argument. The system call number. Fortunately, we don’t need to know the assembly since there is a GlibC library wrapper that handles the low-level details for us. The following code shows how to get the PID (Process ID) of the current process using the wrapper:
#include <signal.h>int main(int argc, char *argv)
pid_t pid = syscall(SYS_getpid);
printf("getpid() system call number %d\n", SYS_getpid);
printf("current process pid is %d\n", pid);
Compiling and executing the code we have:
$ gcc get-pid.c -o get-pid
getpid() system call number 39
current process pid is 4372
The system call number to get the PIDis 39 (SYS_getpid), at least on my Linux machine. It may change depending on your operating system. The process that executed the code has the id 4372.
This is what happens in user-space. In the kernel-space, the kernel looks at the system call number (in this case 39) and calls the corresponding kernel function that will handle the system call. The correspondence between the system call number and the kernel function to be called is usually done using the system call table. Where the index of the table is the system call number and the content of the table entry is the address of the function (see the Figure below).
An upcall is the reverse of a syscall. It allows the system to call a specific function of an application in user-space. Upcalls are not very common in monolithic kernels such as Linux (although very common on microkernel systems). One notable exception is the implementation of the user-space Fuse file system library that is upcalled directly by the Linux kernel. Additionally, POSIX signals can be considered upcalls since the kernel calls a user function: the function registered with sigaction(2)-like syscalls.
To implement upcalls there is no need to use a redirection through a table. We can simply directly call the target function in user-space. The reason that we can directly call a user function and we cannot do it for syscall is related to the security of the system. Indeed it is safe to allow the kernel-space to call a function in user-space since it already has access to all the memory of the system. However, the reverse is not true. If an user-space application can call any kernel space function, it can abuse it (hack into the kernel!).
Hypercalls are found in the context of Virtual Machines (VM). They allow a VM to call the Virtual Machine Monitor (VMM) also called hypervisor. They are similar to system calls, in the sense that it is a less privileged system (VM) that is calling a more privileged one (the VMM).
An example of a VMM that uses it, is KVM (Kernel Virtual Machine). This later is integrated directly into the Linux Kernel. Some systems offer wrappers that can be used to do an hypercall, such as the Linux kernel. Within the VM, we can use the kvm_hypercall*() functions to do this.
Finally, if you are wondering what is the equivalent of an upcall in the world of virtualization, it is simply upcall (it does not change). I guess they did not (yet) found a fancy name for it as the hypercall, where “hyper” comes from the hypervisor.
In this post we went through the different mechanisms uses to communicate between the different components of the system software. We saw the syscalls, which ensure the communication from the user space to the kernel space. On the other hand, upcalls allows the kernel space to request a service from the user space. Finally, hypercalls are representative of system calls in the context of virtual machines.
Hope you liked it! Don’t forget to clap.