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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [m68k/] [kernel/] [traps.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
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
 *  68040 fixes and writeback by Richard Zidlicky
9
 *  68060 fixes by Roman Hodek
10
 *  68060 fixes by Jesper Skov
11
 *
12
 * This file is subject to the terms and conditions of the GNU General Public
13
 * License.  See the file COPYING in the main directory of this archive
14
 * for more details.
15
 */
16
 
17
/*
18
 * Sets up all exception vectors
19
 */
20
 
21
#include <linux/sched.h>
22
#include <linux/signal.h>
23
#include <linux/kernel.h>
24
#include <linux/mm.h>
25
#include <linux/module.h>
26
#include <linux/a.out.h>
27
#include <linux/user.h>
28
#include <linux/string.h>
29
#include <linux/linkage.h>
30
#include <linux/init.h>
31
#include <linux/ptrace.h>
32
#include <linux/kallsyms.h>
33
 
34
#include <asm/setup.h>
35
#include <asm/fpu.h>
36
#include <asm/system.h>
37
#include <asm/uaccess.h>
38
#include <asm/traps.h>
39
#include <asm/pgalloc.h>
40
#include <asm/machdep.h>
41
#include <asm/siginfo.h>
42
 
43
/* assembler routines */
44
asmlinkage void system_call(void);
45
asmlinkage void buserr(void);
46
asmlinkage void trap(void);
47
asmlinkage void nmihandler(void);
48
#ifdef CONFIG_M68KFPU_EMU
49
asmlinkage void fpu_emu(void);
50
#endif
51
 
52
e_vector vectors[256] = {
53
        [VEC_BUSERR]    = buserr,
54
        [VEC_SYS]       = system_call,
55
};
56
 
57
/* nmi handler for the Amiga */
58
asm(".text\n"
59
    __ALIGN_STR "\n"
60
    "nmihandler: rte");
61
 
62
/*
63
 * this must be called very early as the kernel might
64
 * use some instruction that are emulated on the 060
65
 */
66
void __init base_trap_init(void)
67
{
68
        if(MACH_IS_SUN3X) {
69
                extern e_vector *sun3x_prom_vbr;
70
 
71
                __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
72
        }
73
 
74
        /* setup the exception vector table */
75
        __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
76
 
77
        if (CPU_IS_060) {
78
                /* set up ISP entry points */
79
                asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
80
 
81
                vectors[VEC_UNIMPII] = unimp_vec;
82
        }
83
}
84
 
85
void __init trap_init (void)
86
{
87
        int i;
88
 
89
        for (i = VEC_SPUR; i <= VEC_INT7; i++)
90
                vectors[i] = bad_inthandler;
91
 
92
        for (i = 0; i < VEC_USER; i++)
93
                if (!vectors[i])
94
                        vectors[i] = trap;
95
 
96
        for (i = VEC_USER; i < 256; i++)
97
                vectors[i] = bad_inthandler;
98
 
99
#ifdef CONFIG_M68KFPU_EMU
100
        if (FPU_IS_EMU)
101
                vectors[VEC_LINE11] = fpu_emu;
102
#endif
103
 
104
        if (CPU_IS_040 && !FPU_IS_EMU) {
105
                /* set up FPSP entry points */
106
                asmlinkage void dz_vec(void) asm ("dz");
107
                asmlinkage void inex_vec(void) asm ("inex");
108
                asmlinkage void ovfl_vec(void) asm ("ovfl");
109
                asmlinkage void unfl_vec(void) asm ("unfl");
110
                asmlinkage void snan_vec(void) asm ("snan");
111
                asmlinkage void operr_vec(void) asm ("operr");
112
                asmlinkage void bsun_vec(void) asm ("bsun");
113
                asmlinkage void fline_vec(void) asm ("fline");
114
                asmlinkage void unsupp_vec(void) asm ("unsupp");
115
 
116
                vectors[VEC_FPDIVZ] = dz_vec;
117
                vectors[VEC_FPIR] = inex_vec;
118
                vectors[VEC_FPOVER] = ovfl_vec;
119
                vectors[VEC_FPUNDER] = unfl_vec;
120
                vectors[VEC_FPNAN] = snan_vec;
121
                vectors[VEC_FPOE] = operr_vec;
122
                vectors[VEC_FPBRUC] = bsun_vec;
123
                vectors[VEC_LINE11] = fline_vec;
124
                vectors[VEC_FPUNSUP] = unsupp_vec;
125
        }
126
 
127
        if (CPU_IS_060 && !FPU_IS_EMU) {
128
                /* set up IFPSP entry points */
129
                asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
130
                asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
131
                asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
132
                asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
133
                asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
134
                asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
135
                asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
136
                asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
137
                asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
138
 
139
                vectors[VEC_FPNAN] = snan_vec6;
140
                vectors[VEC_FPOE] = operr_vec6;
141
                vectors[VEC_FPOVER] = ovfl_vec6;
142
                vectors[VEC_FPUNDER] = unfl_vec6;
143
                vectors[VEC_FPDIVZ] = dz_vec6;
144
                vectors[VEC_FPIR] = inex_vec6;
145
                vectors[VEC_LINE11] = fline_vec6;
146
                vectors[VEC_FPUNSUP] = unsupp_vec6;
147
                vectors[VEC_UNIMPEA] = effadd_vec6;
148
        }
149
 
150
        /* if running on an amiga, make the NMI interrupt do nothing */
151
        if (MACH_IS_AMIGA) {
152
                vectors[VEC_INT7] = nmihandler;
153
        }
154
}
155
 
156
 
157
static const char *vec_names[] = {
158
        [VEC_RESETSP]   = "RESET SP",
159
        [VEC_RESETPC]   = "RESET PC",
160
        [VEC_BUSERR]    = "BUS ERROR",
161
        [VEC_ADDRERR]   = "ADDRESS ERROR",
162
        [VEC_ILLEGAL]   = "ILLEGAL INSTRUCTION",
163
        [VEC_ZERODIV]   = "ZERO DIVIDE",
164
        [VEC_CHK]       = "CHK",
165
        [VEC_TRAP]      = "TRAPcc",
166
        [VEC_PRIV]      = "PRIVILEGE VIOLATION",
167
        [VEC_TRACE]     = "TRACE",
168
        [VEC_LINE10]    = "LINE 1010",
169
        [VEC_LINE11]    = "LINE 1111",
170
        [VEC_RESV12]    = "UNASSIGNED RESERVED 12",
171
        [VEC_COPROC]    = "COPROCESSOR PROTOCOL VIOLATION",
172
        [VEC_FORMAT]    = "FORMAT ERROR",
173
        [VEC_UNINT]     = "UNINITIALIZED INTERRUPT",
174
        [VEC_RESV16]    = "UNASSIGNED RESERVED 16",
175
        [VEC_RESV17]    = "UNASSIGNED RESERVED 17",
176
        [VEC_RESV18]    = "UNASSIGNED RESERVED 18",
177
        [VEC_RESV19]    = "UNASSIGNED RESERVED 19",
178
        [VEC_RESV20]    = "UNASSIGNED RESERVED 20",
179
        [VEC_RESV21]    = "UNASSIGNED RESERVED 21",
180
        [VEC_RESV22]    = "UNASSIGNED RESERVED 22",
181
        [VEC_RESV23]    = "UNASSIGNED RESERVED 23",
182
        [VEC_SPUR]      = "SPURIOUS INTERRUPT",
183
        [VEC_INT1]      = "LEVEL 1 INT",
184
        [VEC_INT2]      = "LEVEL 2 INT",
185
        [VEC_INT3]      = "LEVEL 3 INT",
186
        [VEC_INT4]      = "LEVEL 4 INT",
187
        [VEC_INT5]      = "LEVEL 5 INT",
188
        [VEC_INT6]      = "LEVEL 6 INT",
189
        [VEC_INT7]      = "LEVEL 7 INT",
190
        [VEC_SYS]       = "SYSCALL",
191
        [VEC_TRAP1]     = "TRAP #1",
192
        [VEC_TRAP2]     = "TRAP #2",
193
        [VEC_TRAP3]     = "TRAP #3",
194
        [VEC_TRAP4]     = "TRAP #4",
195
        [VEC_TRAP5]     = "TRAP #5",
196
        [VEC_TRAP6]     = "TRAP #6",
197
        [VEC_TRAP7]     = "TRAP #7",
198
        [VEC_TRAP8]     = "TRAP #8",
199
        [VEC_TRAP9]     = "TRAP #9",
200
        [VEC_TRAP10]    = "TRAP #10",
201
        [VEC_TRAP11]    = "TRAP #11",
202
        [VEC_TRAP12]    = "TRAP #12",
203
        [VEC_TRAP13]    = "TRAP #13",
204
        [VEC_TRAP14]    = "TRAP #14",
205
        [VEC_TRAP15]    = "TRAP #15",
206
        [VEC_FPBRUC]    = "FPCP BSUN",
207
        [VEC_FPIR]      = "FPCP INEXACT",
208
        [VEC_FPDIVZ]    = "FPCP DIV BY 0",
209
        [VEC_FPUNDER]   = "FPCP UNDERFLOW",
210
        [VEC_FPOE]      = "FPCP OPERAND ERROR",
211
        [VEC_FPOVER]    = "FPCP OVERFLOW",
212
        [VEC_FPNAN]     = "FPCP SNAN",
213
        [VEC_FPUNSUP]   = "FPCP UNSUPPORTED OPERATION",
214
        [VEC_MMUCFG]    = "MMU CONFIGURATION ERROR",
215
        [VEC_MMUILL]    = "MMU ILLEGAL OPERATION ERROR",
216
        [VEC_MMUACC]    = "MMU ACCESS LEVEL VIOLATION ERROR",
217
        [VEC_RESV59]    = "UNASSIGNED RESERVED 59",
218
        [VEC_UNIMPEA]   = "UNASSIGNED RESERVED 60",
219
        [VEC_UNIMPII]   = "UNASSIGNED RESERVED 61",
220
        [VEC_RESV62]    = "UNASSIGNED RESERVED 62",
221
        [VEC_RESV63]    = "UNASSIGNED RESERVED 63",
222
};
223
 
224
static const char *space_names[] = {
225
        [0]              = "Space 0",
226
        [USER_DATA]     = "User Data",
227
        [USER_PROGRAM]  = "User Program",
228
#ifndef CONFIG_SUN3
229
        [3]             = "Space 3",
230
#else
231
        [FC_CONTROL]    = "Control",
232
#endif
233
        [4]             = "Space 4",
234
        [SUPER_DATA]    = "Super Data",
235
        [SUPER_PROGRAM] = "Super Program",
236
        [CPU_SPACE]     = "CPU"
237
};
238
 
239
void die_if_kernel(char *,struct pt_regs *,int);
240
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
241
                             unsigned long error_code);
242
int send_fault_sig(struct pt_regs *regs);
243
 
244
asmlinkage void trap_c(struct frame *fp);
245
 
246
#if defined (CONFIG_M68060)
247
static inline void access_error060 (struct frame *fp)
248
{
249
        unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
250
 
251
#ifdef DEBUG
252
        printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
253
#endif
254
 
255
        if (fslw & MMU060_BPE) {
256
                /* branch prediction error -> clear branch cache */
257
                __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
258
                                      "orl   #0x00400000,%/d0\n\t"
259
                                      "movec %/d0,%/cacr"
260
                                      : : : "d0" );
261
                /* return if there's no other error */
262
                if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
263
                        return;
264
        }
265
 
266
        if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
267
                unsigned long errorcode;
268
                unsigned long addr = fp->un.fmt4.effaddr;
269
 
270
                if (fslw & MMU060_MA)
271
                        addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
272
 
273
                errorcode = 1;
274
                if (fslw & MMU060_DESC_ERR) {
275
                        __flush_tlb040_one(addr);
276
                        errorcode = 0;
277
                }
278
                if (fslw & MMU060_W)
279
                        errorcode |= 2;
280
#ifdef DEBUG
281
                printk("errorcode = %d\n", errorcode );
282
#endif
283
                do_page_fault(&fp->ptregs, addr, errorcode);
284
        } else if (fslw & (MMU060_SEE)){
285
                /* Software Emulation Error.
286
                 * fault during mem_read/mem_write in ifpsp060/os.S
287
                 */
288
                send_fault_sig(&fp->ptregs);
289
        } else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
290
                   send_fault_sig(&fp->ptregs) > 0) {
291
                printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
292
                printk( "68060 access error, fslw=%lx\n", fslw );
293
                trap_c( fp );
294
        }
295
}
296
#endif /* CONFIG_M68060 */
297
 
298
#if defined (CONFIG_M68040)
299
static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
300
{
301
        unsigned long mmusr;
302
        mm_segment_t old_fs = get_fs();
303
 
304
        set_fs(MAKE_MM_SEG(wbs));
305
 
306
        if (iswrite)
307
                asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
308
        else
309
                asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
310
 
311
        asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
312
 
313
        set_fs(old_fs);
314
 
315
        return mmusr;
316
}
317
 
318
static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
319
                                   unsigned long wbd)
320
{
321
        int res = 0;
322
        mm_segment_t old_fs = get_fs();
323
 
324
        /* set_fs can not be moved, otherwise put_user() may oops */
325
        set_fs(MAKE_MM_SEG(wbs));
326
 
327
        switch (wbs & WBSIZ_040) {
328
        case BA_SIZE_BYTE:
329
                res = put_user(wbd & 0xff, (char __user *)wba);
330
                break;
331
        case BA_SIZE_WORD:
332
                res = put_user(wbd & 0xffff, (short __user *)wba);
333
                break;
334
        case BA_SIZE_LONG:
335
                res = put_user(wbd, (int __user *)wba);
336
                break;
337
        }
338
 
339
        /* set_fs can not be moved, otherwise put_user() may oops */
340
        set_fs(old_fs);
341
 
342
 
343
#ifdef DEBUG
344
        printk("do_040writeback1, res=%d\n",res);
345
#endif
346
 
347
        return res;
348
}
349
 
350
/* after an exception in a writeback the stack frame corresponding
351
 * to that exception is discarded, set a few bits in the old frame
352
 * to simulate what it should look like
353
 */
354
static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
355
{
356
        fp->un.fmt7.faddr = wba;
357
        fp->un.fmt7.ssw = wbs & 0xff;
358
        if (wba != current->thread.faddr)
359
            fp->un.fmt7.ssw |= MA_040;
360
}
361
 
362
static inline void do_040writebacks(struct frame *fp)
363
{
364
        int res = 0;
365
#if 0
366
        if (fp->un.fmt7.wb1s & WBV_040)
367
                printk("access_error040: cannot handle 1st writeback. oops.\n");
368
#endif
369
 
370
        if ((fp->un.fmt7.wb2s & WBV_040) &&
371
            !(fp->un.fmt7.wb2s & WBTT_040)) {
372
                res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
373
                                       fp->un.fmt7.wb2d);
374
                if (res)
375
                        fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
376
                else
377
                        fp->un.fmt7.wb2s = 0;
378
        }
379
 
380
        /* do the 2nd wb only if the first one was successful (except for a kernel wb) */
381
        if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
382
                res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
383
                                       fp->un.fmt7.wb3d);
384
                if (res)
385
                    {
386
                        fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
387
 
388
                        fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
389
                        fp->un.fmt7.wb3s &= (~WBV_040);
390
                        fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
391
                        fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
392
                    }
393
                else
394
                        fp->un.fmt7.wb3s = 0;
395
        }
396
 
397
        if (res)
398
                send_fault_sig(&fp->ptregs);
399
}
400
 
401
/*
402
 * called from sigreturn(), must ensure userspace code didn't
403
 * manipulate exception frame to circumvent protection, then complete
404
 * pending writebacks
405
 * we just clear TM2 to turn it into an userspace access
406
 */
407
asmlinkage void berr_040cleanup(struct frame *fp)
408
{
409
        fp->un.fmt7.wb2s &= ~4;
410
        fp->un.fmt7.wb3s &= ~4;
411
 
412
        do_040writebacks(fp);
413
}
414
 
415
static inline void access_error040(struct frame *fp)
416
{
417
        unsigned short ssw = fp->un.fmt7.ssw;
418
        unsigned long mmusr;
419
 
420
#ifdef DEBUG
421
        printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
422
        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
423
                fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
424
        printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
425
                fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
426
                fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
427
#endif
428
 
429
        if (ssw & ATC_040) {
430
                unsigned long addr = fp->un.fmt7.faddr;
431
                unsigned long errorcode;
432
 
433
                /*
434
                 * The MMU status has to be determined AFTER the address
435
                 * has been corrected if there was a misaligned access (MA).
436
                 */
437
                if (ssw & MA_040)
438
                        addr = (addr + 7) & -8;
439
 
440
                /* MMU error, get the MMUSR info for this access */
441
                mmusr = probe040(!(ssw & RW_040), addr, ssw);
442
#ifdef DEBUG
443
                printk("mmusr = %lx\n", mmusr);
444
#endif
445
                errorcode = 1;
446
                if (!(mmusr & MMU_R_040)) {
447
                        /* clear the invalid atc entry */
448
                        __flush_tlb040_one(addr);
449
                        errorcode = 0;
450
                }
451
 
452
                /* despite what documentation seems to say, RMW
453
                 * accesses have always both the LK and RW bits set */
454
                if (!(ssw & RW_040) || (ssw & LK_040))
455
                        errorcode |= 2;
456
 
457
                if (do_page_fault(&fp->ptregs, addr, errorcode)) {
458
#ifdef DEBUG
459
                        printk("do_page_fault() !=0 \n");
460
#endif
461
                        if (user_mode(&fp->ptregs)){
462
                                /* delay writebacks after signal delivery */
463
#ifdef DEBUG
464
                                printk(".. was usermode - return\n");
465
#endif
466
                                return;
467
                        }
468
                        /* disable writeback into user space from kernel
469
                         * (if do_page_fault didn't fix the mapping,
470
                         * the writeback won't do good)
471
                         */
472
#ifdef DEBUG
473
                        printk(".. disabling wb2\n");
474
#endif
475
                        if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
476
                                fp->un.fmt7.wb2s &= ~WBV_040;
477
                }
478
        } else if (send_fault_sig(&fp->ptregs) > 0) {
479
                printk("68040 access error, ssw=%x\n", ssw);
480
                trap_c(fp);
481
        }
482
 
483
        do_040writebacks(fp);
484
}
485
#endif /* CONFIG_M68040 */
486
 
487
#if defined(CONFIG_SUN3)
488
#include <asm/sun3mmu.h>
489
 
490
extern int mmu_emu_handle_fault (unsigned long, int, int);
491
 
492
/* sun3 version of bus_error030 */
493
 
494
static inline void bus_error030 (struct frame *fp)
495
{
496
        unsigned char buserr_type = sun3_get_buserr ();
497
        unsigned long addr, errorcode;
498
        unsigned short ssw = fp->un.fmtb.ssw;
499
        extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
500
 
501
#ifdef DEBUG
502
        if (ssw & (FC | FB))
503
                printk ("Instruction fault at %#010lx\n",
504
                        ssw & FC ?
505
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
506
                        :
507
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
508
        if (ssw & DF)
509
                printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
510
                        ssw & RW ? "read" : "write",
511
                        fp->un.fmtb.daddr,
512
                        space_names[ssw & DFC], fp->ptregs.pc);
513
#endif
514
 
515
        /*
516
         * Check if this page should be demand-mapped. This needs to go before
517
         * the testing for a bad kernel-space access (demand-mapping applies
518
         * to kernel accesses too).
519
         */
520
 
521
        if ((ssw & DF)
522
            && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
523
                if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
524
                        return;
525
        }
526
 
527
        /* Check for kernel-space pagefault (BAD). */
528
        if (fp->ptregs.sr & PS_S) {
529
                /* kernel fault must be a data fault to user space */
530
                if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
531
                     // try checking the kernel mappings before surrender
532
                     if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
533
                          return;
534
                        /* instruction fault or kernel data fault! */
535
                        if (ssw & (FC | FB))
536
                                printk ("Instruction fault at %#010lx\n",
537
                                        fp->ptregs.pc);
538
                        if (ssw & DF) {
539
                                /* was this fault incurred testing bus mappings? */
540
                                if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
541
                                   (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
542
                                        send_fault_sig(&fp->ptregs);
543
                                        return;
544
                                }
545
 
546
                                printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
547
                                        ssw & RW ? "read" : "write",
548
                                        fp->un.fmtb.daddr,
549
                                        space_names[ssw & DFC], fp->ptregs.pc);
550
                        }
551
                        printk ("BAD KERNEL BUSERR\n");
552
 
553
                        die_if_kernel("Oops", &fp->ptregs,0);
554
                        force_sig(SIGKILL, current);
555
                        return;
556
                }
557
        } else {
558
                /* user fault */
559
                if (!(ssw & (FC | FB)) && !(ssw & DF))
560
                        /* not an instruction fault or data fault! BAD */
561
                        panic ("USER BUSERR w/o instruction or data fault");
562
        }
563
 
564
 
565
        /* First handle the data fault, if any.  */
566
        if (ssw & DF) {
567
                addr = fp->un.fmtb.daddr;
568
 
569
// errorcode bit 0:     0 -> no page            1 -> protection fault
570
// errorcode bit 1:     0 -> read fault         1 -> write fault
571
 
572
// (buserr_type & SUN3_BUSERR_PROTERR)  -> protection fault
573
// (buserr_type & SUN3_BUSERR_INVALID)  -> invalid page fault
574
 
575
                if (buserr_type & SUN3_BUSERR_PROTERR)
576
                        errorcode = 0x01;
577
                else if (buserr_type & SUN3_BUSERR_INVALID)
578
                        errorcode = 0x00;
579
                else {
580
#ifdef DEBUG
581
                        printk ("*** unexpected busfault type=%#04x\n", buserr_type);
582
                        printk ("invalid %s access at %#lx from pc %#lx\n",
583
                                !(ssw & RW) ? "write" : "read", addr,
584
                                fp->ptregs.pc);
585
#endif
586
                        die_if_kernel ("Oops", &fp->ptregs, buserr_type);
587
                        force_sig (SIGBUS, current);
588
                        return;
589
                }
590
 
591
//todo: wtf is RM bit? --m
592
                if (!(ssw & RW) || ssw & RM)
593
                        errorcode |= 0x02;
594
 
595
                /* Handle page fault. */
596
                do_page_fault (&fp->ptregs, addr, errorcode);
597
 
598
                /* Retry the data fault now. */
599
                return;
600
        }
601
 
602
        /* Now handle the instruction fault. */
603
 
604
        /* Get the fault address. */
605
        if (fp->ptregs.format == 0xA)
606
                addr = fp->ptregs.pc + 4;
607
        else
608
                addr = fp->un.fmtb.baddr;
609
        if (ssw & FC)
610
                addr -= 2;
611
 
612
        if (buserr_type & SUN3_BUSERR_INVALID) {
613
                if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
614
                        do_page_fault (&fp->ptregs, addr, 0);
615
       } else {
616
#ifdef DEBUG
617
                printk ("protection fault on insn access (segv).\n");
618
#endif
619
                force_sig (SIGSEGV, current);
620
       }
621
}
622
#else
623
#if defined(CPU_M68020_OR_M68030)
624
static inline void bus_error030 (struct frame *fp)
625
{
626
        volatile unsigned short temp;
627
        unsigned short mmusr;
628
        unsigned long addr, errorcode;
629
        unsigned short ssw = fp->un.fmtb.ssw;
630
#ifdef DEBUG
631
        unsigned long desc;
632
 
633
        printk ("pid = %x  ", current->pid);
634
        printk ("SSW=%#06x  ", ssw);
635
 
636
        if (ssw & (FC | FB))
637
                printk ("Instruction fault at %#010lx\n",
638
                        ssw & FC ?
639
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
640
                        :
641
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
642
        if (ssw & DF)
643
                printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
644
                        ssw & RW ? "read" : "write",
645
                        fp->un.fmtb.daddr,
646
                        space_names[ssw & DFC], fp->ptregs.pc);
647
#endif
648
 
649
        /* ++andreas: If a data fault and an instruction fault happen
650
           at the same time map in both pages.  */
651
 
652
        /* First handle the data fault, if any.  */
653
        if (ssw & DF) {
654
                addr = fp->un.fmtb.daddr;
655
 
656
#ifdef DEBUG
657
                asm volatile ("ptestr %3,%2@,#7,%0\n\t"
658
                              "pmove %%psr,%1@"
659
                              : "=a&" (desc)
660
                              : "a" (&temp), "a" (addr), "d" (ssw));
661
#else
662
                asm volatile ("ptestr %2,%1@,#7\n\t"
663
                              "pmove %%psr,%0@"
664
                              : : "a" (&temp), "a" (addr), "d" (ssw));
665
#endif
666
                mmusr = temp;
667
 
668
#ifdef DEBUG
669
                printk("mmusr is %#x for addr %#lx in task %p\n",
670
                       mmusr, addr, current);
671
                printk("descriptor address is %#lx, contents %#lx\n",
672
                       __va(desc), *(unsigned long *)__va(desc));
673
#endif
674
 
675
                errorcode = (mmusr & MMU_I) ? 0 : 1;
676
                if (!(ssw & RW) || (ssw & RM))
677
                        errorcode |= 2;
678
 
679
                if (mmusr & (MMU_I | MMU_WP)) {
680
                        if (ssw & 4) {
681
                                printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
682
                                       ssw & RW ? "read" : "write",
683
                                       fp->un.fmtb.daddr,
684
                                       space_names[ssw & DFC], fp->ptregs.pc);
685
                                goto buserr;
686
                        }
687
                        /* Don't try to do anything further if an exception was
688
                           handled. */
689
                        if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
690
                                return;
691
                } else if (!(mmusr & MMU_I)) {
692
                        /* probably a 020 cas fault */
693
                        if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
694
                                printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
695
                } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
696
                        printk("invalid %s access at %#lx from pc %#lx\n",
697
                               !(ssw & RW) ? "write" : "read", addr,
698
                               fp->ptregs.pc);
699
                        die_if_kernel("Oops",&fp->ptregs,mmusr);
700
                        force_sig(SIGSEGV, current);
701
                        return;
702
                } else {
703
#if 0
704
                        static volatile long tlong;
705
#endif
706
 
707
                        printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
708
                               !(ssw & RW) ? "write" : "read", addr,
709
                               fp->ptregs.pc, ssw);
710
                        asm volatile ("ptestr #1,%1@,#0\n\t"
711
                                      "pmove %%psr,%0@"
712
                                      : /* no outputs */
713
                                      : "a" (&temp), "a" (addr));
714
                        mmusr = temp;
715
 
716
                        printk ("level 0 mmusr is %#x\n", mmusr);
717
#if 0
718
                        asm volatile ("pmove %%tt0,%0@"
719
                                      : /* no outputs */
720
                                      : "a" (&tlong));
721
                        printk("tt0 is %#lx, ", tlong);
722
                        asm volatile ("pmove %%tt1,%0@"
723
                                      : /* no outputs */
724
                                      : "a" (&tlong));
725
                        printk("tt1 is %#lx\n", tlong);
726
#endif
727
#ifdef DEBUG
728
                        printk("Unknown SIGSEGV - 1\n");
729
#endif
730
                        die_if_kernel("Oops",&fp->ptregs,mmusr);
731
                        force_sig(SIGSEGV, current);
732
                        return;
733
                }
734
 
735
                /* setup an ATC entry for the access about to be retried */
736
                if (!(ssw & RW) || (ssw & RM))
737
                        asm volatile ("ploadw %1,%0@" : /* no outputs */
738
                                      : "a" (addr), "d" (ssw));
739
                else
740
                        asm volatile ("ploadr %1,%0@" : /* no outputs */
741
                                      : "a" (addr), "d" (ssw));
742
        }
743
 
744
        /* Now handle the instruction fault. */
745
 
746
        if (!(ssw & (FC|FB)))
747
                return;
748
 
749
        if (fp->ptregs.sr & PS_S) {
750
                printk("Instruction fault at %#010lx\n",
751
                        fp->ptregs.pc);
752
        buserr:
753
                printk ("BAD KERNEL BUSERR\n");
754
                die_if_kernel("Oops",&fp->ptregs,0);
755
                force_sig(SIGKILL, current);
756
                return;
757
        }
758
 
759
        /* get the fault address */
760
        if (fp->ptregs.format == 10)
761
                addr = fp->ptregs.pc + 4;
762
        else
763
                addr = fp->un.fmtb.baddr;
764
        if (ssw & FC)
765
                addr -= 2;
766
 
767
        if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
768
                /* Insn fault on same page as data fault.  But we
769
                   should still create the ATC entry.  */
770
                goto create_atc_entry;
771
 
772
#ifdef DEBUG
773
        asm volatile ("ptestr #1,%2@,#7,%0\n\t"
774
                      "pmove %%psr,%1@"
775
                      : "=a&" (desc)
776
                      : "a" (&temp), "a" (addr));
777
#else
778
        asm volatile ("ptestr #1,%1@,#7\n\t"
779
                      "pmove %%psr,%0@"
780
                      : : "a" (&temp), "a" (addr));
781
#endif
782
        mmusr = temp;
783
 
784
#ifdef DEBUG
785
        printk ("mmusr is %#x for addr %#lx in task %p\n",
786
                mmusr, addr, current);
787
        printk ("descriptor address is %#lx, contents %#lx\n",
788
                __va(desc), *(unsigned long *)__va(desc));
789
#endif
790
 
791
        if (mmusr & MMU_I)
792
                do_page_fault (&fp->ptregs, addr, 0);
793
        else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
794
                printk ("invalid insn access at %#lx from pc %#lx\n",
795
                        addr, fp->ptregs.pc);
796
#ifdef DEBUG
797
                printk("Unknown SIGSEGV - 2\n");
798
#endif
799
                die_if_kernel("Oops",&fp->ptregs,mmusr);
800
                force_sig(SIGSEGV, current);
801
                return;
802
        }
803
 
804
create_atc_entry:
805
        /* setup an ATC entry for the access about to be retried */
806
        asm volatile ("ploadr #2,%0@" : /* no outputs */
807
                      : "a" (addr));
808
}
809
#endif /* CPU_M68020_OR_M68030 */
810
#endif /* !CONFIG_SUN3 */
811
 
812
asmlinkage void buserr_c(struct frame *fp)
813
{
814
        /* Only set esp0 if coming from user mode */
815
        if (user_mode(&fp->ptregs))
816
                current->thread.esp0 = (unsigned long) fp;
817
 
818
#ifdef DEBUG
819
        printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
820
#endif
821
 
822
        switch (fp->ptregs.format) {
823
#if defined (CONFIG_M68060)
824
        case 4:                         /* 68060 access error */
825
          access_error060 (fp);
826
          break;
827
#endif
828
#if defined (CONFIG_M68040)
829
        case 0x7:                       /* 68040 access error */
830
          access_error040 (fp);
831
          break;
832
#endif
833
#if defined (CPU_M68020_OR_M68030)
834
        case 0xa:
835
        case 0xb:
836
          bus_error030 (fp);
837
          break;
838
#endif
839
        default:
840
          die_if_kernel("bad frame format",&fp->ptregs,0);
841
#ifdef DEBUG
842
          printk("Unknown SIGSEGV - 4\n");
843
#endif
844
          force_sig(SIGSEGV, current);
845
        }
846
}
847
 
848
 
849
static int kstack_depth_to_print = 48;
850
 
851
void show_trace(unsigned long *stack)
852
{
853
        unsigned long *endstack;
854
        unsigned long addr;
855
        int i;
856
 
857
        printk("Call Trace:");
858
        addr = (unsigned long)stack + THREAD_SIZE - 1;
859
        endstack = (unsigned long *)(addr & -THREAD_SIZE);
860
        i = 0;
861
        while (stack + 1 <= endstack) {
862
                addr = *stack++;
863
                /*
864
                 * If the address is either in the text segment of the
865
                 * kernel, or in the region which contains vmalloc'ed
866
                 * memory, it *may* be the address of a calling
867
                 * routine; if so, print it so that someone tracing
868
                 * down the cause of the crash will be able to figure
869
                 * out the call path that was taken.
870
                 */
871
                if (__kernel_text_address(addr)) {
872
#ifndef CONFIG_KALLSYMS
873
                        if (i % 5 == 0)
874
                                printk("\n       ");
875
#endif
876
                        printk(" [<%08lx>]", addr);
877
                        print_symbol(" %s\n", addr);
878
                        i++;
879
                }
880
        }
881
        printk("\n");
882
}
883
 
884
void show_registers(struct pt_regs *regs)
885
{
886
        struct frame *fp = (struct frame *)regs;
887
        mm_segment_t old_fs = get_fs();
888
        u16 c, *cp;
889
        unsigned long addr;
890
        int i;
891
 
892
        print_modules();
893
        printk("PC: [<%08lx>]",regs->pc);
894
        print_symbol(" %s", regs->pc);
895
        printk("\nSR: %04x  SP: %p  a2: %08lx\n",
896
               regs->sr, regs, regs->a2);
897
        printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
898
               regs->d0, regs->d1, regs->d2, regs->d3);
899
        printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
900
               regs->d4, regs->d5, regs->a0, regs->a1);
901
 
902
        printk("Process %s (pid: %d, task=%p)\n",
903
                current->comm, task_pid_nr(current), current);
904
        addr = (unsigned long)&fp->un;
905
        printk("Frame format=%X ", regs->format);
906
        switch (regs->format) {
907
        case 0x2:
908
                printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
909
                addr += sizeof(fp->un.fmt2);
910
                break;
911
        case 0x3:
912
                printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
913
                addr += sizeof(fp->un.fmt3);
914
                break;
915
        case 0x4:
916
                printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
917
                        : "eff addr=%08lx pc=%08lx\n"),
918
                        fp->un.fmt4.effaddr, fp->un.fmt4.pc);
919
                addr += sizeof(fp->un.fmt4);
920
                break;
921
        case 0x7:
922
                printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
923
                        fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
924
                printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
925
                        fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
926
                printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
927
                        fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
928
                printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
929
                        fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
930
                printk("push data: %08lx %08lx %08lx %08lx\n",
931
                        fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
932
                        fp->un.fmt7.pd3);
933
                addr += sizeof(fp->un.fmt7);
934
                break;
935
        case 0x9:
936
                printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
937
                addr += sizeof(fp->un.fmt9);
938
                break;
939
        case 0xa:
940
                printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
941
                        fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
942
                        fp->un.fmta.daddr, fp->un.fmta.dobuf);
943
                addr += sizeof(fp->un.fmta);
944
                break;
945
        case 0xb:
946
                printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
947
                        fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
948
                        fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
949
                printk("baddr=%08lx dibuf=%08lx ver=%x\n",
950
                        fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
951
                addr += sizeof(fp->un.fmtb);
952
                break;
953
        default:
954
                printk("\n");
955
        }
956
        show_stack(NULL, (unsigned long *)addr);
957
 
958
        printk("Code:");
959
        set_fs(KERNEL_DS);
960
        cp = (u16 *)regs->pc;
961
        for (i = -8; i < 16; i++) {
962
                if (get_user(c, cp + i) && i >= 0) {
963
                        printk(" Bad PC value.");
964
                        break;
965
                }
966
                printk(i ? " %04x" : " <%04x>", c);
967
        }
968
        set_fs(old_fs);
969
        printk ("\n");
970
}
971
 
972
void show_stack(struct task_struct *task, unsigned long *stack)
973
{
974
        unsigned long *p;
975
        unsigned long *endstack;
976
        int i;
977
 
978
        if (!stack) {
979
                if (task)
980
                        stack = (unsigned long *)task->thread.esp0;
981
                else
982
                        stack = (unsigned long *)&stack;
983
        }
984
        endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
985
 
986
        printk("Stack from %08lx:", (unsigned long)stack);
987
        p = stack;
988
        for (i = 0; i < kstack_depth_to_print; i++) {
989
                if (p + 1 > endstack)
990
                        break;
991
                if (i % 8 == 0)
992
                        printk("\n       ");
993
                printk(" %08lx", *p++);
994
        }
995
        printk("\n");
996
        show_trace(stack);
997
}
998
 
999
/*
1000
 * The architecture-independent backtrace generator
1001
 */
1002
void dump_stack(void)
1003
{
1004
        unsigned long stack;
1005
 
1006
        show_trace(&stack);
1007
}
1008
 
1009
EXPORT_SYMBOL(dump_stack);
1010
 
1011
void bad_super_trap (struct frame *fp)
1012
{
1013
        console_verbose();
1014
        if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
1015
                printk ("*** %s ***   FORMAT=%X\n",
1016
                        vec_names[(fp->ptregs.vector) >> 2],
1017
                        fp->ptregs.format);
1018
        else
1019
                printk ("*** Exception %d ***   FORMAT=%X\n",
1020
                        (fp->ptregs.vector) >> 2,
1021
                        fp->ptregs.format);
1022
        if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
1023
                unsigned short ssw = fp->un.fmtb.ssw;
1024
 
1025
                printk ("SSW=%#06x  ", ssw);
1026
 
1027
                if (ssw & RC)
1028
                        printk ("Pipe stage C instruction fault at %#010lx\n",
1029
                                (fp->ptregs.format) == 0xA ?
1030
                                fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
1031
                if (ssw & RB)
1032
                        printk ("Pipe stage B instruction fault at %#010lx\n",
1033
                                (fp->ptregs.format) == 0xA ?
1034
                                fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
1035
                if (ssw & DF)
1036
                        printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
1037
                                ssw & RW ? "read" : "write",
1038
                                fp->un.fmtb.daddr, space_names[ssw & DFC],
1039
                                fp->ptregs.pc);
1040
        }
1041
        printk ("Current process id is %d\n", task_pid_nr(current));
1042
        die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
1043
}
1044
 
1045
asmlinkage void trap_c(struct frame *fp)
1046
{
1047
        int sig;
1048
        siginfo_t info;
1049
 
1050
        if (fp->ptregs.sr & PS_S) {
1051
                if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
1052
                        /* traced a trapping instruction */
1053
                        current->ptrace |= PT_DTRACE;
1054
                } else
1055
                        bad_super_trap(fp);
1056
                return;
1057
        }
1058
 
1059
        /* send the appropriate signal to the user program */
1060
        switch ((fp->ptregs.vector) >> 2) {
1061
            case VEC_ADDRERR:
1062
                info.si_code = BUS_ADRALN;
1063
                sig = SIGBUS;
1064
                break;
1065
            case VEC_ILLEGAL:
1066
            case VEC_LINE10:
1067
            case VEC_LINE11:
1068
                info.si_code = ILL_ILLOPC;
1069
                sig = SIGILL;
1070
                break;
1071
            case VEC_PRIV:
1072
                info.si_code = ILL_PRVOPC;
1073
                sig = SIGILL;
1074
                break;
1075
            case VEC_COPROC:
1076
                info.si_code = ILL_COPROC;
1077
                sig = SIGILL;
1078
                break;
1079
            case VEC_TRAP1:
1080
            case VEC_TRAP2:
1081
            case VEC_TRAP3:
1082
            case VEC_TRAP4:
1083
            case VEC_TRAP5:
1084
            case VEC_TRAP6:
1085
            case VEC_TRAP7:
1086
            case VEC_TRAP8:
1087
            case VEC_TRAP9:
1088
            case VEC_TRAP10:
1089
            case VEC_TRAP11:
1090
            case VEC_TRAP12:
1091
            case VEC_TRAP13:
1092
            case VEC_TRAP14:
1093
                info.si_code = ILL_ILLTRP;
1094
                sig = SIGILL;
1095
                break;
1096
            case VEC_FPBRUC:
1097
            case VEC_FPOE:
1098
            case VEC_FPNAN:
1099
                info.si_code = FPE_FLTINV;
1100
                sig = SIGFPE;
1101
                break;
1102
            case VEC_FPIR:
1103
                info.si_code = FPE_FLTRES;
1104
                sig = SIGFPE;
1105
                break;
1106
            case VEC_FPDIVZ:
1107
                info.si_code = FPE_FLTDIV;
1108
                sig = SIGFPE;
1109
                break;
1110
            case VEC_FPUNDER:
1111
                info.si_code = FPE_FLTUND;
1112
                sig = SIGFPE;
1113
                break;
1114
            case VEC_FPOVER:
1115
                info.si_code = FPE_FLTOVF;
1116
                sig = SIGFPE;
1117
                break;
1118
            case VEC_ZERODIV:
1119
                info.si_code = FPE_INTDIV;
1120
                sig = SIGFPE;
1121
                break;
1122
            case VEC_CHK:
1123
            case VEC_TRAP:
1124
                info.si_code = FPE_INTOVF;
1125
                sig = SIGFPE;
1126
                break;
1127
            case VEC_TRACE:             /* ptrace single step */
1128
                info.si_code = TRAP_TRACE;
1129
                sig = SIGTRAP;
1130
                break;
1131
            case VEC_TRAP15:            /* breakpoint */
1132
                info.si_code = TRAP_BRKPT;
1133
                sig = SIGTRAP;
1134
                break;
1135
            default:
1136
                info.si_code = ILL_ILLOPC;
1137
                sig = SIGILL;
1138
                break;
1139
        }
1140
        info.si_signo = sig;
1141
        info.si_errno = 0;
1142
        switch (fp->ptregs.format) {
1143
            default:
1144
                info.si_addr = (void *) fp->ptregs.pc;
1145
                break;
1146
            case 2:
1147
                info.si_addr = (void *) fp->un.fmt2.iaddr;
1148
                break;
1149
            case 7:
1150
                info.si_addr = (void *) fp->un.fmt7.effaddr;
1151
                break;
1152
            case 9:
1153
                info.si_addr = (void *) fp->un.fmt9.iaddr;
1154
                break;
1155
            case 10:
1156
                info.si_addr = (void *) fp->un.fmta.daddr;
1157
                break;
1158
            case 11:
1159
                info.si_addr = (void *) fp->un.fmtb.daddr;
1160
                break;
1161
        }
1162
        force_sig_info (sig, &info, current);
1163
}
1164
 
1165
void die_if_kernel (char *str, struct pt_regs *fp, int nr)
1166
{
1167
        if (!(fp->sr & PS_S))
1168
                return;
1169
 
1170
        console_verbose();
1171
        printk("%s: %08x\n",str,nr);
1172
        show_registers(fp);
1173
        add_taint(TAINT_DIE);
1174
        do_exit(SIGSEGV);
1175
}
1176
 
1177
/*
1178
 * This function is called if an error occur while accessing
1179
 * user-space from the fpsp040 code.
1180
 */
1181
asmlinkage void fpsp040_die(void)
1182
{
1183
        do_exit(SIGSEGV);
1184
}
1185
 
1186
#ifdef CONFIG_M68KFPU_EMU
1187
asmlinkage void fpemu_signal(int signal, int code, void *addr)
1188
{
1189
        siginfo_t info;
1190
 
1191
        info.si_signo = signal;
1192
        info.si_errno = 0;
1193
        info.si_code = code;
1194
        info.si_addr = addr;
1195
        force_sig_info(signal, &info, current);
1196
}
1197
#endif

powered by: WebSVN 2.1.0

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