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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1623 jcastillo
/*
2
 *  linux/arch/m68k/kernel/traps.c
3
 *
4
 *  Copyright (C) 1993, 1994 by Hamish Macdonald
5
 *
6
 *  68040 fixes by Michael Rausch
7
 *  68040 fixes by Martin Apel
8
 *  68060 fixes by Roman Hodek
9
 *  68060 fixes by Jesper Skov
10
 *
11
 * This file is subject to the terms and conditions of the GNU General Public
12
 * License.  See the file COPYING in the main directory of this archive
13
 * for more details.
14
 */
15
 
16
/*
17
 * Sets up all exception vectors
18
 */
19
 
20
#include <linux/config.h>
21
#include <linux/sched.h>
22
#include <linux/signal.h>
23
#include <linux/kernel.h>
24
#include <linux/mm.h>
25
#include <linux/types.h>
26
#include <linux/a.out.h>
27
#include <linux/user.h>
28
#include <linux/string.h>
29
#include <linux/linkage.h>
30
 
31
#include <asm/system.h>
32
#include <asm/segment.h>
33
#include <asm/traps.h>
34
#include <asm/bootinfo.h>
35
#include <asm/pgtable.h>
36
#include <asm/machdep.h>
37
 
38
/* assembler routines */
39
asmlinkage void system_call(void);
40
asmlinkage void buserr(void);
41
asmlinkage void trap(void);
42
asmlinkage void inthandler(void);
43
asmlinkage void nmihandler(void);
44
 
45
e_vector vectors[256] = {
46
        0, 0, buserr, trap, trap, trap, trap, trap,
47
        trap, trap, trap, trap, trap, trap, trap, trap,
48
        trap, trap, trap, trap, trap, trap, trap, trap,
49
        inthandler, inthandler, inthandler, inthandler,
50
        inthandler, inthandler, inthandler, inthandler,
51
        /* TRAP #0-15 */
52
        system_call, trap, trap, trap, trap, trap, trap, trap,
53
        trap, trap, trap, trap, trap, trap, trap, trap,
54
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
55
};
56
 
57
/* nmi handler for the Amiga */
58
asm(".text\n"
59
    __ALIGN_STR "\n"
60
    SYMBOL_NAME_STR(nmihandler) ": rte");
61
 
62
void trap_init (void)
63
{
64
        int i;
65
 
66
        /* setup the exception vector table */
67
        __asm__ volatile ("movec %0,%/vbr" : : "r" ((void*)vectors));
68
 
69
        for (i = 48; i < 64; i++)
70
                vectors[i] = trap;
71
 
72
        for (i = 64; i < 256; i++)
73
                vectors[i] = inthandler;
74
 
75
        /* if running on an amiga, make the NMI interrupt do nothing */
76
        if (MACH_IS_AMIGA) {
77
                vectors[VEC_INT7] = nmihandler;
78
        }
79
 
80
#ifdef CONFIG_FPSP_040
81
        if (m68k_is040or060 == 4) {
82
                /* set up FPSP entry points */
83
                asmlinkage void dz_vec(void) asm ("dz");
84
                asmlinkage void inex_vec(void) asm ("inex");
85
                asmlinkage void ovfl_vec(void) asm ("ovfl");
86
                asmlinkage void unfl_vec(void) asm ("unfl");
87
                asmlinkage void snan_vec(void) asm ("snan");
88
                asmlinkage void operr_vec(void) asm ("operr");
89
                asmlinkage void bsun_vec(void) asm ("bsun");
90
                asmlinkage void fline_vec(void) asm ("fline");
91
                asmlinkage void unsupp_vec(void) asm ("unsupp");
92
 
93
                vectors[VEC_FPDIVZ] = dz_vec;
94
                vectors[VEC_FPIR] = inex_vec;
95
                vectors[VEC_FPOVER] = ovfl_vec;
96
                vectors[VEC_FPUNDER] = unfl_vec;
97
                vectors[VEC_FPNAN] = snan_vec;
98
                vectors[VEC_FPOE] = operr_vec;
99
                vectors[VEC_FPBRUC] = bsun_vec;
100
                vectors[VEC_FPBRUC] = bsun_vec;
101
                vectors[VEC_LINE11] = fline_vec;
102
                vectors[VEC_FPUNSUP] = unsupp_vec;
103
        }
104
#endif
105
#ifdef CONFIG_IFPSP_060
106
        if (m68k_is040or060 == 6) {
107
          /* set up IFPSP entry points */
108
          asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
109
          asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
110
          asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl");
111
          asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl");
112
          asmlinkage void dz_vec(void) asm ("_060_fpsp_dz");
113
          asmlinkage void inex_vec(void) asm ("_060_fpsp_inex");
114
          asmlinkage void fline_vec(void) asm ("_060_fpsp_fline");
115
          asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
116
          asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
117
 
118
          asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
119
 
120
          vectors[VEC_FPNAN] = snan_vec;
121
          vectors[VEC_FPOE] = operr_vec;
122
          vectors[VEC_FPOVER] = ovfl_vec;
123
          vectors[VEC_FPUNDER] = unfl_vec;
124
          vectors[VEC_FPDIVZ] = dz_vec;
125
          vectors[VEC_FPIR] = inex_vec;
126
          vectors[VEC_LINE11] = fline_vec;
127
          vectors[VEC_FPUNSUP] = unsupp_vec;
128
          vectors[VEC_UNIMPEA] = effadd_vec;
129
 
130
          /* set up ISP entry points */
131
 
132
          vectors[VEC_UNIMPII] = unimp_vec;
133
 
134
        }
135
#endif
136
}
137
 
138
void set_evector(int vecnum, void (*handler)(void))
139
{
140
        if (vecnum >= 0 && vecnum <= 256)
141
                vectors[vecnum] = handler;
142
}
143
 
144
 
145
static inline void console_verbose(void)
146
{
147
        extern int console_loglevel;
148
        console_loglevel = 15;
149
        mach_debug_init();
150
}
151
 
152
char *vec_names[] = {
153
        "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
154
        "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
155
        "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
156
        "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
157
        "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
158
        "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
159
        "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
160
        "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
161
        "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
162
        "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
163
        "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
164
        "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
165
        "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
166
        "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
167
        "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15"
168
        };
169
 
170
char *space_names[] = {
171
        "Space 0", "User Data", "User Program", "Space 3",
172
        "Space 4", "Super Data", "Super Program", "CPU"
173
        };
174
 
175
 
176
 
177
extern void die_if_kernel(char *,struct pt_regs *,int);
178
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
179
                              unsigned long error_code);
180
 
181
asmlinkage void trap_c(struct frame *fp);
182
 
183
static inline void access_error060 (struct frame *fp)
184
{
185
        unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
186
 
187
#ifdef DEBUG
188
        printk("fslw=%#lx, fa=%#lx\n", ssw, fp->un.fmt4.effaddr);
189
#endif
190
 
191
        if (fslw & MMU060_BPE) {
192
                /* branch prediction error -> clear branch cache */
193
                __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
194
                                      "orl   #0x00400000,%/d0\n\t"
195
                                      "movec %/d0,%/cacr"
196
                                      : : : "d0" );
197
                /* return if there's no other error */
198
                if (!(fslw & MMU060_ERR_BITS))
199
                        return;
200
        }
201
 
202
        if (fslw & (MMU060_DESC_ERR | MMU060_WP)) {
203
                unsigned long errorcode;
204
                unsigned long addr = fp->un.fmt4.effaddr;
205
                errorcode = ((fslw & MMU060_WP) ? 1 : 0) |
206
                                        ((fslw & MMU060_W)  ? 2 : 0);
207
#ifdef DEBUG
208
                printk("errorcode = %d\n", errorcode );
209
#endif
210
                if (fslw & MMU060_MA)
211
                  addr = PAGE_ALIGN(addr);
212
                do_page_fault( (struct pt_regs *)fp, addr, errorcode );
213
        }
214
        else {
215
                printk( "68060 access error, fslw=%lx\n", fslw );
216
                trap_c( fp );
217
        }
218
}
219
 
220
static unsigned long probe040 (int iswrite, int fc, unsigned long addr)
221
{
222
        unsigned long mmusr;
223
        unsigned long fs = get_fs();
224
 
225
        set_fs (fc);
226
 
227
        if (iswrite)
228
                /* write */
229
                asm volatile ("movel %1,%/a0\n\t"
230
                              ".word 0xf548\n\t"        /* ptestw (a0) */
231
                              ".long 0x4e7a8805\n\t"    /* movec mmusr,a0 */
232
                              "movel %/a0,%0"
233
                              : "=g" (mmusr)
234
                              : "g" (addr)
235
                              : "a0");
236
        else
237
                asm volatile ("movel %1,%/a0\n\t"
238
                              ".word 0xf568\n\t"        /* ptestr (a0) */
239
                              ".long 0x4e7a8805\n\t"    /* movec mmusr,a0 */
240
                              "movel %/a0,%0"
241
                              : "=g" (mmusr)
242
                              : "g" (addr)
243
                              : "a0");
244
 
245
 
246
        set_fs (fs);
247
 
248
        return mmusr;
249
}
250
 
251
static void do_040writeback (unsigned short ssw,
252
                             unsigned short wbs,
253
                             unsigned long wba,
254
                             unsigned long wbd,
255
                             struct frame *fp)
256
{
257
        unsigned long fs = get_fs ();
258
        unsigned long mmusr;
259
        unsigned long errorcode;
260
 
261
        /*
262
         * No special handling for the second writeback anymore.
263
         * It misinterpreted the misaligned status sometimes.
264
         * This way an extra page-fault may be caused (Martin Apel).
265
         */
266
 
267
        mmusr = probe040 (1, wbs & WBTM_040,  wba);
268
        errorcode = (mmusr & MMU_R_040) ? 3 : 2;
269
        if (do_page_fault ((struct pt_regs *)fp, wba, errorcode))
270
          /* just return if we can't perform the writeback */
271
          return;
272
 
273
        set_fs (wbs & WBTM_040);
274
        switch (wbs & WBSIZ_040) {
275
            case BA_SIZE_BYTE:
276
                put_fs_byte (wbd & 0xff, (char *)wba);
277
                break;
278
            case BA_SIZE_WORD:
279
                put_fs_word (wbd & 0xffff, (short *)wba);
280
                break;
281
            case BA_SIZE_LONG:
282
                put_fs_long (wbd, (int *)wba);
283
                break;
284
        }
285
        set_fs (fs);
286
}
287
 
288
static inline void access_error040 (struct frame *fp)
289
{
290
        unsigned short ssw = fp->un.fmt7.ssw;
291
        unsigned long mmusr;
292
 
293
#ifdef DEBUG
294
        printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
295
        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
296
                fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
297
        printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
298
                fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
299
                fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
300
#endif
301
 
302
 
303
        if (ssw & ATC_040) {
304
                unsigned long addr = fp->un.fmt7.faddr;
305
                unsigned long errorcode;
306
 
307
                /*
308
                 * The MMU status has to be determined AFTER the address
309
                 * has been corrected if there was a misaligned access (MA).
310
                 */
311
                if (ssw & MA_040)
312
                        addr = PAGE_ALIGN (addr);
313
 
314
                /* MMU error, get the MMUSR info for this access */
315
                mmusr = probe040 (!(ssw & RW_040), ssw & TM_040, addr);
316
                /*
317
#ifdef DEBUG
318
                printk("mmusr = %lx\n", mmusr);
319
#endif
320
*/
321
                errorcode = ((mmusr & MMU_R_040) ? 1 : 0) |
322
                        ((ssw & RW_040) ? 0 : 2);
323
                do_page_fault ((struct pt_regs *)fp, addr, errorcode);
324
        } else {
325
                printk ("68040 access error, ssw=%x\n", ssw);
326
                trap_c (fp);
327
        }
328
 
329
#if 0
330
        if (fp->un.fmt7.wb1s & WBV_040)
331
                printk("access_error040: cannot handle 1st writeback. oops.\n");
332
#endif
333
 
334
/*
335
 *  We may have to do a couple of writebacks here.
336
 *
337
 *  MR: we can speed up the thing a little bit and let do_040writeback()
338
 *  not produce another page fault as wb2 corresponds to the address that
339
 *  caused the fault. on write faults no second fault is generated, but
340
 *  on read faults for security reasons (although per definitionem impossible)
341
 */
342
 
343
        if (fp->un.fmt7.wb2s & WBV_040 && (fp->un.fmt7.wb2s &
344
                                           WBTT_040) != BA_TT_MOVE16)
345
                do_040writeback (ssw,
346
                                 fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
347
                                 fp->un.fmt7.wb2d, fp);
348
 
349
        if (fp->un.fmt7.wb3s & WBV_040)
350
                do_040writeback (ssw, fp->un.fmt7.wb3s,
351
                                 fp->un.fmt7.wb3a, fp->un.fmt7.wb3d,
352
                                 fp);
353
}
354
 
355
static inline void bus_error030 (struct frame *fp)
356
{
357
        volatile unsigned short temp;
358
        unsigned short mmusr;
359
        unsigned long addr, desc, errorcode;
360
        unsigned short ssw = fp->un.fmtb.ssw;
361
        int user_space_fault = 1;
362
 
363
#if DEBUG
364
        printk ("pid = %x  ", current->pid);
365
        printk ("SSW=%#06x  ", ssw);
366
 
367
        if (ssw & (FC | FB))
368
                printk ("Instruction fault at %#010lx\n",
369
                        ssw & FC ?
370
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
371
                        :
372
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
373
        if (ssw & DF)
374
                printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
375
                        ssw & RW ? "read" : "write",
376
                        fp->un.fmtb.daddr,
377
                        space_names[ssw & DFC], fp->ptregs.pc);
378
#endif
379
 
380
        if (fp->ptregs.sr & PS_S) {
381
                /* kernel fault must be a data fault to user space */
382
                if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
383
                        /* instruction fault or kernel data fault! */
384
                        if (ssw & (FC | FB))
385
                                printk ("Instruction fault at %#010lx\n",
386
                                        fp->ptregs.pc);
387
                        if (ssw & DF) {
388
                                printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
389
                                        ssw & RW ? "read" : "write",
390
                                        fp->un.fmtb.daddr,
391
                                        space_names[ssw & DFC], fp->ptregs.pc);
392
                        }
393
                        printk ("BAD KERNEL BUSERR\n");
394
                        die_if_kernel("Oops",&fp->ptregs,0);
395
                        force_sig(SIGSEGV, current);
396
                        user_space_fault = 0;
397
                }
398
        } else {
399
                /* user fault */
400
                if (!(ssw & (FC | FB)) && !(ssw & DF))
401
                        /* not an instruction fault or data fault! BAD */
402
                        panic ("USER BUSERR w/o instruction or data fault");
403
                user_space_fault = 1;
404
#if DEBUG
405
                printk("User space bus-error\n");
406
#endif
407
        }
408
 
409
        /* ++andreas: If a data fault and an instruction fault happen
410
           at the same time map in both pages.  */
411
 
412
        /* First handle the data fault, if any.  */
413
        if (ssw & DF)
414
          {
415
            addr = fp->un.fmtb.daddr;
416
 
417
            if (user_space_fault) {
418
                    asm volatile ("ptestr #1,%2@,#7,%0\n\t"
419
                                  "pmove %/psr,%1@"
420
                                  : "=a&" (desc)
421
                                  : "a" (&temp), "a" (addr));
422
                    mmusr = temp;
423
            } else
424
                    mmusr = MMU_I;
425
 
426
#if DEBUG
427
            printk ("mmusr is %#x for addr %#lx in task %p\n",
428
                    mmusr, addr, current);
429
            printk ("descriptor address is %#lx, contents %#lx\n",
430
                    mm_ptov(desc), *(unsigned long *)mm_ptov(desc));
431
#endif
432
 
433
            errorcode = (mmusr & MMU_I) ? 0 : 1;
434
              /* if (!(ssw & RW)) updated to 1.2.13pl6 */
435
            if (!(ssw & RW) || ssw & RM)
436
                    errorcode |= 2;
437
 
438
            if (mmusr & MMU_I)
439
                    do_page_fault ((struct pt_regs *)fp, addr, errorcode);
440
 
441
            /* else if ((mmusr & MMU_WP) && !(ssw & RW)) */
442
 
443
            else if ((mmusr & MMU_WP) && (!(ssw & RW) || ssw & RM))
444
                    do_page_fault ((struct pt_regs *)fp, addr, errorcode);
445
            else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
446
                    printk ("invalid %s access at %#lx from pc %#lx\n",
447
                            !(ssw & RW) ? "write" : "read", addr,
448
                            fp->ptregs.pc);
449
                    die_if_kernel("Oops",&fp->ptregs,mmusr);
450
                    force_sig(SIGSEGV, current);
451
                    return;
452
            } else {
453
#ifdef DEBUG
454
                    static volatile long tlong;
455
#endif
456
 
457
                    printk ("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
458
                            !(ssw & RW) ? "write" : "read", addr,
459
                            fp->ptregs.pc, ssw);
460
                    asm volatile ("ptestr #1,%1@,#0\n\t"
461
                                  "pmove %/psr,%0@"
462
                                  : /* no outputs */
463
                                  : "a" (&temp), "a" (addr));
464
                    mmusr = temp;
465
 
466
                    printk ("level 0 mmusr is %#x\n", mmusr);
467
#if 0
468
                    asm volatile ("pmove %/tt0,%0@"
469
                                  : /* no outputs */
470
                                  : "a" (&tlong));
471
                    printk ("tt0 is %#lx, ", tlong);
472
                    asm volatile ("pmove %/tt1,%0@"
473
                                  : /* no outputs */
474
                                  : "a" (&tlong));
475
                    printk ("tt1 is %#lx\n", tlong);
476
#endif
477
#if DEBUG
478
                    printk("Unknown SIGSEGV - 1\n");
479
#endif
480
                    die_if_kernel("Oops",&fp->ptregs,mmusr);
481
                    force_sig(SIGSEGV, current);
482
                    return;
483
            }
484
 
485
            /* setup an ATC entry for the access about to be retried */
486
            if (!(ssw & RW))
487
                    asm volatile ("ploadw #1,%0@" : /* no outputs */
488
                                  : "a" (addr));
489
            else
490
                    asm volatile ("ploadr #1,%0@" : /* no outputs */
491
                                  : "a" (addr));
492
 
493
            /* If this was a data fault due to an invalid page and a
494
               prefetch is pending on the same page, simulate it (but
495
               only if the page is now valid).  Otherwise we'll get an
496
               weird insn access.  */
497
            if ((ssw & RB) && (mmusr & MMU_I))
498
              {
499
                unsigned long iaddr;
500
 
501
                if ((fp->ptregs.format) == 0xB)
502
                  iaddr = fp->un.fmtb.baddr;
503
                else
504
                  iaddr = fp->ptregs.pc + 4;
505
                if (((addr ^ iaddr) & PAGE_MASK) == 0)
506
                  {
507
                    /* We only need to check the ATC as the entry has
508
                       already been set up above.  */
509
                    asm volatile ("ptestr #1,%1@,#0\n\t"
510
                                  "pmove %/psr,%0@"
511
                                  : : "a" (&temp), "a" (iaddr));
512
                    mmusr = temp;
513
#ifdef DEBUG
514
                    printk ("prefetch iaddr=%#lx ssw=%#x mmusr=%#x\n",
515
                            iaddr, ssw, mmusr);
516
#endif
517
                    if (!(mmusr & MMU_I))
518
                      {
519
                        unsigned short insn;
520
                        asm volatile ("movesw %1@,%0"
521
                                      : "=r" (insn)
522
                                      : "a" (iaddr));
523
                        fp->un.fmtb.isb = insn;
524
                        fp->un.fmtb.ssw &= ~RB;
525
                      }
526
                  }
527
              }
528
          }
529
 
530
        /* Now handle the instruction fault. */
531
 
532
        /* get the fault address */
533
        if ((fp->ptregs.format) == 0xA )
534
                if (ssw & FC)
535
                        addr = fp->ptregs.pc + 2;
536
                else if (ssw & FB)
537
                        addr = fp->ptregs.pc + 4;
538
                else
539
                        return;
540
        else
541
                if (ssw & FC)
542
                        addr = fp->un.fmtb.baddr - 2;
543
                else if (ssw & FB)
544
                        addr = fp->un.fmtb.baddr;
545
                else
546
                        return;
547
 
548
        if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
549
                /* Insn fault on same page as data fault */
550
                return;
551
 
552
        if (user_space_fault) {
553
                asm volatile ("ptestr #1,%2@,#7,%0\n\t"
554
                              "pmove %/psr,%1@"
555
                              : "=a&" (desc)
556
                              : "a" (&temp), "a" (addr));
557
                mmusr = temp;
558
        } else
559
                mmusr = MMU_I;
560
 
561
#ifdef DEBUG
562
        printk ("mmusr is %#x for addr %#lx in task %p\n",
563
                mmusr, addr, current);
564
        printk ("descriptor address is %#lx, contents %#lx\n",
565
                mm_ptov(desc), *(unsigned long *)mm_ptov(desc));
566
#endif
567
 
568
        errorcode = (mmusr & MMU_I) ? 0 : 1;
569
 
570
        if (mmusr & MMU_I)
571
                do_page_fault ((struct pt_regs *)fp, addr, errorcode);
572
        else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
573
                printk ("invalid insn access at %#lx from pc %#lx\n",
574
                        addr, fp->ptregs.pc);
575
#if DEBUG
576
                printk("Unknown SIGSEGV - 2\n");
577
#endif
578
                die_if_kernel("Oops",&fp->ptregs,mmusr);
579
                force_sig(SIGSEGV, current);
580
                return;
581
        } else {
582
#ifdef DEBUG
583
                static volatile long tlong;
584
#endif
585
 
586
                printk ("weird insn access at %#lx from pc %#lx (ssw is %#x)\n",
587
                        addr, fp->ptregs.pc, ssw);
588
                asm volatile ("ptestr #1,%1@,#0\n\t"
589
                              "pmove %/psr,%0@"
590
                              : /* no outputs */
591
                              : "a" (&temp), "a" (addr));
592
                mmusr = temp;
593
 
594
                printk ("level 0 mmusr is %#x\n", mmusr);
595
#ifdef DEBUG
596
                if (boot_info.cputype & CPU_68030) {
597
                        asm volatile ("pmove %/tt0,%0@"
598
                                      : /* no outputs */
599
                                      : "a" (&tlong));
600
                        printk ("tt0 is %#lx, ", tlong);
601
                        asm volatile ("pmove %/tt1,%0@"
602
                                      : /* no outputs */
603
                                      : "a" (&tlong));
604
                        printk ("tt1 is %#lx\n", tlong);
605
                }
606
 
607
#endif
608
#if DEBUG
609
                printk("Unknown SIGSEGV - 3\n");
610
#endif
611
                die_if_kernel("Oops",&fp->ptregs,mmusr);
612
                force_sig(SIGSEGV, current);
613
                return;
614
        }
615
 
616
        /* setup an ATC entry for the access about to be retried */
617
        asm volatile ("ploadr #1,%0@" : /* no outputs */
618
                      : "a" (addr));
619
}
620
 
621
asmlinkage void buserr_c(struct frame *fp)
622
{
623
        /* Only set esp0 if coming from user mode */
624
        if (user_mode(&fp->ptregs))
625
                current->tss.esp0 = (unsigned long) fp;
626
 
627
#if DEBUG
628
        printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
629
#endif
630
 
631
        switch (fp->ptregs.format) {
632
        case 4:                         /* 68060 access error */
633
          access_error060 (fp);
634
          break;
635
        case 0x7:                       /* 68040 access error */
636
          access_error040 (fp);
637
          break;
638
        case 0xa:
639
        case 0xb:
640
          bus_error030 (fp);
641
          break;
642
        default:
643
          die_if_kernel("bad frame format",&fp->ptregs,0);
644
#if DEBUG
645
          printk("Unknown SIGSEGV - 4\n");
646
#endif
647
          force_sig(SIGSEGV, current);
648
        }
649
}
650
 
651
 
652
int kstack_depth_to_print = 48;
653
 
654
/* MODULE_RANGE is a guess of how much space is likely to be
655
   vmalloced.  */
656
#define MODULE_RANGE (8*1024*1024)
657
 
658
static void dump_stack(struct frame *fp)
659
{
660
        unsigned long *stack, *endstack, addr, module_start, module_end;
661
        extern char _start, _etext;
662
        int i;
663
 
664
        addr = (unsigned long)&fp->un;
665
        printk("Frame format=%X ", fp->ptregs.format);
666
        switch (fp->ptregs.format) {
667
        case 0x2:
668
            printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
669
            addr += sizeof(fp->un.fmt2);
670
            break;
671
        case 0x3:
672
            printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
673
            addr += sizeof(fp->un.fmt3);
674
            break;
675
        case 0x4:
676
            printk((m68k_is040or060 == 6 ? "fault addr=%08lx fslw=%08lx\n"
677
                    : "eff addr=%08lx pc=%08lx\n"),
678
                   fp->un.fmt4.effaddr, fp->un.fmt4.pc);
679
            addr += sizeof(fp->un.fmt4);
680
            break;
681
        case 0x7:
682
            printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
683
                   fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
684
            printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
685
                   fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
686
            printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
687
                   fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
688
            printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
689
                   fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
690
            printk("push data: %08lx %08lx %08lx %08lx\n",
691
                   fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
692
                   fp->un.fmt7.pd3);
693
            addr += sizeof(fp->un.fmt7);
694
            break;
695
        case 0x9:
696
            printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
697
            addr += sizeof(fp->un.fmt9);
698
            break;
699
        case 0xa:
700
            printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
701
                   fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
702
                   fp->un.fmta.daddr, fp->un.fmta.dobuf);
703
            addr += sizeof(fp->un.fmta);
704
            break;
705
        case 0xb:
706
            printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
707
                   fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
708
                   fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
709
            printk("baddr=%08lx dibuf=%08lx ver=%x\n",
710
                   fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
711
            addr += sizeof(fp->un.fmtb);
712
            break;
713
        default:
714
            printk("\n");
715
        }
716
 
717
        stack = (unsigned long *)addr;
718
        endstack = (unsigned long *)PAGE_ALIGN(addr);
719
 
720
        printk("Stack from %08lx:\n       ", (unsigned long)stack);
721
        for (i = 0; i < kstack_depth_to_print; i++) {
722
                if (stack + 1 > endstack)
723
                        break;
724
                if (i && ((i % 8) == 0))
725
                        printk("\n       ");
726
                printk("%08lx ", *stack++);
727
        }
728
 
729
        printk ("\nCall Trace: ");
730
        stack = (unsigned long *) addr;
731
        i = 1;
732
        module_start = VMALLOC_START;
733
        module_end = module_start + MODULE_RANGE;
734
        while (stack + 1 <= endstack) {
735
                addr = *stack++;
736
                /*
737
                 * If the address is either in the text segment of the
738
                 * kernel, or in the region which contains vmalloc'ed
739
                 * memory, it *may* be the address of a calling
740
                 * routine; if so, print it so that someone tracing
741
                 * down the cause of the crash will be able to figure
742
                 * out the call path that was taken.
743
                 */
744
                if (((addr >= (unsigned long) &_start) &&
745
                     (addr <= (unsigned long) &_etext)) ||
746
                    ((addr >= module_start) && (addr <= module_end))) {
747
                        if (i && ((i % 8) == 0))
748
                                printk("\n       ");
749
                        printk("[<%08lx>] ", addr);
750
                        i++;
751
                }
752
        }
753
        printk("\nCode: ");
754
        for (i = 0; i < 10; i++)
755
                printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
756
        printk ("\n");
757
}
758
 
759
void bad_super_trap (struct frame *fp)
760
{
761
        console_verbose();
762
        if ((fp->ptregs.vector) < 48*4)
763
                printk ("*** %s ***   FORMAT=%X\n",
764
                        vec_names[(fp->ptregs.vector) >> 2],
765
                        fp->ptregs.format);
766
        else
767
                printk ("*** Exception %d ***   FORMAT=%X\n",
768
                        (fp->ptregs.vector) >> 2,
769
                        fp->ptregs.format);
770
        if (((fp->ptregs.vector) >> 2) == VEC_ADDRERR
771
            && !m68k_is040or060) {
772
                unsigned short ssw = fp->un.fmtb.ssw;
773
 
774
                printk ("SSW=%#06x  ", ssw);
775
 
776
                if (ssw & RC)
777
                        printk ("Pipe stage C instruction fault at %#010lx\n",
778
                                (fp->ptregs.format) == 0xA ?
779
                                fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
780
                if (ssw & RB)
781
                        printk ("Pipe stage B instruction fault at %#010lx\n",
782
                                (fp->ptregs.format) == 0xA ?
783
                                fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
784
                if (ssw & DF)
785
                        printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
786
                                ssw & RW ? "read" : "write",
787
                                fp->un.fmtb.daddr, space_names[ssw & DFC],
788
                                fp->ptregs.pc);
789
        }
790
        printk ("Current process id is %d\n", current->pid);
791
        die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
792
}
793
 
794
asmlinkage void trap_c(struct frame *fp)
795
{
796
        int sig;
797
 
798
        if ((fp->ptregs.sr & PS_S)
799
            && ((fp->ptregs.vector) >> 2) == VEC_TRACE
800
            && !(fp->ptregs.sr & PS_T)) {
801
                /* traced a trapping instruction */
802
                unsigned char *lp = ((unsigned char *)&fp->un.fmt2) + 4;
803
                current->flags |= PF_DTRACE;
804
                /* clear the trace bit */
805
                (*(unsigned short *)lp) &= ~PS_T;
806
                return;
807
        } else if (fp->ptregs.sr & PS_S) {
808
                bad_super_trap(fp);
809
                return;
810
        }
811
 
812
        /* send the appropriate signal to the user program */
813
        switch ((fp->ptregs.vector) >> 2) {
814
            case VEC_ADDRERR:
815
                sig = SIGBUS;
816
                break;
817
            case VEC_BUSERR:
818
                sig = SIGSEGV;
819
                break;
820
            case VEC_ILLEGAL:
821
            case VEC_PRIV:
822
            case VEC_LINE10:
823
            case VEC_LINE11:
824
            case VEC_COPROC:
825
            case VEC_TRAP1:
826
            case VEC_TRAP2:
827
            case VEC_TRAP3:
828
            case VEC_TRAP4:
829
            case VEC_TRAP5:
830
            case VEC_TRAP6:
831
            case VEC_TRAP7:
832
            case VEC_TRAP8:
833
            case VEC_TRAP9:
834
            case VEC_TRAP10:
835
            case VEC_TRAP11:
836
            case VEC_TRAP12:
837
            case VEC_TRAP13:
838
            case VEC_TRAP14:
839
                sig = SIGILL;
840
                break;
841
            case VEC_FPBRUC:
842
            case VEC_FPIR:
843
            case VEC_FPDIVZ:
844
            case VEC_FPUNDER:
845
            case VEC_FPOE:
846
            case VEC_FPOVER:
847
            case VEC_FPNAN:
848
                {
849
                  unsigned char fstate[216];
850
 
851
                  __asm__ __volatile__ ("fsave %0@" : : "a" (fstate) : "memory");
852
                  /* Set the exception pending bit in the 68882 idle frame */
853
                  if (*(unsigned short *) fstate == 0x1f38)
854
                    {
855
                      fstate[fstate[1]] |= 1 << 3;
856
                      __asm__ __volatile__ ("frestore %0@" : : "a" (fstate));
857
                    }
858
                }
859
                /* fall through */
860
            case VEC_ZERODIV:
861
            case VEC_TRAP:
862
                sig = SIGFPE;
863
                break;
864
            case VEC_TRACE:             /* ptrace single step */
865
                fp->ptregs.sr &= ~PS_T;
866
            case VEC_TRAP15:            /* breakpoint */
867
                sig = SIGTRAP;
868
                break;
869
            default:
870
                sig = SIGILL;
871
                break;
872
        }
873
 
874
        force_sig (sig, current);
875
}
876
 
877
asmlinkage void set_esp0 (unsigned long ssp)
878
{
879
  current->tss.esp0 = ssp;
880
}
881
 
882
void die_if_kernel (char *str, struct pt_regs *fp, int nr)
883
{
884
        if (!(fp->sr & PS_S))
885
                return;
886
 
887
        console_verbose();
888
        printk("%s: %08x\n",str,nr);
889
        printk("PC: %08lx\nSR: %04x  SP: %p\n", fp->pc, fp->sr, fp);
890
        printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
891
               fp->d0, fp->d1, fp->d2, fp->d3);
892
        printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
893
               fp->d4, fp->d5, fp->a0, fp->a1);
894
 
895
        if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
896
                printk("Corrupted stack page\n");
897
        printk("Process %s (pid: %d, stackpage=%08lx)\n",
898
                current->comm, current->pid, current->kernel_stack_page);
899
        dump_stack((struct frame *)fp);
900
        do_exit(SIGSEGV);
901
}

powered by: WebSVN 2.1.0

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