diff options
Diffstat (limited to 'arch/arm/kernel/process.c')
-rw-r--r-- | arch/arm/kernel/process.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 401e38be1f78..5e1e54197227 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <linux/random.h> | 31 | #include <linux/random.h> |
32 | #include <linux/hw_breakpoint.h> | ||
32 | 33 | ||
33 | #include <asm/cacheflush.h> | 34 | #include <asm/cacheflush.h> |
34 | #include <asm/leds.h> | 35 | #include <asm/leds.h> |
@@ -135,6 +136,25 @@ EXPORT_SYMBOL(pm_power_off); | |||
135 | void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart; | 136 | void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart; |
136 | EXPORT_SYMBOL_GPL(arm_pm_restart); | 137 | EXPORT_SYMBOL_GPL(arm_pm_restart); |
137 | 138 | ||
139 | static void do_nothing(void *unused) | ||
140 | { | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of | ||
145 | * pm_idle and update to new pm_idle value. Required while changing pm_idle | ||
146 | * handler on SMP systems. | ||
147 | * | ||
148 | * Caller must have changed pm_idle to the new value before the call. Old | ||
149 | * pm_idle value will not be used by any CPU after the return of this function. | ||
150 | */ | ||
151 | void cpu_idle_wait(void) | ||
152 | { | ||
153 | smp_mb(); | ||
154 | /* kick all the CPUs so that they exit out of pm_idle */ | ||
155 | smp_call_function(do_nothing, NULL, 1); | ||
156 | } | ||
157 | EXPORT_SYMBOL_GPL(cpu_idle_wait); | ||
138 | 158 | ||
139 | /* | 159 | /* |
140 | * This is our default idle handler. We need to disable | 160 | * This is our default idle handler. We need to disable |
@@ -317,6 +337,8 @@ void flush_thread(void) | |||
317 | struct thread_info *thread = current_thread_info(); | 337 | struct thread_info *thread = current_thread_info(); |
318 | struct task_struct *tsk = current; | 338 | struct task_struct *tsk = current; |
319 | 339 | ||
340 | flush_ptrace_hw_breakpoint(tsk); | ||
341 | |||
320 | memset(thread->used_cp, 0, sizeof(thread->used_cp)); | 342 | memset(thread->used_cp, 0, sizeof(thread->used_cp)); |
321 | memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); | 343 | memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); |
322 | memset(&thread->fpstate, 0, sizeof(union fp_state)); | 344 | memset(&thread->fpstate, 0, sizeof(union fp_state)); |
@@ -345,9 +367,13 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, | |||
345 | thread->cpu_context.sp = (unsigned long)childregs; | 367 | thread->cpu_context.sp = (unsigned long)childregs; |
346 | thread->cpu_context.pc = (unsigned long)ret_from_fork; | 368 | thread->cpu_context.pc = (unsigned long)ret_from_fork; |
347 | 369 | ||
370 | clear_ptrace_hw_breakpoint(p); | ||
371 | |||
348 | if (clone_flags & CLONE_SETTLS) | 372 | if (clone_flags & CLONE_SETTLS) |
349 | thread->tp_value = regs->ARM_r3; | 373 | thread->tp_value = regs->ARM_r3; |
350 | 374 | ||
375 | thread_notify(THREAD_NOTIFY_COPY, thread); | ||
376 | |||
351 | return 0; | 377 | return 0; |
352 | } | 378 | } |
353 | 379 | ||
@@ -458,3 +484,26 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) | |||
458 | unsigned long range_end = mm->brk + 0x02000000; | 484 | unsigned long range_end = mm->brk + 0x02000000; |
459 | return randomize_range(mm->brk, range_end, 0) ? : mm->brk; | 485 | return randomize_range(mm->brk, range_end, 0) ? : mm->brk; |
460 | } | 486 | } |
487 | |||
488 | #ifdef CONFIG_MMU | ||
489 | /* | ||
490 | * The vectors page is always readable from user space for the | ||
491 | * atomic helpers and the signal restart code. Let's declare a mapping | ||
492 | * for it so it is visible through ptrace and /proc/<pid>/mem. | ||
493 | */ | ||
494 | |||
495 | int vectors_user_mapping(void) | ||
496 | { | ||
497 | struct mm_struct *mm = current->mm; | ||
498 | return install_special_mapping(mm, 0xffff0000, PAGE_SIZE, | ||
499 | VM_READ | VM_EXEC | | ||
500 | VM_MAYREAD | VM_MAYEXEC | | ||
501 | VM_ALWAYSDUMP | VM_RESERVED, | ||
502 | NULL); | ||
503 | } | ||
504 | |||
505 | const char *arch_vma_name(struct vm_area_struct *vma) | ||
506 | { | ||
507 | return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL; | ||
508 | } | ||
509 | #endif | ||