TTrapHandler

#include <lib/string.h>
#include <lib/trap.h>
#include <lib/syscall.h>
#include <lib/debug.h>
#include <lib/x86.h>
#include <dev/intr.h>
#include <vmm/MPTOp/export.h>
#include "import.h"
  • <lib/string.h>: Provides utilities for string manipulation.

  • <lib/trap.h>: Defines structures and functions for trap handling.

  • <lib/syscall.h>: Includes syscall-related constants and functions.

  • <lib/debug.h>: Debugging macros such as KERN_DEBUG and KERN_PANIC.

  • <lib/x86.h>: Architecture-specific utilities for x86.

  • <dev/intr.h>: Handles device-level interrupt utilities.

  • <vmm/MPTOp/export.h>: Manages virtual memory operations.

  • "import.h": Imports kernel-specific constants and functions.


trap_dump

Purpose

Prints the contents of the trap frame for debugging.

Code Analysis

static void trap_dump(tf_t *tf)
{
    if (tf == NULL)
        return;
  • Checks: Verifies that the trap frame pointer is valid.

    uintptr_t base = (uintptr_t) tf;
    KERN_DEBUG("trapframe at %x\n", base);
    KERN_DEBUG("\t%08x:\tedi:   \t\t%08x\n", &tf->regs.edi, tf->regs.edi);
    ...
}
  • Registers: Logs the values of all general-purpose registers, segment selectors, error codes, and instruction pointers stored in the trap frame.

  • Use Case: Helps debug unexpected traps by providing a snapshot of the CPU state.


default_exception_handler

Purpose

Handles unrecognized exceptions by dumping the trap frame and halting the system.

Code Analysis

void default_exception_handler(void)
{
    unsigned int cur_pid;
    cur_pid = get_curid();
    trap_dump(&uctx_pool[cur_pid]);
    KERN_PANIC("Trap %d @ 0x%08x.\n", uctx_pool[cur_pid].trapno, uctx_pool[cur_pid].eip);
}
  • Dumps the trap frame for the current process and halts execution with a panic message.


pgflt_handler

Purpose

Handles page faults caused by invalid memory access.

Code Analysis

void pgflt_handler(void)
{
    unsigned int cur_pid = get_curid();
    unsigned int errno = uctx_pool[cur_pid].err;
    unsigned int fault_va = rcr2();
  • rcr2(): Retrieves the faulting virtual address from the CR2 register.

    if ((errno & 0x3) == 0x3) {
        pte_entry = get_ptbl_entry_by_va(cur_pid, fault_va);
        if (pte_entry & PTE_COW) {
            // handling copy-on-write
        } else {
            KERN_PANIC("Writing to read-only page: va = %p\n", fault_va);
        }
    }
  • Copy-on-Write Handling:

    • Checks if the fault is caused by writing to a copy-on-write (COW) page.

    • If not, the kernel panics.

    if (errno & PFE_PR) {
        KERN_PANIC("Permission denied: va = 0x%08x, errno = 0x%08x.\n", fault_va, errno);
        return;
    }

    if (alloc_page(cur_pid, fault_va, PTE_W | PTE_U | PTE_P) == MagicNumber) {
        KERN_PANIC("Page allocation failed: va = 0x%08x, errno = 0x%08x.\n", fault_va, errno);
    }
}
  • Page Allocation:

    • Handles allocation of pages for valid page faults.

    • Panics if allocation fails.


exception_handler

Purpose

Routes exceptions to their respective handlers.

Code Analysis

void exception_handler(void)
{
    unsigned int current_pid = get_curid();
    tf_t tf = uctx_pool[current_pid];

    if (tf.trapno == T_PGFLT) {
        pgflt_handler();
    } else {
        default_exception_handler();
    }
}
  • Delegates page faults to pgflt_handler and all other exceptions to default_exception_handler.


Interrupt Handlers

spurious_intr_handler

static int spurious_intr_handler(void)
{
    return 0;
}
  • Handles spurious interrupts (false positives).

timer_intr_handler

static int timer_intr_handler(void)
{
    intr_eoi();
    return 0;
}
  • Acknowledges and clears the timer interrupt.

default_intr_handler

static int default_intr_handler(void)
{
    intr_eoi();
    return 0;
}
  • Handles all other interrupts by acknowledging and clearing them.

interrupt_handler

void interrupt_handler(void)
{
    unsigned int arg1 = syscall_get_arg1();

    if (arg1 == T_IRQ0 + IRQ_TIMER) {
        timer_intr_handler();
    } else if (arg1 == T_IRQ0 + IRQ_SPURIOUS) {
        spurious_intr_handler();
    } else {
        default_intr_handler();
    }
}
  • Routes interrupts to their respective handlers.


trap

Purpose

Central entry point for handling traps, exceptions, and interrupts.

Code Analysis

void trap(tf_t *tf)
{
    unsigned int cur_pid = get_curid();
    uctx_pool[cur_pid] = *tf;  // Save user context
    set_pdir_base(0);          // Switch to kernel page table
  • Saves the trap frame and switches to the kernel's address space.

    if (T_DIVIDE <= tf->trapno && tf->trapno <= T_SECEV)
        exception_handler();
    else if (T_IRQ0 + IRQ_TIMER <= tf->trapno && tf->trapno <= T_IRQ0 + IRQ_IDE2)
        interrupt_handler();
    else if (tf->trapno == T_SYSCALL)
        syscall_dispatch();
  • Routes traps based on their type:

    • Exceptions: Handled by exception_handler.

    • Interrupts: Routed to interrupt_handler.

    • System Calls: Dispatched to the appropriate syscall handler.

    proc_start_user();  // Restore user mode
}
  • Restores user mode and resumes execution.


Summary of Use Cases

  1. Trap Debugging: trap_dump helps analyze the state during unexpected exceptions.

  2. Page Fault Handling: pgflt_handler handles dynamic memory allocation and copy-on-write scenarios.

  3. Interrupt Routing: interrupt_handler ensures proper routing of timer, spurious, and other interrupts.

  4. Trap Handling: The trap function is the central mechanism for transitioning between user and kernel modes.

Last updated