aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/traps.c
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2010-06-25 17:04:17 -0400
committerChris Metcalf <cmetcalf@tilera.com>2010-07-06 13:41:51 -0400
commit0707ad30d10110aebc01a5a64fb63f4b32d20b73 (patch)
tree64d8ba73e605ac26e56808d1d77701b3f83cf8b2 /arch/tile/kernel/traps.c
parentc78095bd8c77fca2619769ff8efb639fd100e373 (diff)
arch/tile: Miscellaneous cleanup changes.
This commit is primarily changes caused by reviewing "sparse" and "checkpatch" output on our sources, so is somewhat noisy, since things like "printk() -> pr_err()" (or whatever) throughout the codebase tend to get tedious to read. Rather than trying to tease apart precisely which things changed due to which type of code review, this commit includes various cleanups in the code: - sparse: Add declarations in headers for globals. - sparse: Fix __user annotations. - sparse: Using gfp_t consistently instead of int. - sparse: removing functions not actually used. - checkpatch: Clean up printk() warnings by using pr_info(), etc.; also avoid partial-line printks except in bootup code. - checkpatch: Use exposed structs rather than typedefs. - checkpatch: Change some C99 comments to C89 comments. In addition, a couple of minor other changes are rolled in to this commit: - Add support for a "raise" instruction to cause SIGFPE, etc., to be raised. - Remove some compat code that is unnecessary when we fully eliminate some of the deprecated syscalls from the generic syscall ABI. - Update the tile_defconfig to reflect current config contents. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com> Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/tile/kernel/traps.c')
-rw-r--r--arch/tile/kernel/traps.c130
1 files changed, 105 insertions, 25 deletions
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c
index 12cb10f38527..3870abbeeaa2 100644
--- a/arch/tile/kernel/traps.c
+++ b/arch/tile/kernel/traps.c
@@ -20,6 +20,9 @@
20#include <linux/uaccess.h> 20#include <linux/uaccess.h>
21#include <linux/ptrace.h> 21#include <linux/ptrace.h>
22#include <asm/opcode-tile.h> 22#include <asm/opcode-tile.h>
23#include <asm/opcode_constants.h>
24#include <asm/stack.h>
25#include <asm/traps.h>
23 26
24#include <arch/interrupts.h> 27#include <arch/interrupts.h>
25#include <arch/spr_def.h> 28#include <arch/spr_def.h>
@@ -42,7 +45,7 @@ static int __init setup_unaligned_fixup(char *str)
42 if (strict_strtol(str, 0, &val) != 0) 45 if (strict_strtol(str, 0, &val) != 0)
43 return 0; 46 return 0;
44 unaligned_fixup = val; 47 unaligned_fixup = val;
45 printk("Fixups for unaligned data accesses are %s\n", 48 pr_info("Fixups for unaligned data accesses are %s\n",
46 unaligned_fixup >= 0 ? 49 unaligned_fixup >= 0 ?
47 (unaligned_fixup ? "enabled" : "disabled") : 50 (unaligned_fixup ? "enabled" : "disabled") :
48 "completely disabled"); 51 "completely disabled");
@@ -56,7 +59,7 @@ static int dma_disabled;
56 59
57static int __init nodma(char *str) 60static int __init nodma(char *str)
58{ 61{
59 printk("User-space DMA is disabled\n"); 62 pr_info("User-space DMA is disabled\n");
60 dma_disabled = 1; 63 dma_disabled = 1;
61 return 1; 64 return 1;
62} 65}
@@ -97,20 +100,106 @@ static int retry_gpv(unsigned int gpv_reason)
97 100
98#endif /* CHIP_HAS_TILE_DMA() */ 101#endif /* CHIP_HAS_TILE_DMA() */
99 102
100/* Defined inside do_trap(), below. */
101#ifdef __tilegx__ 103#ifdef __tilegx__
102extern tilegx_bundle_bits bpt_code; 104#define bundle_bits tilegx_bundle_bits
103#else 105#else
104extern tile_bundle_bits bpt_code; 106#define bundle_bits tile_bundle_bits
105#endif 107#endif
106 108
109extern bundle_bits bpt_code;
110
111asm(".pushsection .rodata.bpt_code,\"a\";"
112 ".align 8;"
113 "bpt_code: bpt;"
114 ".size bpt_code,.-bpt_code;"
115 ".popsection");
116
117static int special_ill(bundle_bits bundle, int *sigp, int *codep)
118{
119 int sig, code, maxcode;
120
121 if (bundle == bpt_code) {
122 *sigp = SIGTRAP;
123 *codep = TRAP_BRKPT;
124 return 1;
125 }
126
127 /* If it's a "raise" bundle, then "ill" must be in pipe X1. */
128#ifdef __tilegx__
129 if ((bundle & TILEGX_BUNDLE_MODE_MASK) != 0)
130 return 0;
131 if (get_Opcode_X1(bundle) != UNARY_OPCODE_X1)
132 return 0;
133 if (get_UnaryOpcodeExtension_X1(bundle) != ILL_UNARY_OPCODE_X1)
134 return 0;
135#else
136 if (bundle & TILE_BUNDLE_Y_ENCODING_MASK)
137 return 0;
138 if (get_Opcode_X1(bundle) != SHUN_0_OPCODE_X1)
139 return 0;
140 if (get_UnShOpcodeExtension_X1(bundle) != UN_0_SHUN_0_OPCODE_X1)
141 return 0;
142 if (get_UnOpcodeExtension_X1(bundle) != ILL_UN_0_SHUN_0_OPCODE_X1)
143 return 0;
144#endif
145
146 /* Check that the magic distinguishers are set to mean "raise". */
147 if (get_Dest_X1(bundle) != 29 || get_SrcA_X1(bundle) != 37)
148 return 0;
149
150 /* There must be an "addli zero, zero, VAL" in X0. */
151 if (get_Opcode_X0(bundle) != ADDLI_OPCODE_X0)
152 return 0;
153 if (get_Dest_X0(bundle) != TREG_ZERO)
154 return 0;
155 if (get_SrcA_X0(bundle) != TREG_ZERO)
156 return 0;
157
158 /*
159 * Validate the proposed signal number and si_code value.
160 * Note that we embed these in the static instruction itself
161 * so that we perturb the register state as little as possible
162 * at the time of the actual fault; it's unlikely you'd ever
163 * need to dynamically choose which kind of fault to raise
164 * from user space.
165 */
166 sig = get_Imm16_X0(bundle) & 0x3f;
167 switch (sig) {
168 case SIGILL:
169 maxcode = NSIGILL;
170 break;
171 case SIGFPE:
172 maxcode = NSIGFPE;
173 break;
174 case SIGSEGV:
175 maxcode = NSIGSEGV;
176 break;
177 case SIGBUS:
178 maxcode = NSIGBUS;
179 break;
180 case SIGTRAP:
181 maxcode = NSIGTRAP;
182 break;
183 default:
184 return 0;
185 }
186 code = (get_Imm16_X0(bundle) >> 6) & 0xf;
187 if (code <= 0 || code > maxcode)
188 return 0;
189
190 /* Make it the requested signal. */
191 *sigp = sig;
192 *codep = code | __SI_FAULT;
193 return 1;
194}
195
107void __kprobes do_trap(struct pt_regs *regs, int fault_num, 196void __kprobes do_trap(struct pt_regs *regs, int fault_num,
108 unsigned long reason) 197 unsigned long reason)
109{ 198{
110 siginfo_t info = { 0 }; 199 siginfo_t info = { 0 };
111 int signo, code; 200 int signo, code;
112 unsigned long address; 201 unsigned long address;
113 __typeof__(bpt_code) instr; 202 bundle_bits instr;
114 203
115 /* Re-enable interrupts. */ 204 /* Re-enable interrupts. */
116 local_irq_enable(); 205 local_irq_enable();
@@ -122,10 +211,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
122 if (!user_mode(regs)) { 211 if (!user_mode(regs)) {
123 if (fixup_exception(regs)) /* only UNALIGN_DATA in practice */ 212 if (fixup_exception(regs)) /* only UNALIGN_DATA in practice */
124 return; 213 return;
125 printk(KERN_ALERT "Kernel took bad trap %d at PC %#lx\n", 214 pr_alert("Kernel took bad trap %d at PC %#lx\n",
126 fault_num, regs->pc); 215 fault_num, regs->pc);
127 if (fault_num == INT_GPV) 216 if (fault_num == INT_GPV)
128 printk(KERN_ALERT "GPV_REASON is %#lx\n", reason); 217 pr_alert("GPV_REASON is %#lx\n", reason);
129 show_regs(regs); 218 show_regs(regs);
130 do_exit(SIGKILL); /* FIXME: implement i386 die() */ 219 do_exit(SIGKILL); /* FIXME: implement i386 die() */
131 return; 220 return;
@@ -133,22 +222,14 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
133 222
134 switch (fault_num) { 223 switch (fault_num) {
135 case INT_ILL: 224 case INT_ILL:
136 asm(".pushsection .rodata.bpt_code,\"a\";" 225 if (copy_from_user(&instr, (void __user *)regs->pc,
137 ".align 8;" 226 sizeof(instr))) {
138 "bpt_code: bpt;" 227 pr_err("Unreadable instruction for INT_ILL:"
139 ".size bpt_code,.-bpt_code;"
140 ".popsection");
141
142 if (copy_from_user(&instr, (void *)regs->pc, sizeof(instr))) {
143 printk(KERN_ERR "Unreadable instruction for INT_ILL:"
144 " %#lx\n", regs->pc); 228 " %#lx\n", regs->pc);
145 do_exit(SIGKILL); 229 do_exit(SIGKILL);
146 return; 230 return;
147 } 231 }
148 if (instr == bpt_code) { 232 if (!special_ill(instr, &signo, &code)) {
149 signo = SIGTRAP;
150 code = TRAP_BRKPT;
151 } else {
152 signo = SIGILL; 233 signo = SIGILL;
153 code = ILL_ILLOPC; 234 code = ILL_ILLOPC;
154 } 235 }
@@ -181,7 +262,8 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
181 if (unaligned_fixup >= 0) { 262 if (unaligned_fixup >= 0) {
182 struct single_step_state *state = 263 struct single_step_state *state =
183 current_thread_info()->step_state; 264 current_thread_info()->step_state;
184 if (!state || (void *)(regs->pc) != state->buffer) { 265 if (!state ||
266 (void __user *)(regs->pc) != state->buffer) {
185 single_step_once(regs); 267 single_step_once(regs);
186 return; 268 return;
187 } 269 }
@@ -221,17 +303,15 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
221 303
222 info.si_signo = signo; 304 info.si_signo = signo;
223 info.si_code = code; 305 info.si_code = code;
224 info.si_addr = (void *)address; 306 info.si_addr = (void __user *)address;
225 if (signo == SIGILL) 307 if (signo == SIGILL)
226 info.si_trapno = fault_num; 308 info.si_trapno = fault_num;
227 force_sig_info(signo, &info, current); 309 force_sig_info(signo, &info, current);
228} 310}
229 311
230extern void _dump_stack(int dummy, ulong pc, ulong lr, ulong sp, ulong r52);
231
232void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52) 312void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52)
233{ 313{
234 _dump_stack(dummy, pc, lr, sp, r52); 314 _dump_stack(dummy, pc, lr, sp, r52);
235 printk("Double fault: exiting\n"); 315 pr_emerg("Double fault: exiting\n");
236 machine_halt(); 316 machine_halt();
237} 317}