⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 traps.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************** * arch/x86/traps.c *  * Modifications to Linux original are copyright (c) 2002-2004, K A Fraser *  * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* *  Copyright (C) 1991, 1992  Linus Torvalds * *  Pentium III FXSR, SSE support * Gareth Hughes <gareth@valinux.com>, May 2000 */#include <xen/config.h>#include <xen/init.h>#include <xen/sched.h>#include <xen/lib.h>#include <xen/errno.h>#include <xen/mm.h>#include <xen/console.h>#include <xen/shutdown.h>#include <asm/regs.h>#include <xen/delay.h>#include <xen/event.h>#include <xen/spinlock.h>#include <xen/irq.h>#include <xen/perfc.h>#include <xen/softirq.h>#include <xen/domain_page.h>#include <xen/symbols.h>#include <xen/iocap.h>#include <xen/nmi.h>#include <xen/version.h>#include <xen/kexec.h>#include <xen/trace.h>#include <asm/paging.h>#include <asm/system.h>#include <asm/io.h>#include <asm/atomic.h>#include <asm/desc.h>#include <asm/debugreg.h>#include <asm/smp.h>#include <asm/flushtlb.h>#include <asm/uaccess.h>#include <asm/i387.h>#include <asm/debugger.h>#include <asm/msr.h>#include <asm/shared.h>#include <asm/x86_emulate.h>#include <asm/traps.h>#include <asm/hvm/vpt.h>#include <public/arch-x86/cpuid.h>/* * opt_nmi: one of 'ignore', 'dom0', or 'fatal'. *  fatal:  Xen prints diagnostic message and then hangs. *  dom0:   The NMI is virtualised to DOM0. *  ignore: The NMI error is cleared and ignored. */#ifdef NDEBUGchar opt_nmi[10] = "dom0";#elsechar opt_nmi[10] = "fatal";#endifstring_param("nmi", opt_nmi);DEFINE_PER_CPU(u32, ler_msr);/* Master table, used by CPU0. */idt_entry_t idt_table[IDT_ENTRIES];/* Pointer to the IDT of every CPU. */idt_entry_t *idt_tables[NR_CPUS] __read_mostly;#define DECLARE_TRAP_HANDLER(_name)                     \asmlinkage void _name(void);                            \asmlinkage void do_ ## _name(struct cpu_user_regs *regs)DECLARE_TRAP_HANDLER(divide_error);DECLARE_TRAP_HANDLER(debug);DECLARE_TRAP_HANDLER(nmi);DECLARE_TRAP_HANDLER(int3);DECLARE_TRAP_HANDLER(overflow);DECLARE_TRAP_HANDLER(bounds);DECLARE_TRAP_HANDLER(invalid_op);DECLARE_TRAP_HANDLER(device_not_available);DECLARE_TRAP_HANDLER(coprocessor_segment_overrun);DECLARE_TRAP_HANDLER(invalid_TSS);DECLARE_TRAP_HANDLER(segment_not_present);DECLARE_TRAP_HANDLER(stack_segment);DECLARE_TRAP_HANDLER(general_protection);DECLARE_TRAP_HANDLER(page_fault);DECLARE_TRAP_HANDLER(coprocessor_error);DECLARE_TRAP_HANDLER(simd_coprocessor_error);DECLARE_TRAP_HANDLER(machine_check);DECLARE_TRAP_HANDLER(alignment_check);DECLARE_TRAP_HANDLER(spurious_interrupt_bug);long do_set_debugreg(int reg, unsigned long value);unsigned long do_get_debugreg(int reg);void (*ioemul_handle_quirk)(    u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs);static int debug_stack_lines = 20;integer_param("debug_stack_lines", debug_stack_lines);static int opt_ler;boolean_param("ler", opt_ler);#ifdef CONFIG_X86_32#define stack_words_per_line 8#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)&regs->esp)#else#define stack_words_per_line 4#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->rsp)#endifstatic void show_guest_stack(struct cpu_user_regs *regs){    int i;    struct vcpu *curr = current;    unsigned long *stack, addr;    if ( is_hvm_vcpu(curr) )        return;    if ( is_pv_32on64_vcpu(curr) )    {        compat_show_guest_stack(regs, debug_stack_lines);        return;    }    if ( vm86_mode(regs) )    {        stack = (unsigned long *)((regs->ss << 4) + (regs->esp & 0xffff));        printk("Guest stack trace from ss:sp = %04x:%04x (VM86)\n  ",               regs->ss, (uint16_t)(regs->esp & 0xffff));    }    else    {        stack = (unsigned long *)regs->esp;        printk("Guest stack trace from "__OP"sp=%p:\n  ", stack);    }    for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )    {        if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )            break;        if ( get_user(addr, stack) )        {            if ( i != 0 )                printk("\n    ");            printk("Fault while accessing guest memory.");            i = 1;            break;        }        if ( (i != 0) && ((i % stack_words_per_line) == 0) )            printk("\n  ");        printk(" %p", _p(addr));        stack++;    }    if ( i == 0 )        printk("Stack empty.");    printk("\n");}#if !defined(CONFIG_FRAME_POINTER)static void show_trace(struct cpu_user_regs *regs){    unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;    printk("Xen call trace:\n   ");    printk("[<%p>]", _p(regs->eip));    print_symbol(" %s\n   ", regs->eip);    while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 )    {        addr = *stack++;        if ( is_kernel_text(addr) || is_kernel_inittext(addr) )        {            printk("[<%p>]", _p(addr));            print_symbol(" %s\n   ", addr);        }    }    printk("\n");}#elsestatic void show_trace(struct cpu_user_regs *regs){    unsigned long *frame, next, addr, low, high;    printk("Xen call trace:\n   ");    printk("[<%p>]", _p(regs->eip));    print_symbol(" %s\n   ", regs->eip);    /* Bounds for range of valid frame pointer. */    low  = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2);    high = (low & ~(STACK_SIZE - 1)) +         (STACK_SIZE - sizeof(struct cpu_info) - 2*sizeof(unsigned long));    /* The initial frame pointer. */    next = regs->ebp;    for ( ; ; )    {        /* Valid frame pointer? */        if ( (next < low) || (next >= high) )        {            /*             * Exception stack frames have a different layout, denoted by an             * inverted frame pointer.             */            next = ~next;            if ( (next < low) || (next >= high) )                break;            frame = (unsigned long *)next;            next  = frame[0];            addr  = frame[(offsetof(struct cpu_user_regs, eip) -                           offsetof(struct cpu_user_regs, ebp))                         / BYTES_PER_LONG];        }        else        {            /* Ordinary stack frame. */            frame = (unsigned long *)next;            next  = frame[0];            addr  = frame[1];        }        printk("[<%p>]", _p(addr));        print_symbol(" %s\n   ", addr);        low = (unsigned long)&frame[2];    }    printk("\n");}#endifvoid show_stack(struct cpu_user_regs *regs){    unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;    int i;    if ( guest_mode(regs) )        return show_guest_stack(regs);    printk("Xen stack trace from "__OP"sp=%p:\n  ", stack);    for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )    {        if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )            break;        if ( (i != 0) && ((i % stack_words_per_line) == 0) )            printk("\n  ");        addr = *stack++;        printk(" %p", _p(addr));    }    if ( i == 0 )        printk("Stack empty.");    printk("\n");    show_trace(regs);}void show_stack_overflow(unsigned int cpu, unsigned long esp){#ifdef MEMORY_GUARD    unsigned long esp_top, esp_bottom;    unsigned long *stack, addr;    esp_bottom = (esp | (STACK_SIZE - 1)) + 1;    esp_top    = esp_bottom - PRIMARY_STACK_SIZE;    printk("Valid stack range: %p-%p, sp=%p, tss.esp0=%p\n",           (void *)esp_top, (void *)esp_bottom, (void *)esp,           (void *)init_tss[cpu].esp0);    /* Trigger overflow trace if %esp is within 512 bytes of the guard page. */    if ( ((unsigned long)(esp - esp_top) > 512) &&         ((unsigned long)(esp_top - esp) > 512) )    {        printk("No stack overflow detected. Skipping stack trace.\n");        return;    }    if ( esp < esp_top )        esp = esp_top;    printk("Xen stack overflow (dumping trace %p-%p):\n   ",           (void *)esp, (void *)esp_bottom);    stack = (unsigned long *)esp;    while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 )    {        addr = *stack++;        if ( is_kernel_text(addr) || is_kernel_inittext(addr) )        {            printk("%p: [<%p>]", stack, _p(addr));            print_symbol(" %s\n   ", addr);        }    }    printk("\n");#endif}void show_execution_state(struct cpu_user_regs *regs){    show_registers(regs);    show_stack(regs);}void vcpu_show_execution_state(struct vcpu *v){    printk("*** Dumping Dom%d vcpu#%d state: ***\n",           v->domain->domain_id, v->vcpu_id);    if ( v == current )    {        show_execution_state(guest_cpu_user_regs());        return;    }    vcpu_pause(v); /* acceptably dangerous */    vcpu_show_registers(v);    /* Todo: map arbitrary vcpu's top guest stack page here. */    if ( (v->domain == current->domain) &&         guest_kernel_mode(v, &v->arch.guest_context.user_regs) )        show_guest_stack(&v->arch.guest_context.user_regs);    vcpu_unpause(v);}char *trapstr(int trapnr){    static char *strings[] = {         "divide error", "debug", "nmi", "bkpt", "overflow", "bounds",         "invalid opcode", "device not available", "double fault",         "coprocessor segment", "invalid tss", "segment not found",         "stack error", "general protection fault", "page fault",         "spurious interrupt", "coprocessor error", "alignment check",         "machine check", "simd error"    };    if ( (trapnr < 0) || (trapnr >= ARRAY_SIZE(strings)) )        return "???";    return strings[trapnr];}/* * This is called for faults at very unexpected times (e.g., when interrupts * are disabled). In such situations we can't do much that is safe. We try to * print out some tracing and then we just spin. */asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs){    static DEFINE_PER_CPU(char, depth);    /*     * In some cases, we can end up in a vicious cycle of fatal_trap()s     * within fatal_trap()s. We give the problem a couple of iterations to     * bottom out, and then we just panic.     */    if ( ++this_cpu(depth) < 3 )    {        watchdog_disable();        console_start_sync();        show_execution_state(regs);        if ( trapnr == TRAP_page_fault )        {            unsigned long cr2 = read_cr2();            printk("Faulting linear address: %p\n", _p(cr2));            show_page_walk(cr2);        }    }    panic("FATAL TRAP: vector = %d (%s)\n"          "[error_code=%04x] %s\n",          trapnr, trapstr(trapnr), regs->error_code,          (regs->eflags & X86_EFLAGS_IF) ? "" : ", IN INTERRUPT CONTEXT");}static void do_guest_trap(    int trapnr, const struct cpu_user_regs *regs, int use_error_code){    struct vcpu *v = current;    struct trap_bounce *tb;    const struct trap_info *ti;    trace_pv_trap(trapnr, regs->eip, use_error_code, regs->error_code);    tb = &v->arch.trap_bounce;    ti = &v->arch.guest_context.trap_ctxt[trapnr];    tb->flags = TBF_EXCEPTION;    tb->cs    = ti->cs;    tb->eip   = ti->address;    if ( use_error_code )    {        tb->flags |= TBF_EXCEPTION_ERRCODE;        tb->error_code = regs->error_code;    }    if ( TI_GET_IF(ti) )        tb->flags |= TBF_INTERRUPT;    if ( unlikely(null_trap_bounce(v, tb)) )        gdprintk(XENLOG_WARNING, "Unhandled %s fault/trap [#%d] "                 "on VCPU %d [ec=%04x]\n",                 trapstr(trapnr), trapnr, v->vcpu_id, regs->error_code);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -