Project

General

Profile

Statistics
| Branch: | Revision:

root / prex-0.9.0 / bsp / hal / x86 / arch / trap.c @ 03e9c04a

History | View | Annotate | Download (5.47 KB)

1 03e9c04a Brad Neuman
/*-
2
 * Copyright (c) 2005-2009, Kohsuke Ohtani
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the author nor the names of any co-contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
/*
31
 * trap.c - called from the trap handler when a processor trap occurs.
32
 */
33
34
#include <sys/signal.h>
35
#include <kernel.h>
36
#include <hal.h>
37
#include <exception.h>
38
#include <task.h>
39
#include <cpu.h>
40
#include <trap.h>
41
#include <cpufunc.h>
42
#include <context.h>
43
#include <locore.h>
44
45
#ifdef DEBUG
46
/*
47
 * Trap name.
48
 */
49
static const char *const trap_name[] = {
50
        "Divide error",                /*  0 */
51
        "Debug trap",                /*  1 */
52
        "NMI",                        /*  2 */
53
        "Breakpoint",                /*  3 */
54
        "Overflow",                /*  4 */
55
        "Bounds check",                /*  5 */
56
        "Invalid opecode",        /*  6 */
57
        "Device not available",        /*  7 */
58
        "Double fault",                /*  8 */
59
        "Coprocessor overrun",        /*  9 */
60
        "Invalid TSS",                /* 10 */
61
        "Segment not present",        /* 11 */
62
        "Stack bounds",                /* 12 */
63
        "General Protection",        /* 13 */
64
        "Page fault",                /* 14 */
65
        "Reserved",                /* 15 */
66
        "Coprocessor error",        /* 16 */
67
        "Alignment check",        /* 17 */
68
        "Cache flush denied"        /* 18 */
69
};
70
#define MAXTRAP (sizeof(trap_name) / sizeof(void *) - 1)
71
#endif        /* DEBUG */
72
73
/*
74
 * Trap/exception mapping table.
75
 * x86 trap code is translated to the architecture
76
 * independent exception code.
77
 */
78
static const int exception_map[] = {
79
        SIGFPE,                /*  0: Divide error */
80
        SIGTRAP,        /*  1: Debug trap */
81
        SIGILL,                /*  2: NMI */
82
        SIGTRAP,        /*  3: Breakpoint */
83
        SIGFPE,                /*  4: Overflow */
84
        SIGILL,                /*  5: Bounds check */
85
        SIGILL,                /*  6: Invalid opecode */
86
        SIGFPE,                /*  7: Device not available */
87
        SIGILL,                /*  8: Double fault */
88
        SIGFPE,                /*  9: Coprocessor overrun */
89
        SIGSEGV,        /* 10: Invalid TSS */
90
        SIGSEGV,        /* 11: Segment not present */
91
        SIGSEGV,        /* 12: Stack bounds */
92
        SIGILL,                /* 13: General Protection fault */
93
        SIGSEGV,        /* 14: Page fault */
94
        SIGILL,                /* 15: Reserved */
95
        SIGFPE,                /* 16: Coprocessor error */
96
        SIGILL,                /* 17: Alignment check */
97
        SIGILL,                /* 18: Cache flush denied */
98
};
99
100
/*
101
 * Trap handler
102
 * Invoke the exception handler if it is needed.
103
 */
104
void
105
trap_handler(struct cpu_regs *regs)
106
{
107
        u_long trap_no = regs->trap_no;
108
109
        if (trap_no > 18)
110
                panic("Unknown trap");
111
        else if (trap_no == 2)
112
                panic("NMI");
113
114
        /*
115
         * Check whether this trap is kernel page fault caused
116
         * by known routine to access user space like copyin().
117
         * If so, we change the return address of this exception.
118
         */
119
        if (trap_no == 14 && regs->cs == KERNEL_CS &&
120
            (regs->eip == (uint32_t)known_fault1 ||
121
             regs->eip == (uint32_t)known_fault2 ||
122
             regs->eip == (uint32_t)known_fault3)) {
123
                DPRINTF(("\n*** Detect Fault! address=%x task=%s ***\n",
124
                         get_cr2(), curtask->name));
125
                regs->eip = (uint32_t)copy_fault;
126
                return;
127
        }
128
#ifdef DEBUG
129
        printf("============================\n");
130
        printf("Trap %x: %s\n", (u_int)trap_no, trap_name[trap_no]);
131
        if (trap_no == 14)
132
                printf(" Fault address=%x\n", get_cr2());
133
        printf("============================\n");
134
        trap_dump(regs);
135
        if (regs->cs == KERNEL_CS) {
136
                printf("Trap in kernel!\n");
137
                interrupt_mask(0);
138
                spl0();
139
        }
140
        for (;;) ;
141
#endif
142
        if (regs->cs == KERNEL_CS)
143
                panic("Kernel exception");
144
145
        exception_mark(exception_map[trap_no]);
146
        exception_deliver();
147
}
148
149
#ifdef DEBUG
150
void
151
trap_dump(struct cpu_regs *r)
152
{
153
        uint32_t ss, esp, *fp;
154
        u_int i;
155
        int spl;
156
157
        /* Get current spl */
158
        spl = splhigh();
159
        splx(spl);
160
161
        if (r->cs & 3) {
162
                ss = r->ss;
163
                esp = r->esp;
164
        } else {
165
                ss = r->ds;
166
                esp = (uint32_t)r;
167
        }
168
        printf("Trap frame %08lx error %x\n", (long)r, r->err_code);
169
        printf(" eax %08x ebx %08x ecx %08x edx %08x esi %08x edi %08x\n",
170
               r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi);
171
        printf(" eip %08x esp %08x ebp %08x eflags %08x\n",
172
               r->eip, esp, r->ebp, r->eflags);
173
        printf(" cs  %08x ss  %08x ds  %08x es  %08x esp0 %08x\n",
174
               r->cs, ss, r->ds, r->es, tss_get());
175
176
        printf(" >> interrupt is %s\n", (spl == 0) ? "enabled" : "disabled");
177
178
        printf(" >> task=%s\n", curtask->name);
179
180
        if (r->cs == KERNEL_CS) {
181
                printf("Stack trace:\n");
182
                fp = (uint32_t *)r->ebp;
183
                for (i = 0; i < 8; i++) {
184
                        if (user_area(fp))
185
                                break;
186
                        fp = (uint32_t *)(*fp);        /* XXX: may cause fault */
187
                        if (!(*(fp + 1) && *fp))
188
                                break;
189
                        printf(" %08x\n", *(fp + 1));
190
                }
191
        }
192
}
193
#endif /* !DEBUG */