diff options
Diffstat (limited to 'arch/x86/kernel/traps_32.c')
-rw-r--r-- | arch/x86/kernel/traps_32.c | 341 |
1 files changed, 174 insertions, 167 deletions
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 02d1e1e58e81..3cf72977d012 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c | |||
@@ -76,7 +76,8 @@ char ignore_fpu_irq = 0; | |||
76 | * F0 0F bug workaround.. We have a special link segment | 76 | * F0 0F bug workaround.. We have a special link segment |
77 | * for this. | 77 | * for this. |
78 | */ | 78 | */ |
79 | struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, }; | 79 | gate_desc idt_table[256] |
80 | __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, }; | ||
80 | 81 | ||
81 | asmlinkage void divide_error(void); | 82 | asmlinkage void divide_error(void); |
82 | asmlinkage void debug(void); | 83 | asmlinkage void debug(void); |
@@ -101,6 +102,34 @@ asmlinkage void machine_check(void); | |||
101 | int kstack_depth_to_print = 24; | 102 | int kstack_depth_to_print = 24; |
102 | static unsigned int code_bytes = 64; | 103 | static unsigned int code_bytes = 64; |
103 | 104 | ||
105 | void printk_address(unsigned long address, int reliable) | ||
106 | { | ||
107 | #ifdef CONFIG_KALLSYMS | ||
108 | unsigned long offset = 0, symsize; | ||
109 | const char *symname; | ||
110 | char *modname; | ||
111 | char *delim = ":"; | ||
112 | char namebuf[128]; | ||
113 | char reliab[4] = ""; | ||
114 | |||
115 | symname = kallsyms_lookup(address, &symsize, &offset, | ||
116 | &modname, namebuf); | ||
117 | if (!symname) { | ||
118 | printk(" [<%08lx>]\n", address); | ||
119 | return; | ||
120 | } | ||
121 | if (!reliable) | ||
122 | strcpy(reliab, "? "); | ||
123 | |||
124 | if (!modname) | ||
125 | modname = delim = ""; | ||
126 | printk(" [<%08lx>] %s%s%s%s%s+0x%lx/0x%lx\n", | ||
127 | address, reliab, delim, modname, delim, symname, offset, symsize); | ||
128 | #else | ||
129 | printk(" [<%08lx>]\n", address); | ||
130 | #endif | ||
131 | } | ||
132 | |||
104 | static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size) | 133 | static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size) |
105 | { | 134 | { |
106 | return p > (void *)tinfo && | 135 | return p > (void *)tinfo && |
@@ -114,48 +143,35 @@ struct stack_frame { | |||
114 | }; | 143 | }; |
115 | 144 | ||
116 | static inline unsigned long print_context_stack(struct thread_info *tinfo, | 145 | static inline unsigned long print_context_stack(struct thread_info *tinfo, |
117 | unsigned long *stack, unsigned long ebp, | 146 | unsigned long *stack, unsigned long bp, |
118 | const struct stacktrace_ops *ops, void *data) | 147 | const struct stacktrace_ops *ops, void *data) |
119 | { | 148 | { |
120 | #ifdef CONFIG_FRAME_POINTER | 149 | struct stack_frame *frame = (struct stack_frame *)bp; |
121 | struct stack_frame *frame = (struct stack_frame *)ebp; | ||
122 | while (valid_stack_ptr(tinfo, frame, sizeof(*frame))) { | ||
123 | struct stack_frame *next; | ||
124 | unsigned long addr; | ||
125 | 150 | ||
126 | addr = frame->return_address; | ||
127 | ops->address(data, addr); | ||
128 | /* | ||
129 | * break out of recursive entries (such as | ||
130 | * end_of_stack_stop_unwind_function). Also, | ||
131 | * we can never allow a frame pointer to | ||
132 | * move downwards! | ||
133 | */ | ||
134 | next = frame->next_frame; | ||
135 | if (next <= frame) | ||
136 | break; | ||
137 | frame = next; | ||
138 | } | ||
139 | #else | ||
140 | while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { | 151 | while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { |
141 | unsigned long addr; | 152 | unsigned long addr; |
142 | 153 | ||
143 | addr = *stack++; | 154 | addr = *stack; |
144 | if (__kernel_text_address(addr)) | 155 | if (__kernel_text_address(addr)) { |
145 | ops->address(data, addr); | 156 | if ((unsigned long) stack == bp + 4) { |
157 | ops->address(data, addr, 1); | ||
158 | frame = frame->next_frame; | ||
159 | bp = (unsigned long) frame; | ||
160 | } else { | ||
161 | ops->address(data, addr, bp == 0); | ||
162 | } | ||
163 | } | ||
164 | stack++; | ||
146 | } | 165 | } |
147 | #endif | 166 | return bp; |
148 | return ebp; | ||
149 | } | 167 | } |
150 | 168 | ||
151 | #define MSG(msg) ops->warning(data, msg) | 169 | #define MSG(msg) ops->warning(data, msg) |
152 | 170 | ||
153 | void dump_trace(struct task_struct *task, struct pt_regs *regs, | 171 | void dump_trace(struct task_struct *task, struct pt_regs *regs, |
154 | unsigned long *stack, | 172 | unsigned long *stack, unsigned long bp, |
155 | const struct stacktrace_ops *ops, void *data) | 173 | const struct stacktrace_ops *ops, void *data) |
156 | { | 174 | { |
157 | unsigned long ebp = 0; | ||
158 | |||
159 | if (!task) | 175 | if (!task) |
160 | task = current; | 176 | task = current; |
161 | 177 | ||
@@ -163,17 +179,17 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, | |||
163 | unsigned long dummy; | 179 | unsigned long dummy; |
164 | stack = &dummy; | 180 | stack = &dummy; |
165 | if (task != current) | 181 | if (task != current) |
166 | stack = (unsigned long *)task->thread.esp; | 182 | stack = (unsigned long *)task->thread.sp; |
167 | } | 183 | } |
168 | 184 | ||
169 | #ifdef CONFIG_FRAME_POINTER | 185 | #ifdef CONFIG_FRAME_POINTER |
170 | if (!ebp) { | 186 | if (!bp) { |
171 | if (task == current) { | 187 | if (task == current) { |
172 | /* Grab ebp right from our regs */ | 188 | /* Grab bp right from our regs */ |
173 | asm ("movl %%ebp, %0" : "=r" (ebp) : ); | 189 | asm ("movl %%ebp, %0" : "=r" (bp) : ); |
174 | } else { | 190 | } else { |
175 | /* ebp is the last reg pushed by switch_to */ | 191 | /* bp is the last reg pushed by switch_to */ |
176 | ebp = *(unsigned long *) task->thread.esp; | 192 | bp = *(unsigned long *) task->thread.sp; |
177 | } | 193 | } |
178 | } | 194 | } |
179 | #endif | 195 | #endif |
@@ -182,7 +198,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, | |||
182 | struct thread_info *context; | 198 | struct thread_info *context; |
183 | context = (struct thread_info *) | 199 | context = (struct thread_info *) |
184 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); | 200 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); |
185 | ebp = print_context_stack(context, stack, ebp, ops, data); | 201 | bp = print_context_stack(context, stack, bp, ops, data); |
186 | /* Should be after the line below, but somewhere | 202 | /* Should be after the line below, but somewhere |
187 | in early boot context comes out corrupted and we | 203 | in early boot context comes out corrupted and we |
188 | can't reference it -AK */ | 204 | can't reference it -AK */ |
@@ -217,9 +233,11 @@ static int print_trace_stack(void *data, char *name) | |||
217 | /* | 233 | /* |
218 | * Print one address/symbol entries per line. | 234 | * Print one address/symbol entries per line. |
219 | */ | 235 | */ |
220 | static void print_trace_address(void *data, unsigned long addr) | 236 | static void print_trace_address(void *data, unsigned long addr, int reliable) |
221 | { | 237 | { |
222 | printk("%s [<%08lx>] ", (char *)data, addr); | 238 | printk("%s [<%08lx>] ", (char *)data, addr); |
239 | if (!reliable) | ||
240 | printk("? "); | ||
223 | print_symbol("%s\n", addr); | 241 | print_symbol("%s\n", addr); |
224 | touch_nmi_watchdog(); | 242 | touch_nmi_watchdog(); |
225 | } | 243 | } |
@@ -233,32 +251,32 @@ static const struct stacktrace_ops print_trace_ops = { | |||
233 | 251 | ||
234 | static void | 252 | static void |
235 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | 253 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, |
236 | unsigned long * stack, char *log_lvl) | 254 | unsigned long *stack, unsigned long bp, char *log_lvl) |
237 | { | 255 | { |
238 | dump_trace(task, regs, stack, &print_trace_ops, log_lvl); | 256 | dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); |
239 | printk("%s =======================\n", log_lvl); | 257 | printk("%s =======================\n", log_lvl); |
240 | } | 258 | } |
241 | 259 | ||
242 | void show_trace(struct task_struct *task, struct pt_regs *regs, | 260 | void show_trace(struct task_struct *task, struct pt_regs *regs, |
243 | unsigned long * stack) | 261 | unsigned long *stack, unsigned long bp) |
244 | { | 262 | { |
245 | show_trace_log_lvl(task, regs, stack, ""); | 263 | show_trace_log_lvl(task, regs, stack, bp, ""); |
246 | } | 264 | } |
247 | 265 | ||
248 | static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | 266 | static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, |
249 | unsigned long *esp, char *log_lvl) | 267 | unsigned long *sp, unsigned long bp, char *log_lvl) |
250 | { | 268 | { |
251 | unsigned long *stack; | 269 | unsigned long *stack; |
252 | int i; | 270 | int i; |
253 | 271 | ||
254 | if (esp == NULL) { | 272 | if (sp == NULL) { |
255 | if (task) | 273 | if (task) |
256 | esp = (unsigned long*)task->thread.esp; | 274 | sp = (unsigned long*)task->thread.sp; |
257 | else | 275 | else |
258 | esp = (unsigned long *)&esp; | 276 | sp = (unsigned long *)&sp; |
259 | } | 277 | } |
260 | 278 | ||
261 | stack = esp; | 279 | stack = sp; |
262 | for(i = 0; i < kstack_depth_to_print; i++) { | 280 | for(i = 0; i < kstack_depth_to_print; i++) { |
263 | if (kstack_end(stack)) | 281 | if (kstack_end(stack)) |
264 | break; | 282 | break; |
@@ -267,13 +285,13 @@ static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | |||
267 | printk("%08lx ", *stack++); | 285 | printk("%08lx ", *stack++); |
268 | } | 286 | } |
269 | printk("\n%sCall Trace:\n", log_lvl); | 287 | printk("\n%sCall Trace:\n", log_lvl); |
270 | show_trace_log_lvl(task, regs, esp, log_lvl); | 288 | show_trace_log_lvl(task, regs, sp, bp, log_lvl); |
271 | } | 289 | } |
272 | 290 | ||
273 | void show_stack(struct task_struct *task, unsigned long *esp) | 291 | void show_stack(struct task_struct *task, unsigned long *sp) |
274 | { | 292 | { |
275 | printk(" "); | 293 | printk(" "); |
276 | show_stack_log_lvl(task, NULL, esp, ""); | 294 | show_stack_log_lvl(task, NULL, sp, 0, ""); |
277 | } | 295 | } |
278 | 296 | ||
279 | /* | 297 | /* |
@@ -282,13 +300,19 @@ void show_stack(struct task_struct *task, unsigned long *esp) | |||
282 | void dump_stack(void) | 300 | void dump_stack(void) |
283 | { | 301 | { |
284 | unsigned long stack; | 302 | unsigned long stack; |
303 | unsigned long bp = 0; | ||
304 | |||
305 | #ifdef CONFIG_FRAME_POINTER | ||
306 | if (!bp) | ||
307 | asm("movl %%ebp, %0" : "=r" (bp):); | ||
308 | #endif | ||
285 | 309 | ||
286 | printk("Pid: %d, comm: %.20s %s %s %.*s\n", | 310 | printk("Pid: %d, comm: %.20s %s %s %.*s\n", |
287 | current->pid, current->comm, print_tainted(), | 311 | current->pid, current->comm, print_tainted(), |
288 | init_utsname()->release, | 312 | init_utsname()->release, |
289 | (int)strcspn(init_utsname()->version, " "), | 313 | (int)strcspn(init_utsname()->version, " "), |
290 | init_utsname()->version); | 314 | init_utsname()->version); |
291 | show_trace(current, NULL, &stack); | 315 | show_trace(current, NULL, &stack, bp); |
292 | } | 316 | } |
293 | 317 | ||
294 | EXPORT_SYMBOL(dump_stack); | 318 | EXPORT_SYMBOL(dump_stack); |
@@ -307,30 +331,30 @@ void show_registers(struct pt_regs *regs) | |||
307 | * time of the fault.. | 331 | * time of the fault.. |
308 | */ | 332 | */ |
309 | if (!user_mode_vm(regs)) { | 333 | if (!user_mode_vm(regs)) { |
310 | u8 *eip; | 334 | u8 *ip; |
311 | unsigned int code_prologue = code_bytes * 43 / 64; | 335 | unsigned int code_prologue = code_bytes * 43 / 64; |
312 | unsigned int code_len = code_bytes; | 336 | unsigned int code_len = code_bytes; |
313 | unsigned char c; | 337 | unsigned char c; |
314 | 338 | ||
315 | printk("\n" KERN_EMERG "Stack: "); | 339 | printk("\n" KERN_EMERG "Stack: "); |
316 | show_stack_log_lvl(NULL, regs, ®s->esp, KERN_EMERG); | 340 | show_stack_log_lvl(NULL, regs, ®s->sp, 0, KERN_EMERG); |
317 | 341 | ||
318 | printk(KERN_EMERG "Code: "); | 342 | printk(KERN_EMERG "Code: "); |
319 | 343 | ||
320 | eip = (u8 *)regs->eip - code_prologue; | 344 | ip = (u8 *)regs->ip - code_prologue; |
321 | if (eip < (u8 *)PAGE_OFFSET || | 345 | if (ip < (u8 *)PAGE_OFFSET || |
322 | probe_kernel_address(eip, c)) { | 346 | probe_kernel_address(ip, c)) { |
323 | /* try starting at EIP */ | 347 | /* try starting at EIP */ |
324 | eip = (u8 *)regs->eip; | 348 | ip = (u8 *)regs->ip; |
325 | code_len = code_len - code_prologue + 1; | 349 | code_len = code_len - code_prologue + 1; |
326 | } | 350 | } |
327 | for (i = 0; i < code_len; i++, eip++) { | 351 | for (i = 0; i < code_len; i++, ip++) { |
328 | if (eip < (u8 *)PAGE_OFFSET || | 352 | if (ip < (u8 *)PAGE_OFFSET || |
329 | probe_kernel_address(eip, c)) { | 353 | probe_kernel_address(ip, c)) { |
330 | printk(" Bad EIP value."); | 354 | printk(" Bad EIP value."); |
331 | break; | 355 | break; |
332 | } | 356 | } |
333 | if (eip == (u8 *)regs->eip) | 357 | if (ip == (u8 *)regs->ip) |
334 | printk("<%02x> ", c); | 358 | printk("<%02x> ", c); |
335 | else | 359 | else |
336 | printk("%02x ", c); | 360 | printk("%02x ", c); |
@@ -339,18 +363,57 @@ void show_registers(struct pt_regs *regs) | |||
339 | printk("\n"); | 363 | printk("\n"); |
340 | } | 364 | } |
341 | 365 | ||
342 | int is_valid_bugaddr(unsigned long eip) | 366 | int is_valid_bugaddr(unsigned long ip) |
343 | { | 367 | { |
344 | unsigned short ud2; | 368 | unsigned short ud2; |
345 | 369 | ||
346 | if (eip < PAGE_OFFSET) | 370 | if (ip < PAGE_OFFSET) |
347 | return 0; | 371 | return 0; |
348 | if (probe_kernel_address((unsigned short *)eip, ud2)) | 372 | if (probe_kernel_address((unsigned short *)ip, ud2)) |
349 | return 0; | 373 | return 0; |
350 | 374 | ||
351 | return ud2 == 0x0b0f; | 375 | return ud2 == 0x0b0f; |
352 | } | 376 | } |
353 | 377 | ||
378 | static int die_counter; | ||
379 | |||
380 | int __kprobes __die(const char * str, struct pt_regs * regs, long err) | ||
381 | { | ||
382 | unsigned long sp; | ||
383 | unsigned short ss; | ||
384 | |||
385 | printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); | ||
386 | #ifdef CONFIG_PREEMPT | ||
387 | printk("PREEMPT "); | ||
388 | #endif | ||
389 | #ifdef CONFIG_SMP | ||
390 | printk("SMP "); | ||
391 | #endif | ||
392 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
393 | printk("DEBUG_PAGEALLOC"); | ||
394 | #endif | ||
395 | printk("\n"); | ||
396 | |||
397 | if (notify_die(DIE_OOPS, str, regs, err, | ||
398 | current->thread.trap_no, SIGSEGV) != | ||
399 | NOTIFY_STOP) { | ||
400 | show_registers(regs); | ||
401 | /* Executive summary in case the oops scrolled away */ | ||
402 | sp = (unsigned long) (®s->sp); | ||
403 | savesegment(ss, ss); | ||
404 | if (user_mode(regs)) { | ||
405 | sp = regs->sp; | ||
406 | ss = regs->ss & 0xffff; | ||
407 | } | ||
408 | printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip); | ||
409 | print_symbol("%s", regs->ip); | ||
410 | printk(" SS:ESP %04x:%08lx\n", ss, sp); | ||
411 | return 0; | ||
412 | } else { | ||
413 | return 1; | ||
414 | } | ||
415 | } | ||
416 | |||
354 | /* | 417 | /* |
355 | * This is gone through when something in the kernel has done something bad and | 418 | * This is gone through when something in the kernel has done something bad and |
356 | * is about to be terminated. | 419 | * is about to be terminated. |
@@ -366,7 +429,6 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
366 | .lock_owner = -1, | 429 | .lock_owner = -1, |
367 | .lock_owner_depth = 0 | 430 | .lock_owner_depth = 0 |
368 | }; | 431 | }; |
369 | static int die_counter; | ||
370 | unsigned long flags; | 432 | unsigned long flags; |
371 | 433 | ||
372 | oops_enter(); | 434 | oops_enter(); |
@@ -382,43 +444,13 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
382 | raw_local_irq_save(flags); | 444 | raw_local_irq_save(flags); |
383 | 445 | ||
384 | if (++die.lock_owner_depth < 3) { | 446 | if (++die.lock_owner_depth < 3) { |
385 | unsigned long esp; | 447 | report_bug(regs->ip, regs); |
386 | unsigned short ss; | ||
387 | 448 | ||
388 | report_bug(regs->eip, regs); | 449 | if (__die(str, regs, err)) |
389 | |||
390 | printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, | ||
391 | ++die_counter); | ||
392 | #ifdef CONFIG_PREEMPT | ||
393 | printk("PREEMPT "); | ||
394 | #endif | ||
395 | #ifdef CONFIG_SMP | ||
396 | printk("SMP "); | ||
397 | #endif | ||
398 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
399 | printk("DEBUG_PAGEALLOC"); | ||
400 | #endif | ||
401 | printk("\n"); | ||
402 | |||
403 | if (notify_die(DIE_OOPS, str, regs, err, | ||
404 | current->thread.trap_no, SIGSEGV) != | ||
405 | NOTIFY_STOP) { | ||
406 | show_registers(regs); | ||
407 | /* Executive summary in case the oops scrolled away */ | ||
408 | esp = (unsigned long) (®s->esp); | ||
409 | savesegment(ss, ss); | ||
410 | if (user_mode(regs)) { | ||
411 | esp = regs->esp; | ||
412 | ss = regs->xss & 0xffff; | ||
413 | } | ||
414 | printk(KERN_EMERG "EIP: [<%08lx>] ", regs->eip); | ||
415 | print_symbol("%s", regs->eip); | ||
416 | printk(" SS:ESP %04x:%08lx\n", ss, esp); | ||
417 | } | ||
418 | else | ||
419 | regs = NULL; | 450 | regs = NULL; |
420 | } else | 451 | } else { |
421 | printk(KERN_EMERG "Recursive die() failure, output suppressed\n"); | 452 | printk(KERN_EMERG "Recursive die() failure, output suppressed\n"); |
453 | } | ||
422 | 454 | ||
423 | bust_spinlocks(0); | 455 | bust_spinlocks(0); |
424 | die.lock_owner = -1; | 456 | die.lock_owner = -1; |
@@ -454,7 +486,7 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86, | |||
454 | { | 486 | { |
455 | struct task_struct *tsk = current; | 487 | struct task_struct *tsk = current; |
456 | 488 | ||
457 | if (regs->eflags & VM_MASK) { | 489 | if (regs->flags & VM_MASK) { |
458 | if (vm86) | 490 | if (vm86) |
459 | goto vm86_trap; | 491 | goto vm86_trap; |
460 | goto trap_signal; | 492 | goto trap_signal; |
@@ -500,7 +532,7 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86, | |||
500 | } | 532 | } |
501 | 533 | ||
502 | #define DO_ERROR(trapnr, signr, str, name) \ | 534 | #define DO_ERROR(trapnr, signr, str, name) \ |
503 | fastcall void do_##name(struct pt_regs * regs, long error_code) \ | 535 | void do_##name(struct pt_regs * regs, long error_code) \ |
504 | { \ | 536 | { \ |
505 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 537 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ |
506 | == NOTIFY_STOP) \ | 538 | == NOTIFY_STOP) \ |
@@ -509,7 +541,7 @@ fastcall void do_##name(struct pt_regs * regs, long error_code) \ | |||
509 | } | 541 | } |
510 | 542 | ||
511 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \ | 543 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \ |
512 | fastcall void do_##name(struct pt_regs * regs, long error_code) \ | 544 | void do_##name(struct pt_regs * regs, long error_code) \ |
513 | { \ | 545 | { \ |
514 | siginfo_t info; \ | 546 | siginfo_t info; \ |
515 | if (irq) \ | 547 | if (irq) \ |
@@ -525,7 +557,7 @@ fastcall void do_##name(struct pt_regs * regs, long error_code) \ | |||
525 | } | 557 | } |
526 | 558 | ||
527 | #define DO_VM86_ERROR(trapnr, signr, str, name) \ | 559 | #define DO_VM86_ERROR(trapnr, signr, str, name) \ |
528 | fastcall void do_##name(struct pt_regs * regs, long error_code) \ | 560 | void do_##name(struct pt_regs * regs, long error_code) \ |
529 | { \ | 561 | { \ |
530 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 562 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ |
531 | == NOTIFY_STOP) \ | 563 | == NOTIFY_STOP) \ |
@@ -534,7 +566,7 @@ fastcall void do_##name(struct pt_regs * regs, long error_code) \ | |||
534 | } | 566 | } |
535 | 567 | ||
536 | #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ | 568 | #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ |
537 | fastcall void do_##name(struct pt_regs * regs, long error_code) \ | 569 | void do_##name(struct pt_regs * regs, long error_code) \ |
538 | { \ | 570 | { \ |
539 | siginfo_t info; \ | 571 | siginfo_t info; \ |
540 | info.si_signo = signr; \ | 572 | info.si_signo = signr; \ |
@@ -548,13 +580,13 @@ fastcall void do_##name(struct pt_regs * regs, long error_code) \ | |||
548 | do_trap(trapnr, signr, str, 1, regs, error_code, &info); \ | 580 | do_trap(trapnr, signr, str, 1, regs, error_code, &info); \ |
549 | } | 581 | } |
550 | 582 | ||
551 | DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip) | 583 | DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip) |
552 | #ifndef CONFIG_KPROBES | 584 | #ifndef CONFIG_KPROBES |
553 | DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) | 585 | DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) |
554 | #endif | 586 | #endif |
555 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) | 587 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) |
556 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) | 588 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) |
557 | DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip, 0) | 589 | DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0) |
558 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) | 590 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) |
559 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) | 591 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) |
560 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) | 592 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) |
@@ -562,7 +594,7 @@ DO_ERROR(12, SIGBUS, "stack segment", stack_segment) | |||
562 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0) | 594 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0) |
563 | DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1) | 595 | DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1) |
564 | 596 | ||
565 | fastcall void __kprobes do_general_protection(struct pt_regs * regs, | 597 | void __kprobes do_general_protection(struct pt_regs * regs, |
566 | long error_code) | 598 | long error_code) |
567 | { | 599 | { |
568 | int cpu = get_cpu(); | 600 | int cpu = get_cpu(); |
@@ -596,7 +628,7 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs, | |||
596 | } | 628 | } |
597 | put_cpu(); | 629 | put_cpu(); |
598 | 630 | ||
599 | if (regs->eflags & VM_MASK) | 631 | if (regs->flags & VM_MASK) |
600 | goto gp_in_vm86; | 632 | goto gp_in_vm86; |
601 | 633 | ||
602 | if (!user_mode(regs)) | 634 | if (!user_mode(regs)) |
@@ -605,11 +637,14 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs, | |||
605 | current->thread.error_code = error_code; | 637 | current->thread.error_code = error_code; |
606 | current->thread.trap_no = 13; | 638 | current->thread.trap_no = 13; |
607 | if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) && | 639 | if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) && |
608 | printk_ratelimit()) | 640 | printk_ratelimit()) { |
609 | printk(KERN_INFO | 641 | printk(KERN_INFO |
610 | "%s[%d] general protection eip:%lx esp:%lx error:%lx\n", | 642 | "%s[%d] general protection ip:%lx sp:%lx error:%lx", |
611 | current->comm, task_pid_nr(current), | 643 | current->comm, task_pid_nr(current), |
612 | regs->eip, regs->esp, error_code); | 644 | regs->ip, regs->sp, error_code); |
645 | print_vma_addr(" in ", regs->ip); | ||
646 | printk("\n"); | ||
647 | } | ||
613 | 648 | ||
614 | force_sig(SIGSEGV, current); | 649 | force_sig(SIGSEGV, current); |
615 | return; | 650 | return; |
@@ -705,8 +740,8 @@ void __kprobes die_nmi(struct pt_regs *regs, const char *msg) | |||
705 | */ | 740 | */ |
706 | bust_spinlocks(1); | 741 | bust_spinlocks(1); |
707 | printk(KERN_EMERG "%s", msg); | 742 | printk(KERN_EMERG "%s", msg); |
708 | printk(" on CPU%d, eip %08lx, registers:\n", | 743 | printk(" on CPU%d, ip %08lx, registers:\n", |
709 | smp_processor_id(), regs->eip); | 744 | smp_processor_id(), regs->ip); |
710 | show_registers(regs); | 745 | show_registers(regs); |
711 | console_silent(); | 746 | console_silent(); |
712 | spin_unlock(&nmi_print_lock); | 747 | spin_unlock(&nmi_print_lock); |
@@ -763,7 +798,7 @@ static __kprobes void default_do_nmi(struct pt_regs * regs) | |||
763 | 798 | ||
764 | static int ignore_nmis; | 799 | static int ignore_nmis; |
765 | 800 | ||
766 | fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) | 801 | __kprobes void do_nmi(struct pt_regs * regs, long error_code) |
767 | { | 802 | { |
768 | int cpu; | 803 | int cpu; |
769 | 804 | ||
@@ -792,7 +827,7 @@ void restart_nmi(void) | |||
792 | } | 827 | } |
793 | 828 | ||
794 | #ifdef CONFIG_KPROBES | 829 | #ifdef CONFIG_KPROBES |
795 | fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) | 830 | void __kprobes do_int3(struct pt_regs *regs, long error_code) |
796 | { | 831 | { |
797 | trace_hardirqs_fixup(); | 832 | trace_hardirqs_fixup(); |
798 | 833 | ||
@@ -828,7 +863,7 @@ fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) | |||
828 | * find every occurrence of the TF bit that could be saved away even | 863 | * find every occurrence of the TF bit that could be saved away even |
829 | * by user code) | 864 | * by user code) |
830 | */ | 865 | */ |
831 | fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code) | 866 | void __kprobes do_debug(struct pt_regs * regs, long error_code) |
832 | { | 867 | { |
833 | unsigned int condition; | 868 | unsigned int condition; |
834 | struct task_struct *tsk = current; | 869 | struct task_struct *tsk = current; |
@@ -837,24 +872,30 @@ fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code) | |||
837 | 872 | ||
838 | get_debugreg(condition, 6); | 873 | get_debugreg(condition, 6); |
839 | 874 | ||
875 | /* | ||
876 | * The processor cleared BTF, so don't mark that we need it set. | ||
877 | */ | ||
878 | clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR); | ||
879 | tsk->thread.debugctlmsr = 0; | ||
880 | |||
840 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, | 881 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, |
841 | SIGTRAP) == NOTIFY_STOP) | 882 | SIGTRAP) == NOTIFY_STOP) |
842 | return; | 883 | return; |
843 | /* It's safe to allow irq's after DR6 has been saved */ | 884 | /* It's safe to allow irq's after DR6 has been saved */ |
844 | if (regs->eflags & X86_EFLAGS_IF) | 885 | if (regs->flags & X86_EFLAGS_IF) |
845 | local_irq_enable(); | 886 | local_irq_enable(); |
846 | 887 | ||
847 | /* Mask out spurious debug traps due to lazy DR7 setting */ | 888 | /* Mask out spurious debug traps due to lazy DR7 setting */ |
848 | if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { | 889 | if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { |
849 | if (!tsk->thread.debugreg[7]) | 890 | if (!tsk->thread.debugreg7) |
850 | goto clear_dr7; | 891 | goto clear_dr7; |
851 | } | 892 | } |
852 | 893 | ||
853 | if (regs->eflags & VM_MASK) | 894 | if (regs->flags & VM_MASK) |
854 | goto debug_vm86; | 895 | goto debug_vm86; |
855 | 896 | ||
856 | /* Save debug status register where ptrace can see it */ | 897 | /* Save debug status register where ptrace can see it */ |
857 | tsk->thread.debugreg[6] = condition; | 898 | tsk->thread.debugreg6 = condition; |
858 | 899 | ||
859 | /* | 900 | /* |
860 | * Single-stepping through TF: make sure we ignore any events in | 901 | * Single-stepping through TF: make sure we ignore any events in |
@@ -886,7 +927,7 @@ debug_vm86: | |||
886 | 927 | ||
887 | clear_TF_reenable: | 928 | clear_TF_reenable: |
888 | set_tsk_thread_flag(tsk, TIF_SINGLESTEP); | 929 | set_tsk_thread_flag(tsk, TIF_SINGLESTEP); |
889 | regs->eflags &= ~TF_MASK; | 930 | regs->flags &= ~TF_MASK; |
890 | return; | 931 | return; |
891 | } | 932 | } |
892 | 933 | ||
@@ -895,7 +936,7 @@ clear_TF_reenable: | |||
895 | * the correct behaviour even in the presence of the asynchronous | 936 | * the correct behaviour even in the presence of the asynchronous |
896 | * IRQ13 behaviour | 937 | * IRQ13 behaviour |
897 | */ | 938 | */ |
898 | void math_error(void __user *eip) | 939 | void math_error(void __user *ip) |
899 | { | 940 | { |
900 | struct task_struct * task; | 941 | struct task_struct * task; |
901 | siginfo_t info; | 942 | siginfo_t info; |
@@ -911,7 +952,7 @@ void math_error(void __user *eip) | |||
911 | info.si_signo = SIGFPE; | 952 | info.si_signo = SIGFPE; |
912 | info.si_errno = 0; | 953 | info.si_errno = 0; |
913 | info.si_code = __SI_FAULT; | 954 | info.si_code = __SI_FAULT; |
914 | info.si_addr = eip; | 955 | info.si_addr = ip; |
915 | /* | 956 | /* |
916 | * (~cwd & swd) will mask out exceptions that are not set to unmasked | 957 | * (~cwd & swd) will mask out exceptions that are not set to unmasked |
917 | * status. 0x3f is the exception bits in these regs, 0x200 is the | 958 | * status. 0x3f is the exception bits in these regs, 0x200 is the |
@@ -954,13 +995,13 @@ void math_error(void __user *eip) | |||
954 | force_sig_info(SIGFPE, &info, task); | 995 | force_sig_info(SIGFPE, &info, task); |
955 | } | 996 | } |
956 | 997 | ||
957 | fastcall void do_coprocessor_error(struct pt_regs * regs, long error_code) | 998 | void do_coprocessor_error(struct pt_regs * regs, long error_code) |
958 | { | 999 | { |
959 | ignore_fpu_irq = 1; | 1000 | ignore_fpu_irq = 1; |
960 | math_error((void __user *)regs->eip); | 1001 | math_error((void __user *)regs->ip); |
961 | } | 1002 | } |
962 | 1003 | ||
963 | static void simd_math_error(void __user *eip) | 1004 | static void simd_math_error(void __user *ip) |
964 | { | 1005 | { |
965 | struct task_struct * task; | 1006 | struct task_struct * task; |
966 | siginfo_t info; | 1007 | siginfo_t info; |
@@ -976,7 +1017,7 @@ static void simd_math_error(void __user *eip) | |||
976 | info.si_signo = SIGFPE; | 1017 | info.si_signo = SIGFPE; |
977 | info.si_errno = 0; | 1018 | info.si_errno = 0; |
978 | info.si_code = __SI_FAULT; | 1019 | info.si_code = __SI_FAULT; |
979 | info.si_addr = eip; | 1020 | info.si_addr = ip; |
980 | /* | 1021 | /* |
981 | * The SIMD FPU exceptions are handled a little differently, as there | 1022 | * The SIMD FPU exceptions are handled a little differently, as there |
982 | * is only a single status/control register. Thus, to determine which | 1023 | * is only a single status/control register. Thus, to determine which |
@@ -1008,19 +1049,19 @@ static void simd_math_error(void __user *eip) | |||
1008 | force_sig_info(SIGFPE, &info, task); | 1049 | force_sig_info(SIGFPE, &info, task); |
1009 | } | 1050 | } |
1010 | 1051 | ||
1011 | fastcall void do_simd_coprocessor_error(struct pt_regs * regs, | 1052 | void do_simd_coprocessor_error(struct pt_regs * regs, |
1012 | long error_code) | 1053 | long error_code) |
1013 | { | 1054 | { |
1014 | if (cpu_has_xmm) { | 1055 | if (cpu_has_xmm) { |
1015 | /* Handle SIMD FPU exceptions on PIII+ processors. */ | 1056 | /* Handle SIMD FPU exceptions on PIII+ processors. */ |
1016 | ignore_fpu_irq = 1; | 1057 | ignore_fpu_irq = 1; |
1017 | simd_math_error((void __user *)regs->eip); | 1058 | simd_math_error((void __user *)regs->ip); |
1018 | } else { | 1059 | } else { |
1019 | /* | 1060 | /* |
1020 | * Handle strange cache flush from user space exception | 1061 | * Handle strange cache flush from user space exception |
1021 | * in all other cases. This is undocumented behaviour. | 1062 | * in all other cases. This is undocumented behaviour. |
1022 | */ | 1063 | */ |
1023 | if (regs->eflags & VM_MASK) { | 1064 | if (regs->flags & VM_MASK) { |
1024 | handle_vm86_fault((struct kernel_vm86_regs *)regs, | 1065 | handle_vm86_fault((struct kernel_vm86_regs *)regs, |
1025 | error_code); | 1066 | error_code); |
1026 | return; | 1067 | return; |
@@ -1032,7 +1073,7 @@ fastcall void do_simd_coprocessor_error(struct pt_regs * regs, | |||
1032 | } | 1073 | } |
1033 | } | 1074 | } |
1034 | 1075 | ||
1035 | fastcall void do_spurious_interrupt_bug(struct pt_regs * regs, | 1076 | void do_spurious_interrupt_bug(struct pt_regs * regs, |
1036 | long error_code) | 1077 | long error_code) |
1037 | { | 1078 | { |
1038 | #if 0 | 1079 | #if 0 |
@@ -1041,7 +1082,7 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs, | |||
1041 | #endif | 1082 | #endif |
1042 | } | 1083 | } |
1043 | 1084 | ||
1044 | fastcall unsigned long patch_espfix_desc(unsigned long uesp, | 1085 | unsigned long patch_espfix_desc(unsigned long uesp, |
1045 | unsigned long kesp) | 1086 | unsigned long kesp) |
1046 | { | 1087 | { |
1047 | struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt; | 1088 | struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt; |
@@ -1095,51 +1136,17 @@ asmlinkage void math_emulate(long arg) | |||
1095 | 1136 | ||
1096 | #endif /* CONFIG_MATH_EMULATION */ | 1137 | #endif /* CONFIG_MATH_EMULATION */ |
1097 | 1138 | ||
1098 | /* | ||
1099 | * This needs to use 'idt_table' rather than 'idt', and | ||
1100 | * thus use the _nonmapped_ version of the IDT, as the | ||
1101 | * Pentium F0 0F bugfix can have resulted in the mapped | ||
1102 | * IDT being write-protected. | ||
1103 | */ | ||
1104 | void set_intr_gate(unsigned int n, void *addr) | ||
1105 | { | ||
1106 | _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS); | ||
1107 | } | ||
1108 | |||
1109 | /* | ||
1110 | * This routine sets up an interrupt gate at directory privilege level 3. | ||
1111 | */ | ||
1112 | static inline void set_system_intr_gate(unsigned int n, void *addr) | ||
1113 | { | ||
1114 | _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS); | ||
1115 | } | ||
1116 | |||
1117 | static void __init set_trap_gate(unsigned int n, void *addr) | ||
1118 | { | ||
1119 | _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS); | ||
1120 | } | ||
1121 | |||
1122 | static void __init set_system_gate(unsigned int n, void *addr) | ||
1123 | { | ||
1124 | _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS); | ||
1125 | } | ||
1126 | |||
1127 | static void __init set_task_gate(unsigned int n, unsigned int gdt_entry) | ||
1128 | { | ||
1129 | _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3)); | ||
1130 | } | ||
1131 | |||
1132 | 1139 | ||
1133 | void __init trap_init(void) | 1140 | void __init trap_init(void) |
1134 | { | 1141 | { |
1135 | int i; | 1142 | int i; |
1136 | 1143 | ||
1137 | #ifdef CONFIG_EISA | 1144 | #ifdef CONFIG_EISA |
1138 | void __iomem *p = ioremap(0x0FFFD9, 4); | 1145 | void __iomem *p = early_ioremap(0x0FFFD9, 4); |
1139 | if (readl(p) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) { | 1146 | if (readl(p) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) { |
1140 | EISA_bus = 1; | 1147 | EISA_bus = 1; |
1141 | } | 1148 | } |
1142 | iounmap(p); | 1149 | early_iounmap(p, 4); |
1143 | #endif | 1150 | #endif |
1144 | 1151 | ||
1145 | #ifdef CONFIG_X86_LOCAL_APIC | 1152 | #ifdef CONFIG_X86_LOCAL_APIC |