~ubuntu-branches/ubuntu/precise/linux-lts-saucy/precise-proposed

« back to all changes in this revision

Viewing changes to arch/c6x/kernel/traps.c

  • Committer: Package Import Robot
  • Author(s): Tim Gardner
  • Date: 2013-10-09 13:31:18 UTC
  • Revision ID: package-import@ubuntu.com-20131009133118-l5q5o2hmtz96hefq
Tags: upstream-3.11.0
ImportĀ upstreamĀ versionĀ 3.11.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Port on Texas Instruments TMS320C6x architecture
 
3
 *
 
4
 *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
 
5
 *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
 
6
 *
 
7
 *  This program is free software; you can redistribute it and/or modify
 
8
 *  it under the terms of the GNU General Public License version 2 as
 
9
 *  published by the Free Software Foundation.
 
10
 */
 
11
#include <linux/module.h>
 
12
#include <linux/ptrace.h>
 
13
#include <linux/kallsyms.h>
 
14
#include <linux/bug.h>
 
15
 
 
16
#include <asm/soc.h>
 
17
#include <asm/special_insns.h>
 
18
#include <asm/traps.h>
 
19
 
 
20
int (*c6x_nmi_handler)(struct pt_regs *regs);
 
21
 
 
22
void __init trap_init(void)
 
23
{
 
24
        ack_exception(EXCEPT_TYPE_NXF);
 
25
        ack_exception(EXCEPT_TYPE_EXC);
 
26
        ack_exception(EXCEPT_TYPE_IXF);
 
27
        ack_exception(EXCEPT_TYPE_SXF);
 
28
        enable_exception();
 
29
}
 
30
 
 
31
void show_regs(struct pt_regs *regs)
 
32
{
 
33
        pr_err("\n");
 
34
        show_regs_print_info(KERN_ERR);
 
35
        pr_err("PC: %08lx SP: %08lx\n", regs->pc, regs->sp);
 
36
        pr_err("Status: %08lx ORIG_A4: %08lx\n", regs->csr, regs->orig_a4);
 
37
        pr_err("A0: %08lx  B0: %08lx\n", regs->a0, regs->b0);
 
38
        pr_err("A1: %08lx  B1: %08lx\n", regs->a1, regs->b1);
 
39
        pr_err("A2: %08lx  B2: %08lx\n", regs->a2, regs->b2);
 
40
        pr_err("A3: %08lx  B3: %08lx\n", regs->a3, regs->b3);
 
41
        pr_err("A4: %08lx  B4: %08lx\n", regs->a4, regs->b4);
 
42
        pr_err("A5: %08lx  B5: %08lx\n", regs->a5, regs->b5);
 
43
        pr_err("A6: %08lx  B6: %08lx\n", regs->a6, regs->b6);
 
44
        pr_err("A7: %08lx  B7: %08lx\n", regs->a7, regs->b7);
 
45
        pr_err("A8: %08lx  B8: %08lx\n", regs->a8, regs->b8);
 
46
        pr_err("A9: %08lx  B9: %08lx\n", regs->a9, regs->b9);
 
47
        pr_err("A10: %08lx  B10: %08lx\n", regs->a10, regs->b10);
 
48
        pr_err("A11: %08lx  B11: %08lx\n", regs->a11, regs->b11);
 
49
        pr_err("A12: %08lx  B12: %08lx\n", regs->a12, regs->b12);
 
50
        pr_err("A13: %08lx  B13: %08lx\n", regs->a13, regs->b13);
 
51
        pr_err("A14: %08lx  B14: %08lx\n", regs->a14, regs->dp);
 
52
        pr_err("A15: %08lx  B15: %08lx\n", regs->a15, regs->sp);
 
53
        pr_err("A16: %08lx  B16: %08lx\n", regs->a16, regs->b16);
 
54
        pr_err("A17: %08lx  B17: %08lx\n", regs->a17, regs->b17);
 
55
        pr_err("A18: %08lx  B18: %08lx\n", regs->a18, regs->b18);
 
56
        pr_err("A19: %08lx  B19: %08lx\n", regs->a19, regs->b19);
 
57
        pr_err("A20: %08lx  B20: %08lx\n", regs->a20, regs->b20);
 
58
        pr_err("A21: %08lx  B21: %08lx\n", regs->a21, regs->b21);
 
59
        pr_err("A22: %08lx  B22: %08lx\n", regs->a22, regs->b22);
 
60
        pr_err("A23: %08lx  B23: %08lx\n", regs->a23, regs->b23);
 
61
        pr_err("A24: %08lx  B24: %08lx\n", regs->a24, regs->b24);
 
62
        pr_err("A25: %08lx  B25: %08lx\n", regs->a25, regs->b25);
 
63
        pr_err("A26: %08lx  B26: %08lx\n", regs->a26, regs->b26);
 
64
        pr_err("A27: %08lx  B27: %08lx\n", regs->a27, regs->b27);
 
65
        pr_err("A28: %08lx  B28: %08lx\n", regs->a28, regs->b28);
 
66
        pr_err("A29: %08lx  B29: %08lx\n", regs->a29, regs->b29);
 
67
        pr_err("A30: %08lx  B30: %08lx\n", regs->a30, regs->b30);
 
68
        pr_err("A31: %08lx  B31: %08lx\n", regs->a31, regs->b31);
 
69
}
 
70
 
 
71
void die(char *str, struct pt_regs *fp, int nr)
 
72
{
 
73
        console_verbose();
 
74
        pr_err("%s: %08x\n", str, nr);
 
75
        show_regs(fp);
 
76
 
 
77
        pr_err("Process %s (pid: %d, stackpage=%08lx)\n",
 
78
               current->comm, current->pid, (PAGE_SIZE +
 
79
                                             (unsigned long) current));
 
80
 
 
81
        dump_stack();
 
82
        while (1)
 
83
                ;
 
84
}
 
85
 
 
86
static void die_if_kernel(char *str, struct pt_regs *fp, int nr)
 
87
{
 
88
        if (user_mode(fp))
 
89
                return;
 
90
 
 
91
        die(str, fp, nr);
 
92
}
 
93
 
 
94
 
 
95
/* Internal exceptions */
 
96
static struct exception_info iexcept_table[10] = {
 
97
        { "Oops - instruction fetch", SIGBUS, BUS_ADRERR },
 
98
        { "Oops - fetch packet", SIGBUS, BUS_ADRERR },
 
99
        { "Oops - execute packet", SIGILL, ILL_ILLOPC },
 
100
        { "Oops - undefined instruction", SIGILL, ILL_ILLOPC },
 
101
        { "Oops - resource conflict", SIGILL, ILL_ILLOPC },
 
102
        { "Oops - resource access", SIGILL, ILL_PRVREG },
 
103
        { "Oops - privilege", SIGILL, ILL_PRVOPC },
 
104
        { "Oops - loops buffer", SIGILL, ILL_ILLOPC },
 
105
        { "Oops - software exception", SIGILL, ILL_ILLTRP },
 
106
        { "Oops - unknown exception", SIGILL, ILL_ILLOPC }
 
107
};
 
108
 
 
109
/* External exceptions */
 
110
static struct exception_info eexcept_table[128] = {
 
111
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
112
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
113
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
114
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
115
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
116
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
117
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
118
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
119
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
120
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
121
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
122
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
123
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
124
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
125
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
126
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
127
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
128
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
129
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
130
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
131
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
132
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
133
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
134
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
135
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
136
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
137
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
138
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
139
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
140
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
141
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
142
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
143
 
 
144
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
145
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
146
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
147
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
148
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
149
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
150
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
151
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
152
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
153
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
154
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
155
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
156
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
157
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
158
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
159
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
160
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
161
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
162
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
163
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
164
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
165
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
166
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
167
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
168
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
169
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
170
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
171
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
172
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
173
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
174
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
175
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
176
 
 
177
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
178
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
179
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
180
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
181
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
182
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
183
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
184
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
185
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
186
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
187
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
188
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
189
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
190
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
191
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
192
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
193
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
194
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
195
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
196
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
197
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
198
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
199
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
200
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
201
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
202
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
203
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
204
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
205
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
206
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
207
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
208
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
209
 
 
210
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
211
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
212
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
213
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
214
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
215
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
216
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
217
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
218
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
219
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
220
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
221
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
222
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
223
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
224
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
225
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
226
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
227
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
228
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
229
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
230
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
231
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
232
        { "Oops - external exception", SIGBUS, BUS_ADRERR },
 
233
        { "Oops - CPU memory protection fault", SIGSEGV, SEGV_ACCERR },
 
234
        { "Oops - CPU memory protection fault in L1P", SIGSEGV, SEGV_ACCERR },
 
235
        { "Oops - DMA memory protection fault in L1P", SIGSEGV, SEGV_ACCERR },
 
236
        { "Oops - CPU memory protection fault in L1D", SIGSEGV, SEGV_ACCERR },
 
237
        { "Oops - DMA memory protection fault in L1D", SIGSEGV, SEGV_ACCERR },
 
238
        { "Oops - CPU memory protection fault in L2", SIGSEGV, SEGV_ACCERR },
 
239
        { "Oops - DMA memory protection fault in L2", SIGSEGV, SEGV_ACCERR },
 
240
        { "Oops - EMC CPU memory protection fault", SIGSEGV, SEGV_ACCERR },
 
241
        { "Oops - EMC bus error", SIGBUS, BUS_ADRERR }
 
242
};
 
243
 
 
244
static void do_trap(struct exception_info *except_info, struct pt_regs *regs)
 
245
{
 
246
        unsigned long addr = instruction_pointer(regs);
 
247
        siginfo_t info;
 
248
 
 
249
        if (except_info->code != TRAP_BRKPT)
 
250
                pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n",
 
251
                       except_info->kernel_str, regs->pc,
 
252
                       except_info->signo, except_info->code);
 
253
 
 
254
        die_if_kernel(except_info->kernel_str, regs, addr);
 
255
 
 
256
        info.si_signo = except_info->signo;
 
257
        info.si_errno = 0;
 
258
        info.si_code  = except_info->code;
 
259
        info.si_addr  = (void __user *)addr;
 
260
 
 
261
        force_sig_info(except_info->signo, &info, current);
 
262
}
 
263
 
 
264
/*
 
265
 * Process an internal exception (non maskable)
 
266
 */
 
267
static int process_iexcept(struct pt_regs *regs)
 
268
{
 
269
        unsigned int iexcept_report = get_iexcept();
 
270
        unsigned int iexcept_num;
 
271
 
 
272
        ack_exception(EXCEPT_TYPE_IXF);
 
273
 
 
274
        pr_err("IEXCEPT: PC[0x%lx]\n", regs->pc);
 
275
 
 
276
        while (iexcept_report) {
 
277
                iexcept_num = __ffs(iexcept_report);
 
278
                iexcept_report &= ~(1 << iexcept_num);
 
279
                set_iexcept(iexcept_report);
 
280
                if (*(unsigned int *)regs->pc == BKPT_OPCODE) {
 
281
                        /* This is a breakpoint */
 
282
                        struct exception_info bkpt_exception = {
 
283
                                "Oops - undefined instruction",
 
284
                                  SIGTRAP, TRAP_BRKPT
 
285
                        };
 
286
                        do_trap(&bkpt_exception, regs);
 
287
                        iexcept_report &= ~(0xFF);
 
288
                        set_iexcept(iexcept_report);
 
289
                        continue;
 
290
                }
 
291
 
 
292
                do_trap(&iexcept_table[iexcept_num], regs);
 
293
        }
 
294
        return 0;
 
295
}
 
296
 
 
297
/*
 
298
 * Process an external exception (maskable)
 
299
 */
 
300
static void process_eexcept(struct pt_regs *regs)
 
301
{
 
302
        int evt;
 
303
 
 
304
        pr_err("EEXCEPT: PC[0x%lx]\n", regs->pc);
 
305
 
 
306
        while ((evt = soc_get_exception()) >= 0)
 
307
                do_trap(&eexcept_table[evt], regs);
 
308
 
 
309
        ack_exception(EXCEPT_TYPE_EXC);
 
310
}
 
311
 
 
312
/*
 
313
 * Main exception processing
 
314
 */
 
315
asmlinkage int process_exception(struct pt_regs *regs)
 
316
{
 
317
        unsigned int type;
 
318
        unsigned int type_num;
 
319
        unsigned int ie_num = 9; /* default is unknown exception */
 
320
 
 
321
        while ((type = get_except_type()) != 0) {
 
322
                type_num = fls(type) - 1;
 
323
 
 
324
                switch (type_num) {
 
325
                case EXCEPT_TYPE_NXF:
 
326
                        ack_exception(EXCEPT_TYPE_NXF);
 
327
                        if (c6x_nmi_handler)
 
328
                                (c6x_nmi_handler)(regs);
 
329
                        else
 
330
                                pr_alert("NMI interrupt!\n");
 
331
                        break;
 
332
 
 
333
                case EXCEPT_TYPE_IXF:
 
334
                        if (process_iexcept(regs))
 
335
                                return 1;
 
336
                        break;
 
337
 
 
338
                case EXCEPT_TYPE_EXC:
 
339
                        process_eexcept(regs);
 
340
                        break;
 
341
 
 
342
                case EXCEPT_TYPE_SXF:
 
343
                        ie_num = 8;
 
344
                default:
 
345
                        ack_exception(type_num);
 
346
                        do_trap(&iexcept_table[ie_num], regs);
 
347
                        break;
 
348
                }
 
349
        }
 
350
        return 0;
 
351
}
 
352
 
 
353
static int kstack_depth_to_print = 48;
 
354
 
 
355
static void show_trace(unsigned long *stack, unsigned long *endstack)
 
356
{
 
357
        unsigned long addr;
 
358
        int i;
 
359
 
 
360
        pr_debug("Call trace:");
 
361
        i = 0;
 
362
        while (stack + 1 <= endstack) {
 
363
                addr = *stack++;
 
364
                /*
 
365
                 * If the address is either in the text segment of the
 
366
                 * kernel, or in the region which contains vmalloc'ed
 
367
                 * memory, it *may* be the address of a calling
 
368
                 * routine; if so, print it so that someone tracing
 
369
                 * down the cause of the crash will be able to figure
 
370
                 * out the call path that was taken.
 
371
                 */
 
372
                if (__kernel_text_address(addr)) {
 
373
#ifndef CONFIG_KALLSYMS
 
374
                        if (i % 5 == 0)
 
375
                                pr_debug("\n        ");
 
376
#endif
 
377
                        pr_debug(" [<%08lx>]", addr);
 
378
                        print_symbol(" %s\n", addr);
 
379
                        i++;
 
380
                }
 
381
        }
 
382
        pr_debug("\n");
 
383
}
 
384
 
 
385
void show_stack(struct task_struct *task, unsigned long *stack)
 
386
{
 
387
        unsigned long *p, *endstack;
 
388
        int i;
 
389
 
 
390
        if (!stack) {
 
391
                if (task && task != current)
 
392
                        /* We know this is a kernel stack,
 
393
                           so this is the start/end */
 
394
                        stack = (unsigned long *)thread_saved_ksp(task);
 
395
                else
 
396
                        stack = (unsigned long *)&stack;
 
397
        }
 
398
        endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1)
 
399
                                     & -THREAD_SIZE);
 
400
 
 
401
        pr_debug("Stack from %08lx:", (unsigned long)stack);
 
402
        for (i = 0, p = stack; i < kstack_depth_to_print; i++) {
 
403
                if (p + 1 > endstack)
 
404
                        break;
 
405
                if (i % 8 == 0)
 
406
                        pr_cont("\n         ");
 
407
                pr_cont(" %08lx", *p++);
 
408
        }
 
409
        pr_cont("\n");
 
410
        show_trace(stack, endstack);
 
411
}
 
412
 
 
413
int is_valid_bugaddr(unsigned long addr)
 
414
{
 
415
        return __kernel_text_address(addr);
 
416
}