Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/csky/kernel/traps.c
26444 views
1
// SPDX-License-Identifier: GPL-2.0
2
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3
4
#include <linux/cpu.h>
5
#include <linux/sched.h>
6
#include <linux/signal.h>
7
#include <linux/kernel.h>
8
#include <linux/mm.h>
9
#include <linux/module.h>
10
#include <linux/user.h>
11
#include <linux/string.h>
12
#include <linux/linkage.h>
13
#include <linux/init.h>
14
#include <linux/ptrace.h>
15
#include <linux/kallsyms.h>
16
#include <linux/rtc.h>
17
#include <linux/uaccess.h>
18
#include <linux/kprobes.h>
19
#include <linux/kdebug.h>
20
#include <linux/sched/debug.h>
21
22
#include <asm/setup.h>
23
#include <asm/traps.h>
24
#include <asm/pgalloc.h>
25
#include <asm/siginfo.h>
26
27
#include <asm/mmu_context.h>
28
29
#ifdef CONFIG_CPU_HAS_FPU
30
#include <abi/fpu.h>
31
#endif
32
33
int show_unhandled_signals = 1;
34
35
/* Defined in entry.S */
36
asmlinkage void csky_trap(void);
37
38
asmlinkage void csky_systemcall(void);
39
asmlinkage void csky_cmpxchg(void);
40
asmlinkage void csky_get_tls(void);
41
asmlinkage void csky_irq(void);
42
43
asmlinkage void csky_pagefault(void);
44
45
/* Defined in head.S */
46
asmlinkage void _start_smp_secondary(void);
47
48
void __init pre_trap_init(void)
49
{
50
int i;
51
52
mtcr("vbr", vec_base);
53
54
for (i = 1; i < 128; i++)
55
VEC_INIT(i, csky_trap);
56
}
57
58
void __init trap_init(void)
59
{
60
VEC_INIT(VEC_AUTOVEC, csky_irq);
61
62
/* setup trap0 trap2 trap3 */
63
VEC_INIT(VEC_TRAP0, csky_systemcall);
64
VEC_INIT(VEC_TRAP2, csky_cmpxchg);
65
VEC_INIT(VEC_TRAP3, csky_get_tls);
66
67
/* setup MMU TLB exception */
68
VEC_INIT(VEC_TLBINVALIDL, csky_pagefault);
69
VEC_INIT(VEC_TLBINVALIDS, csky_pagefault);
70
VEC_INIT(VEC_TLBMODIFIED, csky_pagefault);
71
72
#ifdef CONFIG_CPU_HAS_FPU
73
init_fpu();
74
#endif
75
76
#ifdef CONFIG_SMP
77
mtcr("cr<28, 0>", virt_to_phys(vec_base));
78
79
VEC_INIT(VEC_RESET, (void *)virt_to_phys(_start_smp_secondary));
80
#endif
81
}
82
83
static DEFINE_SPINLOCK(die_lock);
84
85
void die(struct pt_regs *regs, const char *str)
86
{
87
static int die_counter;
88
int ret;
89
90
oops_enter();
91
92
spin_lock_irq(&die_lock);
93
console_verbose();
94
bust_spinlocks(1);
95
96
pr_emerg("%s [#%d]\n", str, ++die_counter);
97
print_modules();
98
show_regs(regs);
99
show_stack(current, (unsigned long *)regs->regs[4], KERN_INFO);
100
101
ret = notify_die(DIE_OOPS, str, regs, 0, trap_no(regs), SIGSEGV);
102
103
bust_spinlocks(0);
104
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
105
spin_unlock_irq(&die_lock);
106
oops_exit();
107
108
if (in_interrupt())
109
panic("Fatal exception in interrupt");
110
if (panic_on_oops)
111
panic("Fatal exception");
112
if (ret != NOTIFY_STOP)
113
make_task_dead(SIGSEGV);
114
}
115
116
void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)
117
{
118
struct task_struct *tsk = current;
119
120
if (show_unhandled_signals && unhandled_signal(tsk, signo)
121
&& printk_ratelimit()) {
122
pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x%08lx",
123
tsk->comm, task_pid_nr(tsk), signo, code, addr);
124
print_vma_addr(KERN_CONT " in ", instruction_pointer(regs));
125
pr_cont("\n");
126
show_regs(regs);
127
}
128
129
force_sig_fault(signo, code, (void __user *)addr);
130
}
131
132
static void do_trap_error(struct pt_regs *regs, int signo, int code,
133
unsigned long addr, const char *str)
134
{
135
current->thread.trap_no = trap_no(regs);
136
137
if (user_mode(regs)) {
138
do_trap(regs, signo, code, addr);
139
} else {
140
if (!fixup_exception(regs))
141
die(regs, str);
142
}
143
}
144
145
#define DO_ERROR_INFO(name, signo, code, str) \
146
asmlinkage __visible void name(struct pt_regs *regs) \
147
{ \
148
do_trap_error(regs, signo, code, regs->pc, "Oops - " str); \
149
}
150
151
DO_ERROR_INFO(do_trap_unknown,
152
SIGILL, ILL_ILLTRP, "unknown exception");
153
DO_ERROR_INFO(do_trap_zdiv,
154
SIGFPE, FPE_INTDIV, "error zero div exception");
155
DO_ERROR_INFO(do_trap_buserr,
156
SIGSEGV, ILL_ILLADR, "error bus error exception");
157
158
asmlinkage void do_trap_misaligned(struct pt_regs *regs)
159
{
160
#ifdef CONFIG_CPU_NEED_SOFTALIGN
161
csky_alignment(regs);
162
#else
163
current->thread.trap_no = trap_no(regs);
164
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->pc,
165
"Oops - load/store address misaligned");
166
#endif
167
}
168
169
asmlinkage void do_trap_bkpt(struct pt_regs *regs)
170
{
171
#ifdef CONFIG_KPROBES
172
if (kprobe_single_step_handler(regs))
173
return;
174
#endif
175
#ifdef CONFIG_UPROBES
176
if (uprobe_single_step_handler(regs))
177
return;
178
#endif
179
if (user_mode(regs)) {
180
send_sig(SIGTRAP, current, 0);
181
return;
182
}
183
184
do_trap_error(regs, SIGILL, ILL_ILLTRP, regs->pc,
185
"Oops - illegal trap exception");
186
}
187
188
asmlinkage void do_trap_illinsn(struct pt_regs *regs)
189
{
190
current->thread.trap_no = trap_no(regs);
191
192
#ifdef CONFIG_KPROBES
193
if (kprobe_breakpoint_handler(regs))
194
return;
195
#endif
196
#ifdef CONFIG_UPROBES
197
if (uprobe_breakpoint_handler(regs))
198
return;
199
#endif
200
#ifndef CONFIG_CPU_NO_USER_BKPT
201
if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT) {
202
send_sig(SIGTRAP, current, 0);
203
return;
204
}
205
#endif
206
207
do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc,
208
"Oops - illegal instruction exception");
209
}
210
211
asmlinkage void do_trap_fpe(struct pt_regs *regs)
212
{
213
#ifdef CONFIG_CPU_HAS_FPU
214
return fpu_fpe(regs);
215
#else
216
do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc,
217
"Oops - fpu instruction exception");
218
#endif
219
}
220
221
asmlinkage void do_trap_priv(struct pt_regs *regs)
222
{
223
#ifdef CONFIG_CPU_HAS_FPU
224
if (user_mode(regs) && fpu_libc_helper(regs))
225
return;
226
#endif
227
do_trap_error(regs, SIGILL, ILL_PRVOPC, regs->pc,
228
"Oops - illegal privileged exception");
229
}
230
231
asmlinkage void trap_c(struct pt_regs *regs)
232
{
233
switch (trap_no(regs)) {
234
case VEC_ZERODIV:
235
do_trap_zdiv(regs);
236
break;
237
case VEC_TRACE:
238
do_trap_bkpt(regs);
239
break;
240
case VEC_ILLEGAL:
241
do_trap_illinsn(regs);
242
break;
243
case VEC_TRAP1:
244
case VEC_BREAKPOINT:
245
do_trap_bkpt(regs);
246
break;
247
case VEC_ACCESS:
248
do_trap_buserr(regs);
249
break;
250
case VEC_ALIGN:
251
do_trap_misaligned(regs);
252
break;
253
case VEC_FPE:
254
do_trap_fpe(regs);
255
break;
256
case VEC_PRIV:
257
do_trap_priv(regs);
258
break;
259
default:
260
do_trap_unknown(regs);
261
break;
262
}
263
}
264
265