1. Overview

Process Context

  • The kernel executes code on behalf of a user-space process (e.g., handling a system call like read() or write()).
  • Key Properties:
    • Associated with a struct task_struct (process descriptor).
    • Can sleep (use blocking functions like mutex_lock()).
    • Can access user-space memory (via copy_from_user()).

Interrupt Context

  • “Atomic context” or “Interrupt context”, The kernel executes code to handle a hardware interrupt or softirq (e.g., a network packet arriving)
  • Key Properties:
    • No associated process (current macro points to an idle task).
    • Cannot sleep (blocking functions like kmalloc(GFP_KERNEL) are forbidden).
    • Runs with interrupts disabled (on the current CPU).

2. CPU Execution States in ARM

ARM architectures (e.g., ARMv8-A) define exception levels (ELs) that correspond to CPU execution states:

Exception LevelPrivilegeTypical Use Case
EL0User mode (least privileged)User-space processes.
EL1Kernel mode (OS privilege)Kernel process/interrupt context.
EL2Hypervisor modeVirtualization (e.g., KVM).
EL3Secure monitor modeTrustZone secure/non-secure transitions.

How Contexts Map to ARM States

  • Process Context:
    • Runs in EL1 (kernel mode) but is tied to a process (e.g., system calls)
    • Example: sys_read() executes in EL1 but is part of the process’s execution flow
  • Interrupt Context:
    • Runs in EL1 (kernel mode) but not tied to any process
    • Example: Handling a timer interrupt (IRQ) triggers a switch from EL0 → EL1

Key ARM Registers for Context Switching

  • SPSR_EL1: Saved Process Status Register (stores CPU state before exception).
  • ELR_EL1: Exception Link Register (saves return address to resume after interrupt).
  • SP_EL0/SP_EL1: Stack pointers for EL0 (user) and EL1 (kernel).

3. How Contexts Are Managed

Switching to Interrupt Context

  1. Interrupt Occurs:
    • CPU switches from EL0 → EL1 (or stays in EL1 if already in kernel mode).
    • Saves PC (Program Counter) to ELR_EL1 and PSTATE (processor state) to SPSR_EL1.
  2. Interrupt Stack:
    • ARM uses a dedicated interrupt stack (configured via SP_EL1) for interrupt handling
  3. Interrupt Handler:
    • Executes in EL1 (interrupt context).
    • Acknowledges the interrupt (e.g., via GIC).
    • May trigger softirqs/tasklets for deferred processing.

Returning to Process Context

  • eret Instruction: Restores PC from ELR_EL1 and PSTATE from SPSR_EL1
  • Resumes Execution: Returns to EL0 (user mode) or EL1 (kernel process context).

4. Other CPU Execution States

Beyond process/interrupt contexts, CPUs have additional states:

  1. Idle Context:
    • When no processes are running, the CPU executes the idle thread (PID 0).
    • ARM: Runs in EL1 with interrupts enabled.
  2. NMI (Non-Maskable Interrupt) Context:
    • Highest-priority interrupts (e.g., hardware failures).
    • ARM: Handled similarly to IRQs but cannot be masked.
  3. Hypervisor Context (EL2):
    • Used by hypervisors (e.g., KVM) to manage virtual machines.
  4. Secure Monitor Context (EL3):
    • Handles transitions between secure/non-secure worlds (ARM TrustZone).

5. Key Kernel APIs & Functions

Process Context

  • schedule(): Voluntarily yield the CPU (allowed in process context).
  • current: Macro to access the current task_struct

Interrupt Context

  • in_interrupt(): Returns true if in interrupt context.
  • local_irq_disable()/local_irq_enable(): Disable/enable interrupts on the local CPU.

6. Examples

Process Context

// Kernel module handling a syscall (process context)
SYSCALL_DEFINE3(write, int, fd, const char __user *, buf, size_t, count) {
    struct file *file = fget(fd);  // Blocking operation (allowed)
    copy_from_user(kernel_buf, buf, count); // Access user memory
    // ...
}

Interrupt Context

// Interrupt handler for a GPIO button (interrupt context)
irqreturn_t button_isr(int irq, void *dev_id) {
    if (in_interrupt()) printk("Running in interrupt context!\n");
    tasklet_schedule(&deferred_task); // Defer work to process context
    return IRQ_HANDLED;
}

7. Tools for Debugging Contexts

  • perf: Trace transitions between EL0/EL1.
    perf record -e exceptions:el1_sync ./my_program
    
  • ftrace: Track function calls in process/interrupt contexts.
  • /proc/interrupts: View interrupt counts per CPU.

References