|
PatchworkOS
da8a090
A non-POSIX operating system.
|
Interrupt Handling. More...
Interrupt Handling.
Interrupts are a way to allow the CPU or external devices to stop the currently executing code and instead to execute a handler function specified in the Interrupt Descriptor Table (IDT).
An interrupt frame (interrupt_frame_t) is a structure that lets us access data pushed onto the stack by the CPU and in the assembly interrupt stubs when an interrupt occurs.
First, when an interrupt occurs, the CPU automatically pushes some data onto the stack, such as the instruction pointer and code/data segments, this data is stored in the higher addresses of the interrupt_frame_t (since the stack grows downwards).
After that, depending on the type of interrupt, the CPU might push an error code, if not the stub will push a 0 as a dummy, all stubs will also push the interrupt vector number onto the stack.
Finally, the vector_common assembly function pushes all general-purpose registers onto the stack, completing the interrupt_frame_t.
After the interrupt handler is done executing, the interrupt frame is popped off the stack allowing the CPU to restore its previous state or, if the interrupt handler modified the registers, it may return to a different state, for example, a different thread. This is how context switching is implemented.
Interrupts are identified by their vector number, which is an 8-bit value ranging from 0x00 to 0xFF. Usually, each vector number would be associated with a specific handler function, but this is quite inconvenient for the OS as a whole, it's more practical to have one single interrupt_handler() function which can then more easily group and dispatch the interrupts as needed, it also lets us write interrupt handling code in C instead of assembly.
This is done by, as mentioned above, having each vector's handler push its vector number onto the stack before jumping to the common interrupt_handler(), which can then read the vector number from the interrupt_frame_t.
Data Structures | |
| struct | interrupt_frame_t |
| Trap Frame Structure. More... | |
| struct | interrupt_ctx_t |
| Per-CPU Interrupt Context. More... | |
Macros | |
| #define | INTERRUPT_FRAME_IN_USER_SPACE(frame) ((frame)->ss == (GDT_SS_RING3) && (frame)->cs == (GDT_CS_RING3)) |
| Checks if a interrupt frame is from user space. | |
Functions | |
| void | interrupt_ctx_init (interrupt_ctx_t *ctx) |
| Initializes the interrupt context. | |
| void | interrupt_disable (void) |
| Disable interrupts and increment the disableDepth. | |
| void | interrupt_enable (void) |
| Decrement the CLI depth and enable interrupts if depth reaches zero and interrupts were previously enabled. | |
| void | interrupt_handler (interrupt_frame_t *frame) |
| Handles CPU interrupts. | |
Variables | |
| void * | vectorTable [IDT_GATE_AMOUNT] |
| Pointers to functions to handle each vector. | |
| #define INTERRUPT_FRAME_IN_USER_SPACE | ( | frame | ) | ((frame)->ss == (GDT_SS_RING3) && (frame)->cs == (GDT_CS_RING3)) |
Checks if a interrupt frame is from user space.
| frame | The interrupt frame to check. |
Definition at line 177 of file interrupt.h.
| enum page_fault_errors_t |
Page Fault Error Codes.
Will be stored in the error code of the interrupt frame on a page fault.
| Enumerator | |
|---|---|
| PAGE_FAULT_PRESENT | |
| PAGE_FAULT_WRITE | |
| PAGE_FAULT_USER | |
| PAGE_FAULT_RESERVED | |
| PAGE_FAULT_INSTRUCTION | |
| PAGE_FAULT_PROTECTION_KEY | |
| PAGE_FAULT_SHADOW_STACK | |
| PAGE_FAULT_SOFTWARE_GUARD_EXT | |
Definition at line 54 of file interrupt.h.
| enum interrupt_vector_t |
Interrupt Vectors.
Lists all interrupt vectors, divided into exceptions, external interrupts and internal interrupts.
Exceptions are interrupts generated by the CPU itself in response to, usually, unexpected conditions such as a divide by zero. Sometimes exceptions can be intentional, such as the use of page faults for dynamic stack growth.
External interrupts are reserved for the IRQ system.
See IRQ.
Internal interrupts are, as the name suggests, used internally by the kernel for things such as timer interrupts and inter-processor interrupts (IPIs).
See IPI and Timer subsystem.
| Enumerator | |
|---|---|
| VECTOR_EXCEPTION_START | Inclusive start of exceptions. |
| VECTOR_DIVIDE_ERROR | |
| VECTOR_DEBUG | |
| VECTOR_NMI | |
| VECTOR_BREAKPOINT | |
| VECTOR_OVERFLOW | |
| VECTOR_BOUND_RANGE_EXCEEDED | |
| VECTOR_INVALID_OPCODE | |
| VECTOR_DEVICE_NOT_AVAILABLE | |
| VECTOR_DOUBLE_FAULT | |
| VECTOR_COPROCESSOR_SEGMENT_OVERRUN | |
| VECTOR_INVALID_TSS | |
| VECTOR_SEGMENT_NOT_PRESENT | |
| VECTOR_STACK_SEGMENT_FAULT | |
| VECTOR_GENERAL_PROTECTION_FAULT | |
| VECTOR_PAGE_FAULT | |
| VECTOR_RESERVED | |
| VECTOR_X87_FLOATING_POINT_EXCEPTION | |
| VECTOR_ALIGNMENT_CHECK | |
| VECTOR_MACHINE_CHECK | |
| VECTOR_SIMD_FLOATING_POINT_EXCEPTION | |
| VECTOR_VIRTUALIZATION_EXCEPTION | |
| VECTOR_CONTROL_PROTECTION_EXCEPTION | |
| VECTOR_HYPERVISOR_INJECTION_EXCEPTION | |
| VECTOR_VMM_COMMUNICATION_EXCEPTION | |
| VECTOR_SECURITY_EXCEPTION | |
| VECTOR_EXCEPTION_END | Exclusive end of exceptions. |
| VECTOR_EXTERNAL_START | Inclusive start of external interrupts (handled by the IRQ system). |
| VECTOR_EXTERNAL_END | Exclusive end of external interrupts. |
| VECTOR_EXTERNAL_AMOUNT | |
| VECTOR_INTERNAL_START | Inclusive start of internal interrupts. |
| VECTOR_IPI | See IPI for more information. |
| VECTOR_TIMER | See Timer subsystem for more information. |
| VECTOR_SPURIOUS | Made available for any component to use as a sink for spurious interrupts. |
| VECTOR_INTERNAL_END | Exclusive end of internal interrupts. |
| VECTOR_TOTAL_AMOUNT | |
Definition at line 91 of file interrupt.h.
| void interrupt_ctx_init | ( | interrupt_ctx_t * | ctx | ) |
Initializes the interrupt context.
| ctx | The interrupt context to initialize. |
Definition at line 16 of file interrupt.c.
| void interrupt_disable | ( | void | ) |
Disable interrupts and increment the disableDepth.
Must have a matching interrupt_enable() call to re-enable interrupts when depth reaches zero.
Definition at line 23 of file interrupt.c.
| void interrupt_enable | ( | void | ) |
Decrement the CLI depth and enable interrupts if depth reaches zero and interrupts were previously enabled.
Definition at line 35 of file interrupt.c.
| void interrupt_handler | ( | interrupt_frame_t * | frame | ) |
Handles CPU interrupts.
This will be called from vector_common in vectors.s.
| frame | The interrupt frame containing the CPU state at the time of the exception. |
Definition at line 160 of file interrupt.c.
|
extern |
Pointers to functions to handle each vector.