I am aware that Kernel mode is a privileged such that in kernel mode all hardware capabilities and all instructions in instruction set are available. I am also aware that when we make a procedure call (say read()) it in turn makes a system call. But before that it Traps into Kernel mode. I wanted to know what use would having Kernel mode serve if every user program can run in Kernel mode as all procedure calls and system calls are available to user programs.
2 Answers
The problem about hardware, files and other safety-critical parts of OS is that they should be operated only in a correct way, otherwise the OS would be damaged (or other bad things would happen).
Without the kernel-user separation an application itself provides a code which works with OS-critical parts. An this code could be any. Thus, a malformed application could potentially damage an OS.
With kernel-user separation the only way for an application to touch a hardware is a system calls. This allows to run only a limited code which works with a safety-critical parts of OS. An application has no way to modify that code.
So, having correctly written the code which handles system calls, an OS protects its critical parts from the malformed applications.
There are several reasons for separating address spaces.
First one is security. Every program can call into the kernel, but the kernel doesn't have to oblige. As an example, you can try asking the kernel to open("/dev/sda", O_RDWR)
as an unprivileged user and see what happens. The kernel will prevent you from screwing up the system that other users are using.
Second one is convenience. On many embedded systems, there is indeed no userspace. So let's imagine we're writing our program in the kernel. And now our program has a small bug and it crashes, or overwrites important memory. In most cases, this screws up the address space and you need a new address space. But if you only have one address space, the only way to get there is to reboot.
Third one is synchronization. For example, If two processes want to use memory, they need to cooperate in order to not use the same memory block. If one program has a bug, it could cause problems to many other programs. Forcing memory management to be done through APIs that programs are forced to abide by means that no program can cause such problems.