Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arc/kernel/traps.c
26444 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Traps/Non-MMU Exception handling for ARC
4
*
5
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
6
*
7
* vineetg: May 2011
8
* -user-space unaligned access emulation
9
*
10
* Rahul Trivedi: Codito Technologies 2004
11
*/
12
13
#include <linux/sched/signal.h>
14
#include <linux/kdebug.h>
15
#include <linux/uaccess.h>
16
#include <linux/ptrace.h>
17
#include <linux/kprobes.h>
18
#include <linux/kgdb.h>
19
#include <asm/entry.h>
20
#include <asm/setup.h>
21
#include <linux/unaligned.h>
22
#include <asm/kprobes.h>
23
#include "unaligned.h"
24
25
void die(const char *str, struct pt_regs *regs, unsigned long address)
26
{
27
show_kernel_fault_diag(str, regs, address);
28
29
/* DEAD END */
30
__asm__("flag 1");
31
}
32
33
/*
34
* Helper called for bulk of exceptions NOT needing specific handling
35
* -for user faults enqueues requested signal
36
* -for kernel, chk if due to copy_(to|from)_user, otherwise die()
37
*/
38
static noinline int
39
unhandled_exception(const char *str, struct pt_regs *regs,
40
int signo, int si_code, void __user *addr)
41
{
42
if (user_mode(regs)) {
43
struct task_struct *tsk = current;
44
45
tsk->thread.fault_address = (__force unsigned int)addr;
46
47
force_sig_fault(signo, si_code, addr);
48
49
} else {
50
/* If not due to copy_(to|from)_user, we are doomed */
51
if (fixup_exception(regs))
52
return 0;
53
54
die(str, regs, (unsigned long)addr);
55
}
56
57
return 1;
58
}
59
60
#define DO_ERROR_INFO(signr, str, name, sicode) \
61
int name(unsigned long address, struct pt_regs *regs) \
62
{ \
63
return unhandled_exception(str, regs, signr, sicode, \
64
(void __user *)address); \
65
}
66
67
/*
68
* Entry points for exceptions NOT needing specific handling
69
*/
70
DO_ERROR_INFO(SIGILL, "Priv Op/Disabled Extn", do_privilege_fault, ILL_PRVOPC)
71
DO_ERROR_INFO(SIGILL, "Invalid Extn Insn", do_extension_fault, ILL_ILLOPC)
72
DO_ERROR_INFO(SIGILL, "Illegal Insn (or Seq)", insterror_is_error, ILL_ILLOPC)
73
DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", __weak do_memory_error, BUS_ADRERR)
74
DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
75
DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN)
76
DO_ERROR_INFO(SIGSEGV, "gcc generated __builtin_trap", do_trap5_error, 0)
77
78
/*
79
* Entry Point for Misaligned Data access Exception, for emulating in software
80
*/
81
int do_misaligned_access(unsigned long address, struct pt_regs *regs,
82
struct callee_regs *cregs)
83
{
84
/* If emulation not enabled, or failed, kill the task */
85
if (misaligned_fixup(address, regs, cregs) != 0)
86
return do_misaligned_error(address, regs);
87
88
return 0;
89
}
90
91
/*
92
* Entry point for miscll errors such as Nested Exceptions
93
* -Duplicate TLB entry is handled separately though
94
*/
95
void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
96
{
97
die("Unhandled Machine Check Exception", regs, address);
98
}
99
100
101
/*
102
* Entry point for traps induced by ARCompact TRAP_S <n> insn
103
* This is same family as TRAP0/SWI insn (use the same vector).
104
* The only difference being SWI insn take no operand, while TRAP_S does
105
* which reflects in ECR Reg as 8 bit param.
106
* Thus TRAP_S <n> can be used for specific purpose
107
* -1 used for software breakpointing (gdb)
108
* -2 used by kprobes
109
* -5 __builtin_trap() generated by gcc (2018.03 onwards) for toggle such as
110
* -fno-isolate-erroneous-paths-dereference
111
*/
112
void do_non_swi_trap(unsigned long address, struct pt_regs *regs)
113
{
114
switch (regs->ecr.param) {
115
case 1:
116
trap_is_brkpt(address, regs);
117
break;
118
119
case 2:
120
trap_is_kprobe(address, regs);
121
break;
122
123
case 3:
124
case 4:
125
kgdb_trap(regs);
126
break;
127
128
case 5:
129
do_trap5_error(address, regs);
130
break;
131
default:
132
break;
133
}
134
}
135
136
/*
137
* Entry point for Instruction Error Exception
138
* -For a corner case, ARC kprobes implementation resorts to using
139
* this exception, hence the check
140
*/
141
void do_insterror_or_kprobe(unsigned long address, struct pt_regs *regs)
142
{
143
int rc;
144
145
/* Check if this exception is caused by kprobes */
146
rc = notify_die(DIE_IERR, "kprobe_ierr", regs, address, 0, SIGILL);
147
if (rc == NOTIFY_STOP)
148
return;
149
150
insterror_is_error(address, regs);
151
}
152
153
/*
154
* abort() call generated by older gcc for __builtin_trap()
155
*/
156
void abort(void)
157
{
158
__asm__ __volatile__("trap_s 5\n");
159
}
160
161