Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
sh
kernel
traps.c
Go to the documentation of this file.
1
#include <
linux/bug.h
>
2
#include <
linux/io.h
>
3
#include <linux/types.h>
4
#include <
linux/kdebug.h
>
5
#include <linux/signal.h>
6
#include <linux/sched.h>
7
#include <
linux/uaccess.h
>
8
#include <
linux/hardirq.h
>
9
#include <linux/kernel.h>
10
#include <linux/kexec.h>
11
#include <linux/module.h>
12
#include <
asm/unwinder.h
>
13
#include <asm/traps.h>
14
15
static
DEFINE_SPINLOCK
(
die_lock
);
16
17
void
die
(
const
char
*
str
,
struct
pt_regs
*
regs
,
long
err
)
18
{
19
static
int
die_counter;
20
21
oops_enter
();
22
23
spin_lock_irq(&
die_lock
);
24
console_verbose();
25
bust_spinlocks
(1);
26
27
printk
(
"%s: %04lx [#%d]\n"
, str, err & 0xffff, ++die_counter);
28
print_modules
();
29
show_regs
(regs);
30
31
printk
(
"Process: %s (pid: %d, stack limit = %p)\n"
,
current
->comm,
32
task_pid_nr(
current
),
task_stack_page
(
current
) + 1);
33
34
if
(!
user_mode
(regs) ||
in_interrupt
())
35
dump_mem
(
"Stack: "
, regs->
regs
[15],
THREAD_SIZE
+
36
(
unsigned
long
)
task_stack_page
(
current
));
37
38
notify_die
(
DIE_OOPS
, str, regs, err, 255,
SIGSEGV
);
39
40
bust_spinlocks
(0);
41
add_taint
(
TAINT_DIE
);
42
spin_unlock_irq(&
die_lock
);
43
oops_exit
();
44
45
if
(
kexec_should_crash
(
current
))
46
crash_kexec
(regs);
47
48
if
(
in_interrupt
())
49
panic
(
"Fatal exception in interrupt"
);
50
51
if
(
panic_on_oops
)
52
panic
(
"Fatal exception"
);
53
54
do_exit
(
SIGSEGV
);
55
}
56
57
void
die_if_kernel
(
const
char
*
str
,
struct
pt_regs
*
regs
,
long
err
)
58
{
59
if
(!
user_mode
(regs))
60
die
(str, regs, err);
61
}
62
63
/*
64
* try and fix up kernelspace address errors
65
* - userspace errors just cause EFAULT to be returned, resulting in SEGV
66
* - kernel/userspace interfaces cause a jump to an appropriate handler
67
* - other kernel errors are bad
68
*/
69
void
die_if_no_fixup
(
const
char
*
str
,
struct
pt_regs
*
regs
,
long
err
)
70
{
71
if
(!
user_mode
(regs)) {
72
const
struct
exception_table_entry
*
fixup
;
73
fixup =
search_exception_tables
(regs->
pc
);
74
if
(fixup) {
75
regs->
pc
= fixup->
fixup
;
76
return
;
77
}
78
79
die
(str, regs, err);
80
}
81
}
82
83
#ifdef CONFIG_GENERIC_BUG
84
static
void
handle_BUG
(
struct
pt_regs
*
regs
)
85
{
86
const
struct
bug_entry *bug;
87
unsigned
long
bugaddr = regs->
pc
;
88
enum
bug_trap_type
tt
;
89
90
if
(!
is_valid_bugaddr
(bugaddr))
91
goto
invalid
;
92
93
bug =
find_bug
(bugaddr);
94
95
/* Switch unwinders when unwind_stack() is called */
96
if
(bug->flags &
BUGFLAG_UNWINDER
)
97
unwinder_faulted
= 1;
98
99
tt =
report_bug
(bugaddr, regs);
100
if
(tt ==
BUG_TRAP_TYPE_WARN
) {
101
regs->
pc
+=
instruction_size
(bugaddr);
102
return
;
103
}
104
105
invalid
:
106
die
(
"Kernel BUG"
, regs,
TRAPA_BUG_OPCODE
& 0xff);
107
}
108
109
int
is_valid_bugaddr
(
unsigned
long
addr
)
110
{
111
insn_size_t
opcode
;
112
113
if
(addr <
PAGE_OFFSET
)
114
return
0;
115
if
(
probe_kernel_address
((
insn_size_t
*)addr, opcode))
116
return
0;
117
if
(opcode ==
TRAPA_BUG_OPCODE
)
118
return
1;
119
120
return
0;
121
}
122
#endif
123
124
/*
125
* Generic trap handler.
126
*/
127
BUILD_TRAP_HANDLER
(
debug
)
128
{
129
TRAP_HANDLER_DECL
;
130
131
/* Rewind */
132
regs->
pc
-=
instruction_size
(
__raw_readw
(regs->
pc
- 4));
133
134
if
(
notify_die
(
DIE_TRAP
,
"debug trap"
, regs, 0, vec & 0xff,
135
SIGTRAP
) == NOTIFY_STOP)
136
return
;
137
138
force_sig
(
SIGTRAP
,
current
);
139
}
140
141
/*
142
* Special handler for BUG() traps.
143
*/
144
BUILD_TRAP_HANDLER
(bug)
145
{
146
TRAP_HANDLER_DECL
;
147
148
/* Rewind */
149
regs->
pc
-=
instruction_size
(
__raw_readw
(regs->
pc
- 4));
150
151
if
(
notify_die
(
DIE_TRAP
,
"bug trap"
, regs, 0,
TRAPA_BUG_OPCODE
& 0xff,
152
SIGTRAP
) == NOTIFY_STOP)
153
return
;
154
155
#ifdef CONFIG_GENERIC_BUG
156
if
(
__kernel_text_address
(
instruction_pointer
(regs))) {
157
insn_size_t
insn
= *(
insn_size_t
*)
instruction_pointer
(regs);
158
if
(insn ==
TRAPA_BUG_OPCODE
)
159
handle_BUG
(regs);
160
return
;
161
}
162
#endif
163
164
force_sig
(
SIGTRAP
,
current
);
165
}
166
167
BUILD_TRAP_HANDLER
(
nmi
)
168
{
169
unsigned
int
cpu
=
smp_processor_id
();
170
TRAP_HANDLER_DECL
;
171
172
nmi_enter
();
173
nmi_count
(cpu)++;
174
175
switch
(
notify_die
(
DIE_NMI
,
"NMI"
, regs, 0, vec & 0xff,
SIGINT
)) {
176
case
NOTIFY_OK:
177
case
NOTIFY_STOP:
178
break
;
179
case
NOTIFY_BAD:
180
die
(
"Fatal Non-Maskable Interrupt"
, regs,
SIGINT
);
181
default
:
182
printk
(
KERN_ALERT
"Got NMI, but nobody cared. Ignoring...\n"
);
183
break
;
184
}
185
186
nmi_exit
();
187
}
Generated on Thu Jan 10 2013 12:53:46 for Linux Kernel by
1.8.2