PatchworkOS  da8a090
A non-POSIX operating system.
Loading...
Searching...
No Matches
Interrupts

Interrupt Handling. More...

Collaboration diagram for Interrupts:

Detailed Description

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).

Interrupt Frames

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.

Interrupt Numbers

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.
 

Enumerations

enum  page_fault_errors_t {
  PAGE_FAULT_PRESENT = 1 << 0 , PAGE_FAULT_WRITE = 1 << 1 , PAGE_FAULT_USER = 1 << 2 , PAGE_FAULT_RESERVED = 1 << 3 ,
  PAGE_FAULT_INSTRUCTION = 1 << 4 , PAGE_FAULT_PROTECTION_KEY = 1 << 5 , PAGE_FAULT_SHADOW_STACK = 1 << 6 , PAGE_FAULT_SOFTWARE_GUARD_EXT = 1 << 7
}
 Page Fault Error Codes. More...
 
enum  interrupt_vector_t {
  VECTOR_EXCEPTION_START = 0x0 , VECTOR_DIVIDE_ERROR = 0x0 , VECTOR_DEBUG = 0x1 , VECTOR_NMI = 0x2 ,
  VECTOR_BREAKPOINT = 0x3 , VECTOR_OVERFLOW = 0x4 , VECTOR_BOUND_RANGE_EXCEEDED = 0x5 , VECTOR_INVALID_OPCODE = 0x6 ,
  VECTOR_DEVICE_NOT_AVAILABLE = 0x7 , VECTOR_DOUBLE_FAULT = 0x8 , VECTOR_COPROCESSOR_SEGMENT_OVERRUN = 0x9 , VECTOR_INVALID_TSS = 0xA ,
  VECTOR_SEGMENT_NOT_PRESENT = 0xB , VECTOR_STACK_SEGMENT_FAULT = 0xC , VECTOR_GENERAL_PROTECTION_FAULT = 0xD , VECTOR_PAGE_FAULT = 0xE ,
  VECTOR_RESERVED = 0xF , VECTOR_X87_FLOATING_POINT_EXCEPTION = 0x10 , VECTOR_ALIGNMENT_CHECK = 0x11 , VECTOR_MACHINE_CHECK = 0x12 ,
  VECTOR_SIMD_FLOATING_POINT_EXCEPTION = 0x13 , VECTOR_VIRTUALIZATION_EXCEPTION = 0x14 , VECTOR_CONTROL_PROTECTION_EXCEPTION = 0x15 , VECTOR_HYPERVISOR_INJECTION_EXCEPTION = 0x1C ,
  VECTOR_VMM_COMMUNICATION_EXCEPTION = 0x1D , VECTOR_SECURITY_EXCEPTION = 0x1E , VECTOR_EXCEPTION_END = 0x20 , VECTOR_EXTERNAL_START = 0x20 ,
  VECTOR_EXTERNAL_END = 0xF0 , VECTOR_EXTERNAL_AMOUNT = VECTOR_EXTERNAL_END - VECTOR_EXTERNAL_START , VECTOR_INTERNAL_START = 0xF0 , VECTOR_IPI = 0xFD ,
  VECTOR_TIMER = 0xFE , VECTOR_SPURIOUS = 0xFF , VECTOR_INTERNAL_END = 0x100 , VECTOR_TOTAL_AMOUNT = 0x100
}
 Interrupt Vectors. More...
 

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.
 

Macro Definition Documentation

◆ INTERRUPT_FRAME_IN_USER_SPACE

#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.

Parameters
frameThe interrupt frame to check.
Returns
true if the interrupt frame is from user space, false otherwise.

Definition at line 177 of file interrupt.h.

Enumeration Type Documentation

◆ 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.

◆ interrupt_vector_t

Interrupt Vectors.

Lists all interrupt vectors, divided into exceptions, external interrupts and internal interrupts.

Exceptions

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

External interrupts are reserved for the IRQ system.

See IRQ.

Internal Interrupts

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.

Function Documentation

◆ interrupt_ctx_init()

void interrupt_ctx_init ( interrupt_ctx_t ctx)

Initializes the interrupt context.

Parameters
ctxThe interrupt context to initialize.

Definition at line 16 of file interrupt.c.

Here is the caller graph for this function:

◆ interrupt_disable()

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.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ interrupt_enable()

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.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ interrupt_handler()

void interrupt_handler ( interrupt_frame_t frame)

Handles CPU interrupts.

This will be called from vector_common in vectors.s.

Parameters
frameThe interrupt frame containing the CPU state at the time of the exception.

Definition at line 160 of file interrupt.c.

Here is the call graph for this function:

Variable Documentation

◆ vectorTable

void* vectorTable[IDT_GATE_AMOUNT]
extern

Pointers to functions to handle each vector.