Instruction level simulators are efficient tools for evaluating and debugging computer architectures. They are typically portable and highly flexible with respect to architectural modifications and instrumentation. However, a major problem arise when dealing with real application programs that require the full support of an operating system, e.g., the SPEC benchmark programs. In principle, this problem can be handled by providing a complete simulator specific runtime system. However, the effort of implementing a runtime system in combination with the moving target posed by operating system updates makes this task very hard. Here, we describe a simulator technique that accommodates general application programs but avoids the complexity of special runtime libraries, compiler/linker modifications, and the burden of booting an operating system on the simulator.
The basic idea is to execute system calls made by the simulated program on the physical CPU by capturing them at the lowest level, i.e., when the simulated program executes the system trap. At this point the context of the simulated CPU is loaded into the physical CPU and the trap is executed by the simulator process.
Utilizing system calls as the point of communication between the simulated program environment and the simulator platform offer two important advantages, simplicity and generality. Across various Unix implementations the services offered at the system call level are relatively simple and consistent. The technique presented here leads to the following advantages:
? The simulator can run virtually any program, regardless of runtime or system calls made by the program.
? Easily portable to different platforms
? No need for special compiler, recompilation or simulator specific runtime system.
? Execution of runtime modules, e.g., libc routines, are performed on the simulated CPU.
II. Simulator overview
The technique for handling system calls has been implemented in a typical instruction level simulator for the SPARC architecture (part of the CacheMire testbench ). Programs executed on the simulator are ordinary SPARC binaries running under SunOS, including runtime routines. The simulator intercepts system calls when it encounters the system trap instruction.
Handling System Calls in an Instruction Level Simulator
Bertil Roslund and Per Andersson,
Department of Computer Engineering, Lund University,
P.O. Box 118, S-221 00 Lund, Sweden.
To perform the action requested by the system call, the simulator will execute the call on the physical CPU by issuing a real system trap. This requires that enough of the context from the simulated process is loaded into the simulator process before the trap is taken. For many system calls this includes not only the processor registers but also data structures in virtual memory, e.g., file control blocks and file buffers.
The key idea that makes these context switches between the simulated process and the simulator process possible, is the mapping of simulated virtual addresses to identical virtual addresses in the simulator process. That is, a data structure residing at virtual address x in the simulated program is always mapped on virtual address x in the simulator process.
This address identity is achieved by starting the simulator in two steps. First a small bootstrap program loads the simulator into memory at a ?high? address. It then hands over control to the simulator, that loads the program to be simulated at the normal address for programs, and thus overwrites the bootstrap program. The simulator also allocates memory for the stack of the simulated program, and sets the stackpointer of the simulated processor to point at this memory area. The simulator itself uses no dynamically allocated data and thus there is no need for a simulator heap. The resulting memory configuration is shown in figure 1. Since the program is loaded into the memory addresses it was linked for, an initial memory identity is
Figure 1: Memory map