diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/calls.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 10 | ||||
-rw-r--r-- | arch/arm/kernel/entry-header.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/ftrace.c | 8 | ||||
-rw-r--r-- | arch/arm/kernel/irq.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/kgdb.c | 13 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes.c | 11 | ||||
-rw-r--r-- | arch/arm/kernel/module.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event.c | 9 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 9 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 60 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.h | 14 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 93 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/sys_arm.c | 131 | ||||
-rw-r--r-- | arch/arm/kernel/sys_oabi-compat.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/unwind.c | 4 |
17 files changed, 154 insertions, 224 deletions
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 9314a2d681f1..37ae301cc47c 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -91,7 +91,7 @@ | |||
91 | CALL(sys_settimeofday) | 91 | CALL(sys_settimeofday) |
92 | /* 80 */ CALL(sys_getgroups16) | 92 | /* 80 */ CALL(sys_getgroups16) |
93 | CALL(sys_setgroups16) | 93 | CALL(sys_setgroups16) |
94 | CALL(OBSOLETE(old_select)) /* used by libc4 */ | 94 | CALL(OBSOLETE(sys_old_select)) /* used by libc4 */ |
95 | CALL(sys_symlink) | 95 | CALL(sys_symlink) |
96 | CALL(sys_ni_syscall) /* was sys_lstat */ | 96 | CALL(sys_ni_syscall) /* was sys_lstat */ |
97 | /* 85 */ CALL(sys_readlink) | 97 | /* 85 */ CALL(sys_readlink) |
@@ -99,7 +99,7 @@ | |||
99 | CALL(sys_swapon) | 99 | CALL(sys_swapon) |
100 | CALL(sys_reboot) | 100 | CALL(sys_reboot) |
101 | CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */ | 101 | CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */ |
102 | /* 90 */ CALL(OBSOLETE(old_mmap)) /* used by libc4 */ | 102 | /* 90 */ CALL(OBSOLETE(sys_old_mmap)) /* used by libc4 */ |
103 | CALL(sys_munmap) | 103 | CALL(sys_munmap) |
104 | CALL(sys_truncate) | 104 | CALL(sys_truncate) |
105 | CALL(sys_ftruncate) | 105 | CALL(sys_ftruncate) |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 6c5cf369183b..e6a0fb0f392e 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -523,16 +523,16 @@ ENDPROC(__und_usr) | |||
523 | /* | 523 | /* |
524 | * The out of line fixup for the ldrt above. | 524 | * The out of line fixup for the ldrt above. |
525 | */ | 525 | */ |
526 | .section .fixup, "ax" | 526 | .pushsection .fixup, "ax" |
527 | 4: mov pc, r9 | 527 | 4: mov pc, r9 |
528 | .previous | 528 | .popsection |
529 | .section __ex_table,"a" | 529 | .pushsection __ex_table,"a" |
530 | .long 1b, 4b | 530 | .long 1b, 4b |
531 | #if __LINUX_ARM_ARCH__ >= 7 | 531 | #if __LINUX_ARM_ARCH__ >= 7 |
532 | .long 2b, 4b | 532 | .long 2b, 4b |
533 | .long 3b, 4b | 533 | .long 3b, 4b |
534 | #endif | 534 | #endif |
535 | .previous | 535 | .popsection |
536 | 536 | ||
537 | /* | 537 | /* |
538 | * Check whether the instruction is a co-processor instruction. | 538 | * Check whether the instruction is a co-processor instruction. |
@@ -679,7 +679,7 @@ do_fpe: | |||
679 | .data | 679 | .data |
680 | ENTRY(fp_enter) | 680 | ENTRY(fp_enter) |
681 | .word no_fp | 681 | .word no_fp |
682 | .previous | 682 | .text |
683 | 683 | ||
684 | ENTRY(no_fp) | 684 | ENTRY(no_fp) |
685 | mov pc, lr | 685 | mov pc, lr |
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 7e9ed1eea40a..d93f976fb389 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S | |||
@@ -102,6 +102,8 @@ | |||
102 | .else | 102 | .else |
103 | ldmdb sp, {r0 - lr}^ @ get calling r0 - lr | 103 | ldmdb sp, {r0 - lr}^ @ get calling r0 - lr |
104 | .endif | 104 | .endif |
105 | mov r0, r0 @ ARMv5T and earlier require a nop | ||
106 | @ after ldm {}^ | ||
105 | add sp, sp, #S_FRAME_SIZE - S_PC | 107 | add sp, sp, #S_FRAME_SIZE - S_PC |
106 | movs pc, lr @ return & move spsr_svc into cpsr | 108 | movs pc, lr @ return & move spsr_svc into cpsr |
107 | .endm | 109 | .endm |
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index c63842766229..0298286ad4ad 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c | |||
@@ -62,15 +62,15 @@ int ftrace_modify_code(unsigned long pc, unsigned char *old_code, | |||
62 | " movne %0, #2 \n" | 62 | " movne %0, #2 \n" |
63 | "3:\n" | 63 | "3:\n" |
64 | 64 | ||
65 | ".section .fixup, \"ax\"\n" | 65 | ".pushsection .fixup, \"ax\"\n" |
66 | "4: mov %0, #1 \n" | 66 | "4: mov %0, #1 \n" |
67 | " b 3b \n" | 67 | " b 3b \n" |
68 | ".previous\n" | 68 | ".popsection\n" |
69 | 69 | ||
70 | ".section __ex_table, \"a\"\n" | 70 | ".pushsection __ex_table, \"a\"\n" |
71 | " .long 1b, 4b \n" | 71 | " .long 1b, 4b \n" |
72 | " .long 2b, 4b \n" | 72 | " .long 2b, 4b \n" |
73 | ".previous\n" | 73 | ".popsection\n" |
74 | 74 | ||
75 | : "=r"(err), "=r"(replaced) | 75 | : "=r"(err), "=r"(replaced) |
76 | : "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced) | 76 | : "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced) |
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index b7cb45bb91e8..3b3d2c80509c 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/irq.h> | 29 | #include <linux/irq.h> |
30 | #include <linux/slab.h> | ||
31 | #include <linux/random.h> | 30 | #include <linux/random.h> |
32 | #include <linux/smp.h> | 31 | #include <linux/smp.h> |
33 | #include <linux/init.h> | 32 | #include <linux/init.h> |
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index ba8ccfede964..a5b846b9895d 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * Authors: George Davis <davis_g@mvista.com> | 9 | * Authors: George Davis <davis_g@mvista.com> |
10 | * Deepak Saxena <dsaxena@plexity.net> | 10 | * Deepak Saxena <dsaxena@plexity.net> |
11 | */ | 11 | */ |
12 | #include <linux/irq.h> | ||
12 | #include <linux/kgdb.h> | 13 | #include <linux/kgdb.h> |
13 | #include <asm/traps.h> | 14 | #include <asm/traps.h> |
14 | 15 | ||
@@ -158,6 +159,18 @@ static struct undef_hook kgdb_compiled_brkpt_hook = { | |||
158 | .fn = kgdb_compiled_brk_fn | 159 | .fn = kgdb_compiled_brk_fn |
159 | }; | 160 | }; |
160 | 161 | ||
162 | static void kgdb_call_nmi_hook(void *ignored) | ||
163 | { | ||
164 | kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); | ||
165 | } | ||
166 | |||
167 | void kgdb_roundup_cpus(unsigned long flags) | ||
168 | { | ||
169 | local_irq_enable(); | ||
170 | smp_call_function(kgdb_call_nmi_hook, NULL, 0); | ||
171 | local_irq_disable(); | ||
172 | } | ||
173 | |||
161 | /** | 174 | /** |
162 | * kgdb_arch_init - Perform any architecture specific initalization. | 175 | * kgdb_arch_init - Perform any architecture specific initalization. |
163 | * | 176 | * |
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index 60c62c377fa9..2ba7deb3072e 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/kprobes.h> | 23 | #include <linux/kprobes.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/slab.h> | ||
25 | #include <linux/stop_machine.h> | 26 | #include <linux/stop_machine.h> |
26 | #include <linux/stringify.h> | 27 | #include <linux/stringify.h> |
27 | #include <asm/traps.h> | 28 | #include <asm/traps.h> |
@@ -393,6 +394,14 @@ void __kprobes jprobe_return(void) | |||
393 | /* | 394 | /* |
394 | * Setup an empty pt_regs. Fill SP and PC fields as | 395 | * Setup an empty pt_regs. Fill SP and PC fields as |
395 | * they're needed by longjmp_break_handler. | 396 | * they're needed by longjmp_break_handler. |
397 | * | ||
398 | * We allocate some slack between the original SP and start of | ||
399 | * our fabricated regs. To be precise we want to have worst case | ||
400 | * covered which is STMFD with all 16 regs so we allocate 2 * | ||
401 | * sizeof(struct_pt_regs)). | ||
402 | * | ||
403 | * This is to prevent any simulated instruction from writing | ||
404 | * over the regs when they are accessing the stack. | ||
396 | */ | 405 | */ |
397 | "sub sp, %0, %1 \n\t" | 406 | "sub sp, %0, %1 \n\t" |
398 | "ldr r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t" | 407 | "ldr r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t" |
@@ -410,7 +419,7 @@ void __kprobes jprobe_return(void) | |||
410 | "ldmia sp, {r0 - pc} \n\t" | 419 | "ldmia sp, {r0 - pc} \n\t" |
411 | : | 420 | : |
412 | : "r" (kcb->jprobe_saved_regs.ARM_sp), | 421 | : "r" (kcb->jprobe_saved_regs.ARM_sp), |
413 | "I" (sizeof(struct pt_regs)), | 422 | "I" (sizeof(struct pt_regs) * 2), |
414 | "J" (offsetof(struct pt_regs, ARM_sp)), | 423 | "J" (offsetof(struct pt_regs, ARM_sp)), |
415 | "J" (offsetof(struct pt_regs, ARM_pc)), | 424 | "J" (offsetof(struct pt_regs, ARM_pc)), |
416 | "J" (offsetof(struct pt_regs, ARM_cpsr)) | 425 | "J" (offsetof(struct pt_regs, ARM_cpsr)) |
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index f28c5e9c51ea..c628bdf6c430 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c | |||
@@ -16,9 +16,9 @@ | |||
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/elf.h> | 17 | #include <linux/elf.h> |
18 | #include <linux/vmalloc.h> | 18 | #include <linux/vmalloc.h> |
19 | #include <linux/slab.h> | ||
20 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
21 | #include <linux/string.h> | 20 | #include <linux/string.h> |
21 | #include <linux/gfp.h> | ||
22 | 22 | ||
23 | #include <asm/pgtable.h> | 23 | #include <asm/pgtable.h> |
24 | #include <asm/sections.h> | 24 | #include <asm/sections.h> |
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index c54ceb3d1f97..9e70f2053f9a 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -332,7 +332,8 @@ armpmu_reserve_hardware(void) | |||
332 | 332 | ||
333 | for (i = 0; i < pmu_irqs->num_irqs; ++i) { | 333 | for (i = 0; i < pmu_irqs->num_irqs; ++i) { |
334 | err = request_irq(pmu_irqs->irqs[i], armpmu->handle_irq, | 334 | err = request_irq(pmu_irqs->irqs[i], armpmu->handle_irq, |
335 | IRQF_DISABLED, "armpmu", NULL); | 335 | IRQF_DISABLED | IRQF_NOBALANCING, |
336 | "armpmu", NULL); | ||
336 | if (err) { | 337 | if (err) { |
337 | pr_warning("unable to request IRQ%d for ARM " | 338 | pr_warning("unable to request IRQ%d for ARM " |
338 | "perf counters\n", pmu_irqs->irqs[i]); | 339 | "perf counters\n", pmu_irqs->irqs[i]); |
@@ -965,7 +966,7 @@ armv6pmu_handle_irq(int irq_num, | |||
965 | */ | 966 | */ |
966 | armv6_pmcr_write(pmcr); | 967 | armv6_pmcr_write(pmcr); |
967 | 968 | ||
968 | data.addr = 0; | 969 | perf_sample_data_init(&data, 0); |
969 | 970 | ||
970 | cpuc = &__get_cpu_var(cpu_hw_events); | 971 | cpuc = &__get_cpu_var(cpu_hw_events); |
971 | for (idx = 0; idx <= armpmu->num_events; ++idx) { | 972 | for (idx = 0; idx <= armpmu->num_events; ++idx) { |
@@ -1624,7 +1625,7 @@ enum armv7_counters { | |||
1624 | /* | 1625 | /* |
1625 | * EVTSEL: Event selection reg | 1626 | * EVTSEL: Event selection reg |
1626 | */ | 1627 | */ |
1627 | #define ARMV7_EVTSEL_MASK 0x7f /* Mask for writable bits */ | 1628 | #define ARMV7_EVTSEL_MASK 0xff /* Mask for writable bits */ |
1628 | 1629 | ||
1629 | /* | 1630 | /* |
1630 | * SELECT: Counter selection reg | 1631 | * SELECT: Counter selection reg |
@@ -1945,7 +1946,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) | |||
1945 | */ | 1946 | */ |
1946 | regs = get_irq_regs(); | 1947 | regs = get_irq_regs(); |
1947 | 1948 | ||
1948 | data.addr = 0; | 1949 | perf_sample_data_init(&data, 0); |
1949 | 1950 | ||
1950 | cpuc = &__get_cpu_var(cpu_hw_events); | 1951 | cpuc = &__get_cpu_var(cpu_hw_events); |
1951 | for (idx = 0; idx <= armpmu->num_events; ++idx) { | 1952 | for (idx = 0; idx <= armpmu->num_events; ++idx) { |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index ba2adefa53f7..acf5e6fdb6dc 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/stddef.h> | 17 | #include <linux/stddef.h> |
18 | #include <linux/unistd.h> | 18 | #include <linux/unistd.h> |
19 | #include <linux/slab.h> | ||
20 | #include <linux/user.h> | 19 | #include <linux/user.h> |
21 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
22 | #include <linux/reboot.h> | 21 | #include <linux/reboot.h> |
@@ -356,7 +355,7 @@ EXPORT_SYMBOL(dump_fpu); | |||
356 | * the thread function, and r3 points to the exit function. | 355 | * the thread function, and r3 points to the exit function. |
357 | */ | 356 | */ |
358 | extern void kernel_thread_helper(void); | 357 | extern void kernel_thread_helper(void); |
359 | asm( ".section .text\n" | 358 | asm( ".pushsection .text\n" |
360 | " .align\n" | 359 | " .align\n" |
361 | " .type kernel_thread_helper, #function\n" | 360 | " .type kernel_thread_helper, #function\n" |
362 | "kernel_thread_helper:\n" | 361 | "kernel_thread_helper:\n" |
@@ -364,11 +363,11 @@ asm( ".section .text\n" | |||
364 | " mov lr, r3\n" | 363 | " mov lr, r3\n" |
365 | " mov pc, r2\n" | 364 | " mov pc, r2\n" |
366 | " .size kernel_thread_helper, . - kernel_thread_helper\n" | 365 | " .size kernel_thread_helper, . - kernel_thread_helper\n" |
367 | " .previous"); | 366 | " .popsection"); |
368 | 367 | ||
369 | #ifdef CONFIG_ARM_UNWIND | 368 | #ifdef CONFIG_ARM_UNWIND |
370 | extern void kernel_thread_exit(long code); | 369 | extern void kernel_thread_exit(long code); |
371 | asm( ".section .text\n" | 370 | asm( ".pushsection .text\n" |
372 | " .align\n" | 371 | " .align\n" |
373 | " .type kernel_thread_exit, #function\n" | 372 | " .type kernel_thread_exit, #function\n" |
374 | "kernel_thread_exit:\n" | 373 | "kernel_thread_exit:\n" |
@@ -378,7 +377,7 @@ asm( ".section .text\n" | |||
378 | " nop\n" | 377 | " nop\n" |
379 | " .fnend\n" | 378 | " .fnend\n" |
380 | " .size kernel_thread_exit, . - kernel_thread_exit\n" | 379 | " .size kernel_thread_exit, . - kernel_thread_exit\n" |
381 | " .previous"); | 380 | " .popsection"); |
382 | #else | 381 | #else |
383 | #define kernel_thread_exit do_exit | 382 | #define kernel_thread_exit do_exit |
384 | #endif | 383 | #endif |
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 08f899fb76a6..3f562a7c0a99 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -452,12 +452,23 @@ void ptrace_cancel_bpt(struct task_struct *child) | |||
452 | clear_breakpoint(child, &child->thread.debug.bp[i]); | 452 | clear_breakpoint(child, &child->thread.debug.bp[i]); |
453 | } | 453 | } |
454 | 454 | ||
455 | void user_disable_single_step(struct task_struct *task) | ||
456 | { | ||
457 | task->ptrace &= ~PT_SINGLESTEP; | ||
458 | ptrace_cancel_bpt(task); | ||
459 | } | ||
460 | |||
461 | void user_enable_single_step(struct task_struct *task) | ||
462 | { | ||
463 | task->ptrace |= PT_SINGLESTEP; | ||
464 | } | ||
465 | |||
455 | /* | 466 | /* |
456 | * Called by kernel/ptrace.c when detaching.. | 467 | * Called by kernel/ptrace.c when detaching.. |
457 | */ | 468 | */ |
458 | void ptrace_disable(struct task_struct *child) | 469 | void ptrace_disable(struct task_struct *child) |
459 | { | 470 | { |
460 | single_step_disable(child); | 471 | user_disable_single_step(child); |
461 | } | 472 | } |
462 | 473 | ||
463 | /* | 474 | /* |
@@ -753,53 +764,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
753 | ret = ptrace_write_user(child, addr, data); | 764 | ret = ptrace_write_user(child, addr, data); |
754 | break; | 765 | break; |
755 | 766 | ||
756 | /* | ||
757 | * continue/restart and stop at next (return from) syscall | ||
758 | */ | ||
759 | case PTRACE_SYSCALL: | ||
760 | case PTRACE_CONT: | ||
761 | ret = -EIO; | ||
762 | if (!valid_signal(data)) | ||
763 | break; | ||
764 | if (request == PTRACE_SYSCALL) | ||
765 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
766 | else | ||
767 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
768 | child->exit_code = data; | ||
769 | single_step_disable(child); | ||
770 | wake_up_process(child); | ||
771 | ret = 0; | ||
772 | break; | ||
773 | |||
774 | /* | ||
775 | * make the child exit. Best I can do is send it a sigkill. | ||
776 | * perhaps it should be put in the status that it wants to | ||
777 | * exit. | ||
778 | */ | ||
779 | case PTRACE_KILL: | ||
780 | single_step_disable(child); | ||
781 | if (child->exit_state != EXIT_ZOMBIE) { | ||
782 | child->exit_code = SIGKILL; | ||
783 | wake_up_process(child); | ||
784 | } | ||
785 | ret = 0; | ||
786 | break; | ||
787 | |||
788 | /* | ||
789 | * execute single instruction. | ||
790 | */ | ||
791 | case PTRACE_SINGLESTEP: | ||
792 | ret = -EIO; | ||
793 | if (!valid_signal(data)) | ||
794 | break; | ||
795 | single_step_enable(child); | ||
796 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
797 | child->exit_code = data; | ||
798 | /* give it a chance to run. */ | ||
799 | wake_up_process(child); | ||
800 | ret = 0; | ||
801 | break; | ||
802 | |||
803 | case PTRACE_GETREGS: | 767 | case PTRACE_GETREGS: |
804 | ret = ptrace_getregs(child, (void __user *)data); | 768 | ret = ptrace_getregs(child, (void __user *)data); |
805 | break; | 769 | break; |
diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h index def3b6184a79..3926605b82ea 100644 --- a/arch/arm/kernel/ptrace.h +++ b/arch/arm/kernel/ptrace.h | |||
@@ -14,20 +14,6 @@ extern void ptrace_set_bpt(struct task_struct *); | |||
14 | extern void ptrace_break(struct task_struct *, struct pt_regs *); | 14 | extern void ptrace_break(struct task_struct *, struct pt_regs *); |
15 | 15 | ||
16 | /* | 16 | /* |
17 | * make sure single-step breakpoint is gone. | ||
18 | */ | ||
19 | static inline void single_step_disable(struct task_struct *task) | ||
20 | { | ||
21 | task->ptrace &= ~PT_SINGLESTEP; | ||
22 | ptrace_cancel_bpt(task); | ||
23 | } | ||
24 | |||
25 | static inline void single_step_enable(struct task_struct *task) | ||
26 | { | ||
27 | task->ptrace |= PT_SINGLESTEP; | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * Send SIGTRAP if we're single-stepping | 17 | * Send SIGTRAP if we're single-stepping |
32 | */ | 18 | */ |
33 | static inline void single_step_trap(struct task_struct *task) | 19 | static inline void single_step_trap(struct task_struct *task) |
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index e7714f367eb8..907d5a620bca 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/cacheflush.h> | 18 | #include <asm/cacheflush.h> |
19 | #include <asm/ucontext.h> | 19 | #include <asm/ucontext.h> |
20 | #include <asm/unistd.h> | 20 | #include <asm/unistd.h> |
21 | #include <asm/vfp.h> | ||
21 | 22 | ||
22 | #include "ptrace.h" | 23 | #include "ptrace.h" |
23 | #include "signal.h" | 24 | #include "signal.h" |
@@ -175,6 +176,90 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame) | |||
175 | 176 | ||
176 | #endif | 177 | #endif |
177 | 178 | ||
179 | #ifdef CONFIG_VFP | ||
180 | |||
181 | static int preserve_vfp_context(struct vfp_sigframe __user *frame) | ||
182 | { | ||
183 | struct thread_info *thread = current_thread_info(); | ||
184 | struct vfp_hard_struct *h = &thread->vfpstate.hard; | ||
185 | const unsigned long magic = VFP_MAGIC; | ||
186 | const unsigned long size = VFP_STORAGE_SIZE; | ||
187 | int err = 0; | ||
188 | |||
189 | vfp_sync_hwstate(thread); | ||
190 | __put_user_error(magic, &frame->magic, err); | ||
191 | __put_user_error(size, &frame->size, err); | ||
192 | |||
193 | /* | ||
194 | * Copy the floating point registers. There can be unused | ||
195 | * registers see asm/hwcap.h for details. | ||
196 | */ | ||
197 | err |= __copy_to_user(&frame->ufp.fpregs, &h->fpregs, | ||
198 | sizeof(h->fpregs)); | ||
199 | /* | ||
200 | * Copy the status and control register. | ||
201 | */ | ||
202 | __put_user_error(h->fpscr, &frame->ufp.fpscr, err); | ||
203 | |||
204 | /* | ||
205 | * Copy the exception registers. | ||
206 | */ | ||
207 | __put_user_error(h->fpexc, &frame->ufp_exc.fpexc, err); | ||
208 | __put_user_error(h->fpinst, &frame->ufp_exc.fpinst, err); | ||
209 | __put_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err); | ||
210 | |||
211 | return err ? -EFAULT : 0; | ||
212 | } | ||
213 | |||
214 | static int restore_vfp_context(struct vfp_sigframe __user *frame) | ||
215 | { | ||
216 | struct thread_info *thread = current_thread_info(); | ||
217 | struct vfp_hard_struct *h = &thread->vfpstate.hard; | ||
218 | unsigned long magic; | ||
219 | unsigned long size; | ||
220 | unsigned long fpexc; | ||
221 | int err = 0; | ||
222 | |||
223 | __get_user_error(magic, &frame->magic, err); | ||
224 | __get_user_error(size, &frame->size, err); | ||
225 | |||
226 | if (err) | ||
227 | return -EFAULT; | ||
228 | if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) | ||
229 | return -EINVAL; | ||
230 | |||
231 | /* | ||
232 | * Copy the floating point registers. There can be unused | ||
233 | * registers see asm/hwcap.h for details. | ||
234 | */ | ||
235 | err |= __copy_from_user(&h->fpregs, &frame->ufp.fpregs, | ||
236 | sizeof(h->fpregs)); | ||
237 | /* | ||
238 | * Copy the status and control register. | ||
239 | */ | ||
240 | __get_user_error(h->fpscr, &frame->ufp.fpscr, err); | ||
241 | |||
242 | /* | ||
243 | * Sanitise and restore the exception registers. | ||
244 | */ | ||
245 | __get_user_error(fpexc, &frame->ufp_exc.fpexc, err); | ||
246 | /* Ensure the VFP is enabled. */ | ||
247 | fpexc |= FPEXC_EN; | ||
248 | /* Ensure FPINST2 is invalid and the exception flag is cleared. */ | ||
249 | fpexc &= ~(FPEXC_EX | FPEXC_FP2V); | ||
250 | h->fpexc = fpexc; | ||
251 | |||
252 | __get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err); | ||
253 | __get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err); | ||
254 | |||
255 | if (!err) | ||
256 | vfp_flush_hwstate(thread); | ||
257 | |||
258 | return err ? -EFAULT : 0; | ||
259 | } | ||
260 | |||
261 | #endif | ||
262 | |||
178 | /* | 263 | /* |
179 | * Do a signal return; undo the signal stack. These are aligned to 64-bit. | 264 | * Do a signal return; undo the signal stack. These are aligned to 64-bit. |
180 | */ | 265 | */ |
@@ -233,8 +318,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) | |||
233 | err |= restore_iwmmxt_context(&aux->iwmmxt); | 318 | err |= restore_iwmmxt_context(&aux->iwmmxt); |
234 | #endif | 319 | #endif |
235 | #ifdef CONFIG_VFP | 320 | #ifdef CONFIG_VFP |
236 | // if (err == 0) | 321 | if (err == 0) |
237 | // err |= vfp_restore_state(&sf->aux.vfp); | 322 | err |= restore_vfp_context(&aux->vfp); |
238 | #endif | 323 | #endif |
239 | 324 | ||
240 | return err; | 325 | return err; |
@@ -348,8 +433,8 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set) | |||
348 | err |= preserve_iwmmxt_context(&aux->iwmmxt); | 433 | err |= preserve_iwmmxt_context(&aux->iwmmxt); |
349 | #endif | 434 | #endif |
350 | #ifdef CONFIG_VFP | 435 | #ifdef CONFIG_VFP |
351 | // if (err == 0) | 436 | if (err == 0) |
352 | // err |= vfp_save_state(&sf->aux.vfp); | 437 | err |= preserve_vfp_context(&aux->vfp); |
353 | #endif | 438 | #endif |
354 | __put_user_error(0, &aux->end_magic, err); | 439 | __put_user_error(0, &aux->end_magic, err); |
355 | 440 | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 57162af53dc9..577543f3857f 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -99,6 +99,7 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
99 | *pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) | | 99 | *pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) | |
100 | PMD_TYPE_SECT | PMD_SECT_AP_WRITE); | 100 | PMD_TYPE_SECT | PMD_SECT_AP_WRITE); |
101 | flush_pmd_entry(pmd); | 101 | flush_pmd_entry(pmd); |
102 | outer_clean_range(__pa(pmd), __pa(pmd + 1)); | ||
102 | 103 | ||
103 | /* | 104 | /* |
104 | * We need to tell the secondary core where to find | 105 | * We need to tell the secondary core where to find |
@@ -106,7 +107,8 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
106 | */ | 107 | */ |
107 | secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; | 108 | secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; |
108 | secondary_data.pgdir = virt_to_phys(pgd); | 109 | secondary_data.pgdir = virt_to_phys(pgd); |
109 | wmb(); | 110 | __cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data)); |
111 | outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1)); | ||
110 | 112 | ||
111 | /* | 113 | /* |
112 | * Now bring the CPU into our world. | 114 | * Now bring the CPU into our world. |
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index ae4027bd01bd..c23501842b98 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/slab.h> | ||
19 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
20 | #include <linux/sem.h> | 19 | #include <linux/sem.h> |
21 | #include <linux/msg.h> | 20 | #include <linux/msg.h> |
@@ -27,135 +26,7 @@ | |||
27 | #include <linux/file.h> | 26 | #include <linux/file.h> |
28 | #include <linux/ipc.h> | 27 | #include <linux/ipc.h> |
29 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
30 | 29 | #include <linux/slab.h> | |
31 | struct mmap_arg_struct { | ||
32 | unsigned long addr; | ||
33 | unsigned long len; | ||
34 | unsigned long prot; | ||
35 | unsigned long flags; | ||
36 | unsigned long fd; | ||
37 | unsigned long offset; | ||
38 | }; | ||
39 | |||
40 | asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) | ||
41 | { | ||
42 | int error = -EFAULT; | ||
43 | struct mmap_arg_struct a; | ||
44 | |||
45 | if (copy_from_user(&a, arg, sizeof(a))) | ||
46 | goto out; | ||
47 | |||
48 | error = -EINVAL; | ||
49 | if (a.offset & ~PAGE_MASK) | ||
50 | goto out; | ||
51 | |||
52 | error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); | ||
53 | out: | ||
54 | return error; | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
59 | * calls. | ||
60 | */ | ||
61 | |||
62 | struct sel_arg_struct { | ||
63 | unsigned long n; | ||
64 | fd_set __user *inp, *outp, *exp; | ||
65 | struct timeval __user *tvp; | ||
66 | }; | ||
67 | |||
68 | asmlinkage int old_select(struct sel_arg_struct __user *arg) | ||
69 | { | ||
70 | struct sel_arg_struct a; | ||
71 | |||
72 | if (copy_from_user(&a, arg, sizeof(a))) | ||
73 | return -EFAULT; | ||
74 | /* sys_select() does the appropriate kernel locking */ | ||
75 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
76 | } | ||
77 | |||
78 | #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) | ||
79 | /* | ||
80 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
81 | * | ||
82 | * This is really horribly ugly. | ||
83 | */ | ||
84 | asmlinkage int sys_ipc(uint call, int first, int second, int third, | ||
85 | void __user *ptr, long fifth) | ||
86 | { | ||
87 | int version, ret; | ||
88 | |||
89 | version = call >> 16; /* hack for backward compatibility */ | ||
90 | call &= 0xffff; | ||
91 | |||
92 | switch (call) { | ||
93 | case SEMOP: | ||
94 | return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL); | ||
95 | case SEMTIMEDOP: | ||
96 | return sys_semtimedop(first, (struct sembuf __user *)ptr, second, | ||
97 | (const struct timespec __user *)fifth); | ||
98 | |||
99 | case SEMGET: | ||
100 | return sys_semget (first, second, third); | ||
101 | case SEMCTL: { | ||
102 | union semun fourth; | ||
103 | if (!ptr) | ||
104 | return -EINVAL; | ||
105 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
106 | return -EFAULT; | ||
107 | return sys_semctl (first, second, third, fourth); | ||
108 | } | ||
109 | |||
110 | case MSGSND: | ||
111 | return sys_msgsnd(first, (struct msgbuf __user *) ptr, | ||
112 | second, third); | ||
113 | case MSGRCV: | ||
114 | switch (version) { | ||
115 | case 0: { | ||
116 | struct ipc_kludge tmp; | ||
117 | if (!ptr) | ||
118 | return -EINVAL; | ||
119 | if (copy_from_user(&tmp,(struct ipc_kludge __user *)ptr, | ||
120 | sizeof (tmp))) | ||
121 | return -EFAULT; | ||
122 | return sys_msgrcv (first, tmp.msgp, second, | ||
123 | tmp.msgtyp, third); | ||
124 | } | ||
125 | default: | ||
126 | return sys_msgrcv (first, | ||
127 | (struct msgbuf __user *) ptr, | ||
128 | second, fifth, third); | ||
129 | } | ||
130 | case MSGGET: | ||
131 | return sys_msgget ((key_t) first, second); | ||
132 | case MSGCTL: | ||
133 | return sys_msgctl(first, second, (struct msqid_ds __user *)ptr); | ||
134 | |||
135 | case SHMAT: | ||
136 | switch (version) { | ||
137 | default: { | ||
138 | ulong raddr; | ||
139 | ret = do_shmat(first, (char __user *)ptr, second, &raddr); | ||
140 | if (ret) | ||
141 | return ret; | ||
142 | return put_user(raddr, (ulong __user *)third); | ||
143 | } | ||
144 | case 1: /* Of course, we don't support iBCS2! */ | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | case SHMDT: | ||
148 | return sys_shmdt ((char __user *)ptr); | ||
149 | case SHMGET: | ||
150 | return sys_shmget (first, second, third); | ||
151 | case SHMCTL: | ||
152 | return sys_shmctl (first, second, | ||
153 | (struct shmid_ds __user *) ptr); | ||
154 | default: | ||
155 | return -ENOSYS; | ||
156 | } | ||
157 | } | ||
158 | #endif | ||
159 | 30 | ||
160 | /* Fork a new task - this creates a new program thread. | 31 | /* Fork a new task - this creates a new program thread. |
161 | * This is called indirectly via a small wrapper | 32 | * This is called indirectly via a small wrapper |
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index d59a0cd537f0..33ff678e32f2 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c | |||
@@ -346,9 +346,6 @@ asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops, | |||
346 | return sys_oabi_semtimedop(semid, tsops, nsops, NULL); | 346 | return sys_oabi_semtimedop(semid, tsops, nsops, NULL); |
347 | } | 347 | } |
348 | 348 | ||
349 | extern asmlinkage int sys_ipc(uint call, int first, int second, int third, | ||
350 | void __user *ptr, long fifth); | ||
351 | |||
352 | asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, | 349 | asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, |
353 | void __user *ptr, long fifth) | 350 | void __user *ptr, long fifth) |
354 | { | 351 | { |
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 786ac2b6914a..50292cd9c120 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c | |||
@@ -359,7 +359,9 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
359 | frame.fp = regs->ARM_fp; | 359 | frame.fp = regs->ARM_fp; |
360 | frame.sp = regs->ARM_sp; | 360 | frame.sp = regs->ARM_sp; |
361 | frame.lr = regs->ARM_lr; | 361 | frame.lr = regs->ARM_lr; |
362 | frame.pc = regs->ARM_pc; | 362 | /* PC might be corrupted, use LR in that case. */ |
363 | frame.pc = kernel_text_address(regs->ARM_pc) | ||
364 | ? regs->ARM_pc : regs->ARM_lr; | ||
363 | } else if (tsk == current) { | 365 | } else if (tsk == current) { |
364 | frame.fp = (unsigned long)__builtin_frame_address(0); | 366 | frame.fp = (unsigned long)__builtin_frame_address(0); |
365 | frame.sp = current_sp; | 367 | frame.sp = current_sp; |