diff options
Diffstat (limited to 'arch/x86/machine/trap.c')
-rw-r--r-- | arch/x86/machine/trap.c | 354 |
1 files changed, 0 insertions, 354 deletions
diff --git a/arch/x86/machine/trap.c b/arch/x86/machine/trap.c deleted file mode 100644 index 90c8bf66..00000000 --- a/arch/x86/machine/trap.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (c) 2012-2014 Richard Braun. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * - * XXX Many traps have not been tested. Some, such as NMIs, are known to need - * additional configuration and resources to be properly handled. - */ - -#include <assert.h> -#include <stdalign.h> -#include <stdint.h> -#include <stdio.h> - -#include <kern/atomic.h> -#include <kern/init.h> -#include <kern/macros.h> -#include <kern/spinlock.h> -#include <kern/thread.h> -#include <machine/cpu.h> -#include <machine/lapic.h> -#include <machine/pic.h> -#include <machine/pmap.h> -#include <machine/strace.h> -#include <machine/trap.h> - -struct trap_cpu_data { - alignas(CPU_DATA_ALIGN) unsigned char intr_stack[TRAP_STACK_SIZE]; -}; - -static struct trap_cpu_data trap_cpu_data __percpu; - -/* - * Type for interrupt service routines and trap handler functions. - */ -typedef void (*trap_isr_fn_t)(void); - -/* - * Trap handler flags. - */ -#define TRAP_HF_INTR 0x1 /* Enter interrupt context */ - -/* - * Properties of a trap handler. - */ -struct trap_handler { - int flags; - trap_handler_fn_t fn; -}; - -/* - * Table of ISR addresses. - */ -extern trap_isr_fn_t trap_isr_table[CPU_IDT_SIZE]; - -/* - * Array of trap handlers. - */ -static struct trap_handler trap_handlers[CPU_IDT_SIZE] __read_mostly; - -/* - * Global trap lock. - * - * This lock is currently only used to serialize concurrent trap handler - * updates. - * - * Interrupts must be disabled when holding this lock. - */ -static struct spinlock trap_lock; - -static struct trap_handler * -trap_handler_get(unsigned int vector) -{ - assert(vector < ARRAY_SIZE(trap_handlers)); - return &trap_handlers[vector]; -} - -static void __init -trap_handler_init(struct trap_handler *handler, int flags, trap_handler_fn_t fn) -{ - handler->flags = flags; - handler->fn = fn; -} - -static void __init -trap_install(unsigned int vector, int flags, trap_handler_fn_t fn) -{ - assert(vector < ARRAY_SIZE(trap_handlers)); - trap_handler_init(trap_handler_get(vector), flags, fn); -} - -static void -trap_show_thread(void) -{ - struct thread *thread; - - thread = thread_self(); - printf("trap: interrupted thread: %p (%s)\n", thread, thread->name); -} - -static void -trap_double_fault(struct trap_frame *frame) -{ - cpu_halt_broadcast(); - -#ifndef __LP64__ - struct trap_frame frame_store; - struct cpu *cpu; - - /* - * Double faults are catched through a task gate, which makes the given - * frame useless. The interrupted state is automatically saved in the - * main TSS by the processor. Build a proper trap frame from there. - */ - frame = &frame_store; - cpu = cpu_current(); - frame->eax = cpu->tss.eax; - frame->ebx = cpu->tss.ebx; - frame->ecx = cpu->tss.ecx; - frame->edx = cpu->tss.edx; - frame->ebp = cpu->tss.ebp; - frame->esi = cpu->tss.esi; - frame->edi = cpu->tss.edi; - frame->ds = cpu->tss.ds; - frame->es = cpu->tss.es; - frame->fs = cpu->tss.fs; - frame->gs = cpu->tss.gs; - frame->vector = TRAP_DF; - frame->error = 0; - frame->eip = cpu->tss.eip; - frame->cs = cpu->tss.cs; - frame->eflags = cpu->tss.eflags; - frame->esp = cpu->tss.esp; - frame->ss = cpu->tss.ss; -#endif /* __LP64__ */ - - printf("trap: double fault (cpu%u):\n", cpu_id()); - trap_show_thread(); - trap_frame_show(frame); - trap_stack_show(frame); - cpu_halt(); -} - -static void __init -trap_install_double_fault(void) -{ - trap_install(TRAP_DF, TRAP_HF_INTR, trap_double_fault); - cpu_idt_set_double_fault(trap_isr_table[TRAP_DF]); -} - -static void -trap_default(struct trap_frame *frame) -{ - cpu_halt_broadcast(); - printf("trap: unhandled interrupt or exception (cpu%u):\n", cpu_id()); - trap_show_thread(); - trap_frame_show(frame); - trap_stack_show(frame); - cpu_halt(); -} - -static int __init -trap_setup(void) -{ - size_t i; - - spinlock_init(&trap_lock); - - for (i = 0; i < ARRAY_SIZE(trap_isr_table); i++) { - cpu_idt_set_gate(i, trap_isr_table[i]); - } - - for (i = 0; i < ARRAY_SIZE(trap_handlers); i++) { - trap_install(i, TRAP_HF_INTR, trap_default); - } - - /* Architecture defined traps */ - trap_install(TRAP_DE, 0, trap_default); - trap_install(TRAP_DB, 0, trap_default); - trap_install(TRAP_NMI, TRAP_HF_INTR, trap_default); - trap_install(TRAP_BP, 0, trap_default); - trap_install(TRAP_OF, 0, trap_default); - trap_install(TRAP_BR, 0, trap_default); - trap_install(TRAP_UD, 0, trap_default); - trap_install(TRAP_NM, 0, trap_default); - trap_install_double_fault(); - trap_install(TRAP_TS, 0, trap_default); - trap_install(TRAP_NP, 0, trap_default); - trap_install(TRAP_SS, 0, trap_default); - trap_install(TRAP_GP, 0, trap_default); - trap_install(TRAP_PF, 0, trap_default); - trap_install(TRAP_MF, 0, trap_default); - trap_install(TRAP_AC, 0, trap_default); - trap_install(TRAP_MC, TRAP_HF_INTR, trap_default); - trap_install(TRAP_XM, 0, trap_default); - - /* System defined traps */ - trap_install(TRAP_XCALL, TRAP_HF_INTR, cpu_xcall_intr); - trap_install(TRAP_THREAD_SCHEDULE, TRAP_HF_INTR, cpu_thread_schedule_intr); - trap_install(TRAP_CPU_HALT, TRAP_HF_INTR, cpu_halt_intr); -#ifdef CONFIG_PERFMON - trap_install(TRAP_LAPIC_PMC_OF, TRAP_HF_INTR, lapic_pmc_overflow_intr); -#endif - trap_install(TRAP_LAPIC_TIMER, TRAP_HF_INTR, lapic_timer_intr); - trap_install(TRAP_LAPIC_ERROR, TRAP_HF_INTR, lapic_error_intr); - trap_install(TRAP_LAPIC_SPURIOUS, TRAP_HF_INTR, lapic_spurious_intr); - - return 0; -} - -INIT_OP_DEFINE(trap_setup); - -void -trap_main(struct trap_frame *frame) -{ - struct trap_handler *handler; - trap_handler_fn_t fn; - - assert(!cpu_intr_enabled()); - - handler = trap_handler_get(frame->vector); - - if (handler->flags & TRAP_HF_INTR) { - thread_intr_enter(); - } - - fn = atomic_load(&handler->fn, ATOMIC_RELAXED); - fn(frame); - - if (handler->flags & TRAP_HF_INTR) { - thread_intr_leave(); - } - - assert(!cpu_intr_enabled()); -} - -void -trap_register(unsigned int vector, trap_handler_fn_t handler_fn) -{ - unsigned long flags; - - spinlock_lock_intr_save(&trap_lock, &flags); - trap_install(vector, TRAP_HF_INTR, handler_fn); - spinlock_unlock_intr_restore(&trap_lock, flags); -} - -#ifdef __LP64__ - -void -trap_frame_show(struct trap_frame *frame) -{ - printf("trap: rax: %016lx rbx: %016lx rcx: %016lx\n" - "trap: rdx: %016lx rbp: %016lx rsi: %016lx\n" - "trap: rdi: %016lx r8: %016lx r9: %016lx\n" - "trap: r10: %016lx r11: %016lx r12: %016lx\n" - "trap: r13: %016lx r14: %016lx r15: %016lx\n" - "trap: vector: %lu error: %08lx\n" - "trap: rip: %016lx cs: %lu rflags: %016lx\n" - "trap: rsp: %016lx ss: %lu\n", - (unsigned long)frame->rax, (unsigned long)frame->rbx, - (unsigned long)frame->rcx, (unsigned long)frame->rdx, - (unsigned long)frame->rbp, (unsigned long)frame->rsi, - (unsigned long)frame->rdi, (unsigned long)frame->r8, - (unsigned long)frame->r9, (unsigned long)frame->r10, - (unsigned long)frame->r11, (unsigned long)frame->r12, - (unsigned long)frame->r13, (unsigned long)frame->r14, - (unsigned long)frame->r15, (unsigned long)frame->vector, - (unsigned long)frame->error, (unsigned long)frame->rip, - (unsigned long)frame->cs, (unsigned long)frame->rflags, - (unsigned long)frame->rsp, (unsigned long)frame->ss); - - /* XXX Until the page fault handler is written */ - if (frame->vector == 14) { - printf("trap: cr2: %016lx\n", (unsigned long)cpu_get_cr2()); - } -} - -#else /* __LP64__ */ - -void -trap_frame_show(struct trap_frame *frame) -{ - unsigned long esp, ss; - - if ((frame->cs & CPU_PL_USER) || (frame->vector == TRAP_DF)) { - esp = frame->esp; - ss = frame->ss; - } else { - esp = 0; - ss = 0; - } - - printf("trap: eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n" - "trap: ebp: %08lx esi: %08lx edi: %08lx\n" - "trap: ds: %hu es: %hu fs: %hu gs: %hu\n" - "trap: vector: %lu error: %08lx\n" - "trap: eip: %08lx cs: %lu eflags: %08lx\n" - "trap: esp: %08lx ss: %lu\n", - (unsigned long)frame->eax, (unsigned long)frame->ebx, - (unsigned long)frame->ecx, (unsigned long)frame->edx, - (unsigned long)frame->ebp, (unsigned long)frame->esi, - (unsigned long)frame->edi, (unsigned short)frame->ds, - (unsigned short)frame->es, (unsigned short)frame->fs, - (unsigned short)frame->gs, (unsigned long)frame->vector, - (unsigned long)frame->error, (unsigned long)frame->eip, - (unsigned long)frame->cs, (unsigned long)frame->eflags, - (unsigned long)esp, (unsigned long)ss); - - - /* XXX Until the page fault handler is written */ - if (frame->vector == 14) { - printf("trap: cr2: %08lx\n", (unsigned long)cpu_get_cr2()); - } -} - -#endif /* __LP64__ */ - -void -trap_stack_show(struct trap_frame *frame) -{ -#ifdef __LP64__ - strace_show(frame->rip, frame->rbp); -#else /* __LP64__ */ - strace_show(frame->eip, frame->ebp); -#endif /* __LP64__ */ -} - -void * -trap_get_interrupt_stack(const struct trap_frame *frame) -{ - struct trap_cpu_data *cpu_data; - struct trap_handler *handler; - - handler = trap_handler_get(frame->vector); - - if ((handler->flags & TRAP_HF_INTR) && !thread_interrupted()) { - cpu_data = cpu_local_ptr(trap_cpu_data); - return cpu_data->intr_stack + sizeof(cpu_data->intr_stack); - } else { - return NULL; - } -} |