|
PatchworkOS
19e446b
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... | |
Macros | |
| #define | INTERRUPT_FRAME_SIZE (8 * 22) |
| Macro to be used in ASM to define the size of an interrupt frame. | |
| #define | INTERRUPT_FRAME_REGS_PUSH |
| Macro to be used in ASM to push general-purpose registers onto the stack. | |
| #define | INTERRUPT_FRAME_REGS_POP |
| Macro to be used in ASM to pop general-purpose registers from the stack. | |
| #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_handler (interrupt_frame_t *frame) |
| Handles CPU interrupts. | |
| _NORETURN void | interrupt_fake (interrupt_frame_t *frame) |
| Enter a fake interrupt context as if an interrupt had occurred at the given frame. | |
Variables | |
| void * | vectorTable [IDT_GATE_AMOUNT] |
| Pointers to functions to handle each vector. | |
| #define INTERRUPT_FRAME_SIZE (8 * 22) |
Macro to be used in ASM to define the size of an interrupt frame.
Definition at line 55 of file interrupt.h.
| #define INTERRUPT_FRAME_REGS_PUSH |
Macro to be used in ASM to push general-purpose registers onto the stack.
Definition at line 60 of file interrupt.h.
| #define INTERRUPT_FRAME_REGS_POP |
Macro to be used in ASM to pop general-purpose registers from the stack.
Definition at line 80 of file interrupt.h.
| #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 229 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 105 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_FAKE | Used to implement |
| 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 142 of file interrupt.h.
| 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 184 of file interrupt.c.
|
extern |
Enter a fake interrupt context as if an interrupt had occurred at the given frame.
Provides a way to schedule and handle notes outside of a real interrupt context.
| frame | The interrupt frame representing the state at the time of the fake interrupt. |
|
extern |
Pointers to functions to handle each vector.