Privilege
Have you ever got a Segmentation fault?
Now imagine that every time your program has a bug, your entire computer just reboot. No error message, no debugger, just a blue screen.
To keep an operating system stable and protected from buggy or malicious applications, software solutions alone aren’t enough. We need hardware support—specifically, a privilege level mechanism that allows the CPU to operate in different modes depending on whether it’s executing application code or kernel code.
Now, I will explain the design motivation behind privilege levels, how hardware and software work together to implement them, and how RISC-V defines and enforces privilege levels through special instructions.
Note that the same principle holds for other CPU architecture (e.g., X86, ARM), but I use RISC-V as case study below because later in the semester, we will work on xv6, which is currently based on RISC-V. As operating systems grew in complexity and started serving multiple applications, it became risky to run everything in one single address space. If an application misbehaves (due to bugs) it might bring down the entire system. To address this, computer architects designed systems with two separate execution environments: These two environments are known as: There are two main restrictions for user-mode applications: However, user programs still need to interact with the OS. For example, when you want to open a file or print to the screen, your program must ask the OS for help. To allow such interactions without compromising security, CPUs define special instructions that safely switch between user mode and kernel mode. There are four kinds of exceptions: Interrupt, Trap, Fault, and Abort. Whenever an exception occurs, the CPU looks up a table for how to handle it. Each entry in this table points to a small piece of code, called an exception handler, that knows how to deal with a particular situation. The table is usually set up by the OS when the computer boots. In RISC-V, the base address of the table is stored in a control register called So here’s what happens under the hood: 1. Your program causes a trap (say, a call to Each type of exception has its own code, and that code is used as an index into the table. After the handler finishes, control returns to where the program left off (unless the situation was serious enough that the program is killed). Learn more about xv6’s Interrupt Descriptor Table RISC-V has two instructions to manage privilege-level transitions: Without these instructions, a normal function call ( RISC-V defines four privilege levels: For example: - Simple embedded systems might only use M mode. - More secure systems might use M + U. - Full operating systems like Unix require M + S + U. The execution environment stack in a RISC-V system typically looks like this: - User programs run in U mode. - Operating system kernel runs in S mode. - Firmware / bootloader runs in M mode. Each layer can only do what the higher privilege level allows it to do. If a user program needs something it can’t do, it must request the OS’s help via When a user program executes Once the CPU has switched to supervisor mode, the kernel can then validate the arguments of the system call (e.g., check if the address passed to the system call is part of the application’s memory), decide whether the application is allowed to perform the requested operation (e.g., check if the application is allowed to write the specified file), and then deny it or execute it. It is important that the kernel control the entry point for transitions to supervisor mode; if the application could decide the kernel entry point, a malicious application could, for example, enter the kernel at a point where the validation of arguments is skipped. (Kaashoek and Morris 2023)Why Privilege Levels
Exception
Exception Handling
stvec
.read()
). 2. The CPU sees it’s a trap and looks at the current privilege level (e.g., user mode). 3. It consults the exception table to find the correct handler address for a “user environment call.” 4. It jumps to that handler—code in the kernel that knows how to perform the requested system call safely.RISC-V’s Privilege Switching
ecall
(Environment Call): Used by user programs to request a service from the OS. It triggers a switch from user mode to supervisor (kernel) mode.sret
(Supervisor Return): Used by the OS to return control back to the user program.call
/ret
) could skip hardware checks and allow privilege violations. The hardware ensures that only controlled, secure transitions can occur through ecall
/sret
.RISC-V Privilege Levels
Level Encoding Name 0 00
User / Application (U) 1 01
Supervisor (S) 2 10
Hypervisor (H) 3 11
Machine (M) ecall
.ecall
, or if it tries to do something illegal (like divide by zero or use a privileged instruction), the CPU generates an exception—a kind of interrupt or trap. Control transfers to the OS to handle the situation.System Calls