The state of affairs is that only interrupts and traps were actually used and remain in use. Theoretically, both of them can be used both for s / w and for handling h / w events. The only difference between the two is that calling the interrupt call automatically prohibits future interrupts, which may be useful in some cases of processing a hardware interrupt. By default, people try to use trap traps, because unnecessarily disabling interrupts is bad, because interrupting an interrupt increases the delay in processing interrupts and increases the likelihood of losing an interrupt. The call gate has never been used. This is inconvenient and not optimal for implementing a system call. Instead of a call gateway, most operating systems use a trap (int 0x80 on Linux and int 0x2E on Windows) or sysenter / sysexit syscall / sysrt. The target door has also never been used. This is not an optimal, inconvenient and limited feature, if not ugly. Instead, operating systems typically implement task switching for their part by switching kernel mode task stacks. Intel initially provided hardware support for multitasking by introducing TSS (task status segment) and Task Gate. In accordance with these functions, the processor is able to automatically save the state of one task and restore the state of another in response to a request received from hw or sw. The Sw request can be made by issuing call or jmp commands using the TSS selector or the task gate selector used as the instruction operand. The Hw request can be executed in hardware, moving to the task gate in the corresponding IDT record. But, as I mentioned, no one uses it. Instead, operating systems use only one TSS for all tasks (TSS should be used in any case, because during the transfer of control from the less privileged segment to the more privileged switch segments of the CPU and it grabs the stack address for the more privileged segment from TSS) and manually switch task.
In theory, interrupts and exceptions can be processed in user mode (ring 3), but in practice this is not useful, and the operating system processes all such events on the kernel side (in ring 0). The reason is simple: interrupts and exception handlers should always be in memory and be accessible from any address space. The core part of the address space is common and identical in all address spaces of all tasks in the system, but the user part of the address space is connected to a specific task. If you want to handle the exception in user mode, you will have to reprogram the IDT on each task switch, which will lead to a significant decrease in performance. If you want to handle interrupts the same way, you will be forced to share interrupt handlers between all tasks at the same addresses. As undesirable consequences, any task in the system will be able to ruin the handler.
source share