OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [mips/] [kernel/] [traps.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1624 jcastillo
/*
2
 *  arch/mips/kernel/traps.c
3
 *
4
 * This file is subject to the terms and conditions of the GNU General Public
5
 * License.  See the file "COPYING" in the main directory of this archive
6
 * for more details.
7
 */
8
 
9
/*
10
 * 'traps.c' handles hardware traps and faults after we have saved some
11
 * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
12
 * to mainly kill the offending process (probably by giving it a signal,
13
 * but possibly by killing it outright if necessary).
14
 *
15
 * FIXME: This is the place for a fpu emulator.
16
 */
17
#include <linux/head.h>
18
#include <linux/sched.h>
19
#include <linux/kernel.h>
20
#include <linux/signal.h>
21
#include <linux/string.h>
22
#include <linux/types.h>
23
#include <linux/errno.h>
24
#include <linux/ptrace.h>
25
#include <linux/timer.h>
26
#include <linux/mm.h>
27
 
28
#include <asm/vector.h>
29
#include <asm/page.h>
30
#include <asm/pgtable.h>
31
#include <asm/system.h>
32
#include <asm/segment.h>
33
#include <asm/io.h>
34
#include <asm/mipsregs.h>
35
#include <asm/bootinfo.h>
36
 
37
static inline void console_verbose(void)
38
{
39
        extern int console_loglevel;
40
        console_loglevel = 15;
41
}
42
 
43
/*
44
 * Machine specific interrupt handlers
45
 */
46
extern asmlinkage void acer_pica_61_handle_int(void);
47
extern asmlinkage void decstation_handle_int(void);
48
extern asmlinkage void deskstation_rpc44_handle_int(void);
49
extern asmlinkage void deskstation_tyne_handle_int(void);
50
extern asmlinkage void mips_magnum_4000_handle_int(void);
51
 
52
extern asmlinkage void handle_mod(void);
53
extern asmlinkage void handle_tlbl(void);
54
extern asmlinkage void handle_tlbs(void);
55
extern asmlinkage void handle_adel(void);
56
extern asmlinkage void handle_ades(void);
57
extern asmlinkage void handle_ibe(void);
58
extern asmlinkage void handle_dbe(void);
59
extern asmlinkage void handle_sys(void);
60
extern asmlinkage void handle_bp(void);
61
extern asmlinkage void handle_ri(void);
62
extern asmlinkage void handle_cpu(void);
63
extern asmlinkage void handle_ov(void);
64
extern asmlinkage void handle_tr(void);
65
extern asmlinkage void handle_vcei(void);
66
extern asmlinkage void handle_fpe(void);
67
extern asmlinkage void handle_vced(void);
68
extern asmlinkage void handle_watch(void);
69
extern asmlinkage void handle_reserved(void);
70
 
71
static char *cpu_names[] = CPU_NAMES;
72
 
73
unsigned long page_colour_mask;
74
 
75
int kstack_depth_to_print = 24;
76
 
77
/*
78
 * These constant is for searching for possible module text segments.
79
 * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
80
 */
81
#define MODULE_RANGE (8*1024*1024)
82
 
83
void die_if_kernel(char * str, struct pt_regs * regs, long err)
84
{
85
        int     i;
86
        int     *stack;
87
        u32     *sp, *pc, addr, module_start, module_end;
88
        extern  char start_kernel, _etext;
89
 
90
        if ((regs->cp0_status & (ST0_ERL|ST0_EXL)) == 0)
91
                return;
92
 
93
        sp = (u32 *)regs->reg29;
94
        pc = (u32 *)regs->cp0_epc;
95
 
96
        console_verbose();
97
        printk("%s: %08lx\n", str, err );
98
 
99
        show_regs(regs);
100
 
101
        /*
102
         * Dump the stack
103
         */
104
        if (STACK_MAGIC != *(u32 *)current->kernel_stack_page)
105
                printk("Corrupted stack page\n");
106
        printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ",
107
                current->comm, current->pid, current->kernel_stack_page);
108
        for(i=0;i<5;i++)
109
                printk("%08x ", *sp++);
110
        stack = (int *) sp;
111
        for(i=0; i < kstack_depth_to_print; i++) {
112
                if (((u32) stack & (PAGE_SIZE -1)) == 0)
113
                        break;
114
                if (i && ((i % 8) == 0))
115
                        printk("\n       ");
116
                printk("%08lx ", get_user(stack++));
117
        }
118
        printk("\nCall Trace: ");
119
        stack = (int *)sp;
120
        i = 1;
121
        module_start = VMALLOC_START;
122
        module_end = module_start + MODULE_RANGE;
123
        while (((u32)stack & (PAGE_SIZE -1)) != 0) {
124
                addr = get_user(stack++);
125
                /*
126
                 * If the address is either in the text segment of the
127
                 * kernel, or in the region which contains vmalloc'ed
128
                 * memory, it *may* be the address of a calling
129
                 * routine; if so, print it so that someone tracing
130
                 * down the cause of the crash will be able to figure
131
                 * out the call path that was taken.
132
                 */
133
                if (((addr >= (u32) &start_kernel) &&
134
                     (addr <= (u32) &_etext)) ||
135
                    ((addr >= module_start) && (addr <= module_end))) {
136
                        if (i && ((i % 8) == 0))
137
                                printk("\n       ");
138
                        printk("%08x ", addr);
139
                        i++;
140
                }
141
        }
142
 
143
        printk("\nCode : ");
144
        if ((!verify_area(VERIFY_READ, pc, 5 * sizeof(*pc)) ||
145
             KSEGX(pc) == KSEG0 ||
146
             KSEGX(pc) == KSEG1) &&
147
            (((unsigned long) pc & 3) == 0))
148
        {
149
                for(i=0;i<5;i++)
150
                        printk("%08x ", *pc++);
151
                printk("\n");
152
        }
153
        else
154
                printk("(Bad address in epc)\n");
155
while(1);
156
        do_exit(SIGSEGV);
157
}
158
 
159
static void
160
fix_ade(struct pt_regs *regs, int write)
161
{
162
        printk("Received address error (ade%c)\n", write ? 's' : 'l');
163
        panic("Fixing address errors not implemented yet");
164
}
165
 
166
void do_adel(struct pt_regs *regs)
167
{
168
        if(current->tss.mflags & MF_FIXADE)
169
        {
170
                fix_ade(regs, 0);
171
                return;
172
        }
173
        show_regs(regs);
174
while(1);
175
        dump_tlb_nonwired();
176
        send_sig(SIGSEGV, current, 1);
177
}
178
 
179
void do_ades(struct pt_regs *regs)
180
{
181
        unsigned long   pc = regs->cp0_epc;
182
        int     i;
183
 
184
        if(current->tss.mflags & MF_FIXADE)
185
        {
186
                fix_ade(regs, 1);
187
                return;
188
        }
189
while(1);
190
        for(i=0; i<NR_TASKS;i++)
191
                if(task[i] && task[i]->pid >= 2)
192
                {
193
                        printk("Process %d\n", task[i]->pid);
194
                        dump_list_process(task[i], pc);
195
                }
196
        show_regs(regs);
197
        dump_tlb_nonwired();
198
        send_sig(SIGSEGV, current, 1);
199
}
200
 
201
/*
202
 * The ibe/dbe exceptions are signaled by onboard hardware and should get
203
 * a board specific handlers to get maximum available information. Bus
204
 * errors are always symptom of hardware malfunction or a kernel error.
205
 *
206
 * FIXME: Linux/68k sends a SIGSEGV for a buserror which seems to be wrong.
207
 * This is certainly wrong. Actually, all hardware errors (ades,adel,ibe,dbe)
208
 * are bus errors and therefor should send a SIGBUS! (Andy)
209
 */
210
void do_ibe(struct pt_regs *regs)
211
{
212
show_regs(regs);
213
while(1);
214
        send_sig(SIGBUS, current, 1);
215
}
216
 
217
void do_dbe(struct pt_regs *regs)
218
{
219
show_regs(regs);
220
while(1);
221
        send_sig(SIGBUS, current, 1);
222
}
223
 
224
void do_ov(struct pt_regs *regs)
225
{
226
show_regs(regs);
227
while(1);
228
        send_sig(SIGFPE, current, 1);
229
}
230
 
231
void do_fpe(struct pt_regs *regs)
232
{
233
show_regs(regs);
234
while(1);
235
        send_sig(SIGFPE, current, 1);
236
}
237
 
238
void do_bp(struct pt_regs *regs)
239
{
240
show_regs(regs);
241
while(1);
242
        send_sig(SIGILL, current, 1);
243
}
244
 
245
void do_tr(struct pt_regs *regs)
246
{
247
show_regs(regs);
248
while(1);
249
        send_sig(SIGILL, current, 1);
250
}
251
 
252
void do_ri(struct pt_regs *regs)
253
{
254
        int     i;
255
 
256
        for(i=0; i<NR_TASKS;i++)
257
                if(task[i] && task[i]->pid >= 2)
258
                {
259
                        printk("Process %d\n", task[i]->pid);
260
                        dump_list_process(task[i], 0x7ffff000);
261
                }
262
        show_regs(regs);
263
while(1);
264
        send_sig(SIGILL, current, 1);
265
}
266
 
267
void do_cpu(struct pt_regs *regs)
268
{
269
        unsigned int cpid;
270
 
271
        cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
272
        switch(cpid)
273
        {
274
        case 1:
275
                regs->cp0_status |= ST0_CU1;
276
                break;
277
        case 0:
278
                /*
279
                 * CPU for cp0 can only happen in user mode
280
                 */
281
        case 2:
282
        case 3:
283
                send_sig(SIGILL, current, 1);
284
                break;
285
        }
286
}
287
 
288
void do_vcei(struct pt_regs *regs)
289
{
290
        /*
291
         * Only possible on R4[04]00[SM]C. No handler because
292
         * I don't have such a cpu.
293
         */
294
        panic("Caught VCEI exception - can't handle yet\n");
295
}
296
 
297
void do_vced(struct pt_regs *regs)
298
{
299
        /*
300
         * Only possible on R4[04]00[SM]C. No handler because
301
         * I don't have such a cpu.
302
         */
303
        panic("Caught VCED exception - can't handle yet\n");
304
}
305
 
306
void do_watch(struct pt_regs *regs)
307
{
308
        panic("Caught WATCH exception - can't handle yet\n");
309
}
310
 
311
void do_reserved(struct pt_regs *regs)
312
{
313
        /*
314
         * Game over - no way to handle this if it ever occurs.
315
         * Most probably caused by a new unknown cpu type or
316
         * after another deadly hard/software error.
317
         */
318
        panic("Caught reserved exception - can't handle.\n");
319
}
320
 
321
void trap_init(void)
322
{
323
        unsigned long   i;
324
        void watch_set(unsigned long, unsigned long);
325
 
326
        if(boot_info.machtype == MACH_MIPS_MAGNUM_4000)
327
                EISA_bus = 1;
328
 
329
        /*
330
         * Setup default vectors
331
         */
332
        for (i=0;i<=31;i++)
333
                set_except_vector(i, handle_reserved);
334
 
335
        /*
336
         * Handling the following exceptions depends mostly of the cpu type
337
         */
338
        switch(boot_info.cputype) {
339
        /*
340
         * The R10000 is in most aspects similar to the R4400.  It however
341
         * should get some special optimizations.
342
         */
343
        case CPU_R10000:
344
                write_32bit_cp0_register(CP0_FRAMEMASK, 0);
345
                set_cp0_status(ST0_XX, ST0_XX);
346
                page_colour_mask = 0x3000;
347
                panic("CPU too expensive - making holiday in the ANDES!");
348
                break;
349
        case CPU_R4000MC:
350
        case CPU_R4400MC:
351
        case CPU_R4000SC:
352
        case CPU_R4400SC:
353
                /*
354
                 * Handlers not implemented yet.  If should ever be used -
355
                 * otherwise it's a bug in the Linux/MIPS kernel, anyway.
356
                 */
357
                set_except_vector(14, handle_vcei);
358
                set_except_vector(31, handle_vced);
359
        case CPU_R4000PC:
360
        case CPU_R4400PC:
361
        case CPU_R4200:
362
     /* case CPU_R4300: */
363
                /*
364
                 * Use watch exception to trap on access to address zero
365
                 */
366
                set_except_vector(23, handle_watch);
367
                watch_set(KSEG0, 3);
368
        case CPU_R4600:
369
                set_except_vector(1, handle_mod);
370
                set_except_vector(2, handle_tlbl);
371
                set_except_vector(3, handle_tlbs);
372
                set_except_vector(4, handle_adel);
373
                set_except_vector(5, handle_ades);
374
                /*
375
                 * The following two are signaled by onboard hardware and
376
                 * should get board specific handlers to get maximum
377
                 * available information.
378
                 */
379
                set_except_vector(6, handle_ibe);
380
                set_except_vector(7, handle_dbe);
381
 
382
                set_except_vector(8, handle_sys);
383
                set_except_vector(9, handle_bp);
384
                set_except_vector(10, handle_ri);
385
                set_except_vector(11, handle_cpu);
386
                set_except_vector(12, handle_ov);
387
                set_except_vector(13, handle_tr);
388
                set_except_vector(15, handle_fpe);
389
 
390
                /*
391
                 * Compute mask for page_colour().  This is based on the
392
                 * size of the data cache.  Does the size of the icache
393
                 * need to be accounted for?
394
                 */
395
                i = read_32bit_cp0_register(CP0_CONFIG);
396
                i = (i >> 26) & 7;
397
                page_colour_mask = 1 << (12 + i);
398
                break;
399
        case CPU_R2000:
400
        case CPU_R3000:
401
        case CPU_R3000A:
402
        case CPU_R3041:
403
        case CPU_R3051:
404
        case CPU_R3052:
405
        case CPU_R3081:
406
        case CPU_R3081E:
407
        case CPU_R6000:
408
        case CPU_R6000A:
409
        case CPU_R8000:
410
                printk("Detected unsupported CPU type %s.\n",
411
                        cpu_names[boot_info.cputype]);
412
                panic("Can't handle CPU\n");
413
                break;
414
 
415
        case CPU_UNKNOWN:
416
        default:
417
                panic("Unknown CPU type");
418
        }
419
 
420
        /*
421
         * The interrupt handler mostly depends of the board type.
422
         */
423
        set_except_vector(0, feature->handle_int);
424
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.