3: Context Switch
*User to kernel Mode Switch
There are three conditions will trigger switch.
- Exceptions: When the processor encounters unexpected condition like illegal memory access, divide-by-zero (in C), perform privileged instructions.
- Interrupts: Asynchronous signal to the processor that some external event has occurred that requires its attention, like timer interrupts, I/O requests such as mouse movement.
- System calls: User processes requests the kernel do som operation on the user’s behalf, like R/W files, creating new processes, network connections.
What types of these user-to-kernel switch are they?
- inter-processor interrupt(IPI)
- invalid opcode
- segmentation fault
- network card interrupt
- divide-by-zero in python/java
- exception from interpreter (not processor)
Interrupt Vector Table
Interrupt vector table stores the entries of different handlers for exceptions, interrupts, and traps in real mode.
There is a special register that point to the vector (array) in kernel memory, where each entry points to the first instruction of a different handler procedure in the kernel.
In x86, there are \(256\) entries in total. Each takes \(4\) bytes.
Old.
Interrupt Descriptor Table
Interrupt descriptor table tells CPU where the interrupt service routines are located.
Location calls entry, also called gate. There are \(256\) gates in total. Each gate is \(8\)-bytes long on \(32\)-bit processors; or \(16\)-bytes long on \(64\)-bit processors. Its location is kept in IDT register(IDTR), loaded with LIDT assembly instruction.
用户态到内核态只能经过这 \(256\) 个门
The following table is gate descriptor(32-bit) structure:
| bits | name |
|---|---|
| 0 ~ 15 | Offset |
| 16 ~ 31 | Segment Selector |
| 32 ~ 39 | Reserved |
| 40 ~ 43 | Gate Type |
| 44 | 0 |
| 45 ~ 46 | DPL |
| 47 | P |
| 48 ~ 63 | Offset |
- Offset: A 32-bit value, split in two parts, represents the address of the interrupt service routine.
- Selector: A segment selector which must point to a valid code segment in your GDT (Global Descriptor Table).
- Gate Type: A 4-bit value which defines the type of gate this interrupt descriptor represents.
- DPL: A 2-bit value which defines the CPU privilege levels which are allowed to access this interrupt via the INT (Interrupt Instruction).
- P: Present bit. Must be set 1 for the descriptor to be valid.
Why offset is split into two parts? For compatibility.
| 特性 | IVT | IDT |
|---|---|---|
| 用途 | 实模式中断向量表 | 保护模式/长模式中断描述符表 |
| 存储位置 | 固定在 0x0000 到 0x03FF | 动态位置,由 IDTR 指定 |
| 条目大小 | \(4\) 字节 | \(8\) 字节(\(32\) 位)或 \(16\) 字节(\(64\) 位) |
| 条目内容 | 中断处理程序的入口地址 | 描述符(包含段选择器、偏移地址等) |
| 支持的模式 | 实模式 | 保护模式、长模式 |
IVT 是早期的简单实现,而 IDT 是现代操作系统中更灵活和安全的中断处理机制。
Interrupt Masking
There are two kinds of interrupts:
- Maskable interrupts: all software interrupts, all system calls, and partial hardware exceptions.
- Non-Maskable interrupts: partial hardware exceptions.
- Specified by eflags registers.
Disable interrupts and enable interrupts. Both of them are privileged instructions.
Masked interrupts are deferred, but not ignored. Given the limited buffer for interrupts, hardware buffers one interrupt of each type.
*Interrupt Stack
Interrupt stack is a special stack in kernel memory that saves interrupt process status. Empty when there is no interrupt (running in user space).
Why not directly use the user-space stack?
For reliability and security
How many interrupt stack in kernel?
Kernel need to allocate each thread a interrupt stack
- First fault: trap from user-space program to kernel-space exception handler.
- Double fault: trap from exception handler to another handler.
- Triple fault: reboot.
Kernel to User Mode Switch
New process
When a new process is created (e.g., via
forkandexecin Unix-like systems), the kernel initializes its context and then switches to user mode to start executing the user program.Resume after an interrupt/exception/syscall
After handling an interrupt, exception, or system call, the kernel restores the user process’s context and returns to user mode so the process can continue execution from where it was interrupted.
Switch to a different process
The kernel may decide to switch to another process (context switch), often triggered by a timer interrupt (preemptive multitasking) or when the current process is blocked (e.g., waiting for I/O). The kernel saves the current process’s state and restores the next process’s state before switching to user mode.
User-level upcall
Sometimes, the kernel needs to notify a user process of an event (such as asynchronous I/O completion or signals). This is done via a user-level upcall, where the kernel arranges for a specific user-mode handler to be invoked.
Upcalls allow apps to implement OS-like functionality to be invoked by OS.
Asynchronous I/O notification, like waiting for I/O completion.
Inter-process communication, such as debugger suspends a process.
User-level exception handling, like ensuring files saved before app shuts down.
User-level resource allocation, such as Java garbage collection.
*x86 Example
x86 Background
- Memory is segmented, so pointers come in two parts: a segment and an offset.
- program counter:
csregister andeipregister - stack pointer:
ssregister andespregister - CPL is stored as the \(2\) lower-bit of
csregister
- program counter:
- In Intel 8086:
cs:eip= cs \(\times 16 +\)eip- both
csandeipare \(16\)-bits long, therefore CPU can access at most \(1\) MB memory space
- both
eflagsregister stores the processor status and controls its behavior. Whether interrupts are masked or not.- Only a small number of instructions can change the
csregister valueljmp(far jump)lcall(far call), which pusheseipandcsto the stack, and then far jumpslref(far return), which inverses the far callINT: an assembly languages instruction for x86 processors that generates a software interrupt. It takes the interrupt number formatted as a byte value. Which readcs/eipfrom the IVTIRET: returns program control from an exception or interrupt handler to a program or procedure that was interrupted previously
x86 transfer
When an interrupt/exception/syscall occurs, the hardware will:
- mask interrupts
- save the special register values to other temporary registers
- switch onto the kernel interrupt stack
- push the three key values onto the new stack
- optionally save an error code
- invoke the interrupt handler (CPL changed!)
Then the OS will:
- save the rest of the interrupted process’s state
pusha/pushad
- execute the handler
- resume the interrupted process
popa/popad\(+\) pop error cod
- resume the interrupted process
iret(kernel mode to user mode)
Recap
(1). Define three types of user-mode to kernel-mode transfers.
(2). Define four type of kernel-mode to user-mode transfers.
(3). Most hardware architectures provide an instruction to return from an interrupt, such as iret. This instruction switches the mode of operation from kernel-mode to user-mode.
- Explain where in the operating system this instruction would be used.
- Explain what happens if an application program executes this instruction.