There are few challenges when virtualizing the machine:
A basic technique to make a program run as fast as one might expect is limited direct execution
“direct execution” → run the program directly on the CPU, so when OS wishes to start a program running, it creates a process entry for it in a process list, allocates some memory for it, load the code and starts running.
However, doing so would arise few problems. How can the OS make sure the program doesn’t do anything that we don’t want it to do while ensuring its efficiency and how does the OS stop it from running and switch to other process?
To prevent the program from doing restricted operations, we can have different modes for the hardware and the different mode will have different permissions.
User mode: when code runs in user mode, a process can’t issue I/O requests
Kernel mode: the mode that the OS runs in. In this mode, code that runs can do whatever it wants.
any hardware or exception related operations are considered as “privileged” operation, and the difference between user and kernel mode is that privileged operation are allowed only in kernel mode.
For a user process to perform some operation that need higher permission, the user process has to perform a system call. To execute a system call, a program must execute a special trap instruction. This instruction simultaneously jumps into the kernel and raises the privilege level to kernel mode; once in the kernel, the system can now perform whatever privileged operations are needed (if allowed), and thus do the required work for the calling process. When finished, the OS calls a special return-from-trap instruction which returns into the calling user program and switch back to user mode.
To know which code to return to from trap, the OS will have a kernel stack to record the necessary information. The trap, on the other hand, will know which code to run inside the OS by using a trap table that’s set up by the kernel at boot time. The OS informs the hardware of the locations of trap handlers and the hardware will know what to do.
In this approach, the OS trust the processes of the system to behave reasonably. Processes that run for too long are assumed to periodically give up the CPU so that the OS can decide to run some other task. The OS regains control of the CPU by waiting for a system call or an illegal operation of some kind to take place.
A timer interrupt: a timer device can be programmed to raise an interrupt every so many milliseconds, and when the interrupt is raised, the currently running process is halted, and a pre-configured interrupt-handler in the OS runs so the OS can regain the control.