====== Performing Native system calls for user-level simulators ====== User-level simulators focus on simulating the user-space part of the target ISA, such as computation instructions, load/stores, branches and so on... Such simulator usually do not implement complex scheduling techniques, running a single thread over a single processor dedicated to this only thread. ===== Why user-level simulators needs to perform system calls ===== To simulate at user-level even a simple benchmark, it is required to implement some of the tasks that should be dedicated to the target OS, like the **System Calls**. To better understand why, let's consider the following //hello_world// benchmark. #include int main() { printf("hello world\n"); return 0; } Simulating this benchmark, the user expect if to write "hello world" on the screen. Let's detail how this is performed in the real target architecture. The ''printf'' function call will itself performs a call to the following ''write '' lower-level method of the //glibc//. write(1, "hello world", 12); With the first parameter (''1'') being the file descriptor number of the standard output, and the third one (''12'') the size of the buffer to print. Once translated to a PowerPC assembly code, this ''write'' function correspond to the following assembly code: li r3, 1 // r3 = target file descriptor mr r4, @hello // r4 = string buffer address li r5, 13 // r5 = buffer length li r0,4 // r0 = 4 (linux write syscall number) sc // Perform the system call This code is using the system call instruction ''sc'' procided by the PowerPC ISA, and this instruction should itself require the operating system to perform the syscall. Each operating system has its own system call table. The Linux Operating system for instance has the following [[Linux Syscall Table]], where ''write'' is the system call number 4. Such system calls can access dataset files (open, close, read and write), perform some filesystem related operations (rmdir, mkdir), obtain system informations (time,...) etc... Those operation should be performed natively on the hosting machine for the files to be effectively accessed. We therefore need to translate the system calls of the target architecture to the native architecture running the simulator. This operation is performed by the **Syscall Translator** capability. ===== What is needed to perform a Syscall ===== As long as the Target OS is close to the native OS, it is quite easy to map syscalls: A 32-bit PowerPC 405 linux OS distribution has the same syscall table than a Intel 64-bit linux distribution. However, the data structure involved in the system calls will not be the same when switching from 32-bit to 64-bit that will require a conversion. And the encoding can also be different when switching from a big-endian target to a little-endian host, as it is the case with the previous example. The impact of the system calls on the architecture are usually to either read a buffer in the memory and perform something on the data (like the ''write'' syscall is doing) or to write a buffer in the memory (like the ''read'' syscall is doing). As we are performing the syscall natively, we have to copy those buffers from/to the native memory to/from the simulated memory, eventually performing some endian conversion. The step usually involved in translating a syscall are: * Get the target syscall parameters from the register bank * Converting the input structures for the target syscall to build the native input structures * Copying memory buffers from the simulated memory to the native memory * Correcting endianess * Allocating and filling the native input structures for the native syscall * Performing the native syscall * Converting the native output structures to target output structures * Allocating a buffer corresponding to the target output structure in the native memory * Filling htis structure with the result of the syscall perfoming some endianess conversion * Copying back the output structure to the simulated memory. * Set up the result register correctly Therefore to perform syscalls, the syscall capability needs to be able to: * Access (read/write) the register bank * Access (read/write) the memory hierarchy ===== Native Syscall for Linux capability in the SVN repository ===== This capability is available at [[https://unisim.org/svn/public/components/FullSystem/trunk/src/plugins/os/linux]]. To compile it requires to download the whole public branch of the repository which contains all the components composing the simulator. More information can be found on the [[download:Public Branch]] page. Two different capabilities are provided: * A Syscall Translation capability for 32-bit PowerPC * A Syscall Translation capability for 32-bit ARM ===== Reference Manual ===== * [[http://unisim.org/website/refman/capabilities/os/refman.pdf|Syscall Capability reference manual]]