diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-10-01 03:02:11 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-10-01 03:02:11 -0400 |
commit | 95c632f4e4e6365a20397f4fd04dcf27aab02958 (patch) | |
tree | aacb57bca96a6cc58e8a194a95a72ce13cc2d833 | |
parent | 4ac86a6dcec1c3878de9747bf5a2aa4455be69e3 (diff) | |
parent | 7ba78053aacb89998a052843e3c56983c31d57f0 (diff) |
Merge remote-tracking branch 'tglx/x86/urgent' into x86/urgent
Pick up the WCHAN fixes from Thomas.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/kernel/process.c | 55 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 28 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 24 |
3 files changed, 55 insertions, 52 deletions
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 6d0e62ae8516..39e585a554b7 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -506,3 +506,58 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) | |||
506 | return randomize_range(mm->brk, range_end, 0) ? : mm->brk; | 506 | return randomize_range(mm->brk, range_end, 0) ? : mm->brk; |
507 | } | 507 | } |
508 | 508 | ||
509 | /* | ||
510 | * Called from fs/proc with a reference on @p to find the function | ||
511 | * which called into schedule(). This needs to be done carefully | ||
512 | * because the task might wake up and we might look at a stack | ||
513 | * changing under us. | ||
514 | */ | ||
515 | unsigned long get_wchan(struct task_struct *p) | ||
516 | { | ||
517 | unsigned long start, bottom, top, sp, fp, ip; | ||
518 | int count = 0; | ||
519 | |||
520 | if (!p || p == current || p->state == TASK_RUNNING) | ||
521 | return 0; | ||
522 | |||
523 | start = (unsigned long)task_stack_page(p); | ||
524 | if (!start) | ||
525 | return 0; | ||
526 | |||
527 | /* | ||
528 | * Layout of the stack page: | ||
529 | * | ||
530 | * ----------- topmax = start + THREAD_SIZE - sizeof(unsigned long) | ||
531 | * PADDING | ||
532 | * ----------- top = topmax - TOP_OF_KERNEL_STACK_PADDING | ||
533 | * stack | ||
534 | * ----------- bottom = start + sizeof(thread_info) | ||
535 | * thread_info | ||
536 | * ----------- start | ||
537 | * | ||
538 | * The tasks stack pointer points at the location where the | ||
539 | * framepointer is stored. The data on the stack is: | ||
540 | * ... IP FP ... IP FP | ||
541 | * | ||
542 | * We need to read FP and IP, so we need to adjust the upper | ||
543 | * bound by another unsigned long. | ||
544 | */ | ||
545 | top = start + THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING; | ||
546 | top -= 2 * sizeof(unsigned long); | ||
547 | bottom = start + sizeof(struct thread_info); | ||
548 | |||
549 | sp = READ_ONCE(p->thread.sp); | ||
550 | if (sp < bottom || sp > top) | ||
551 | return 0; | ||
552 | |||
553 | fp = READ_ONCE(*(unsigned long *)sp); | ||
554 | do { | ||
555 | if (fp < bottom || fp > top) | ||
556 | return 0; | ||
557 | ip = READ_ONCE(*(unsigned long *)(fp + sizeof(unsigned long))); | ||
558 | if (!in_sched_functions(ip)) | ||
559 | return ip; | ||
560 | fp = READ_ONCE(*(unsigned long *)fp); | ||
561 | } while (count++ < 16 && p->state != TASK_RUNNING); | ||
562 | return 0; | ||
563 | } | ||
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index c13df2c735f8..737527b40e5b 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -324,31 +324,3 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
324 | 324 | ||
325 | return prev_p; | 325 | return prev_p; |
326 | } | 326 | } |
327 | |||
328 | #define top_esp (THREAD_SIZE - sizeof(unsigned long)) | ||
329 | #define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) | ||
330 | |||
331 | unsigned long get_wchan(struct task_struct *p) | ||
332 | { | ||
333 | unsigned long bp, sp, ip; | ||
334 | unsigned long stack_page; | ||
335 | int count = 0; | ||
336 | if (!p || p == current || p->state == TASK_RUNNING) | ||
337 | return 0; | ||
338 | stack_page = (unsigned long)task_stack_page(p); | ||
339 | sp = p->thread.sp; | ||
340 | if (!stack_page || sp < stack_page || sp > top_esp+stack_page) | ||
341 | return 0; | ||
342 | /* include/asm-i386/system.h:switch_to() pushes bp last. */ | ||
343 | bp = *(unsigned long *) sp; | ||
344 | do { | ||
345 | if (bp < stack_page || bp > top_ebp+stack_page) | ||
346 | return 0; | ||
347 | ip = *(unsigned long *) (bp+4); | ||
348 | if (!in_sched_functions(ip)) | ||
349 | return ip; | ||
350 | bp = *(unsigned long *) bp; | ||
351 | } while (count++ < 16); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 3c1bbcf12924..b35921a670b2 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -499,30 +499,6 @@ void set_personality_ia32(bool x32) | |||
499 | } | 499 | } |
500 | EXPORT_SYMBOL_GPL(set_personality_ia32); | 500 | EXPORT_SYMBOL_GPL(set_personality_ia32); |
501 | 501 | ||
502 | unsigned long get_wchan(struct task_struct *p) | ||
503 | { | ||
504 | unsigned long stack; | ||
505 | u64 fp, ip; | ||
506 | int count = 0; | ||
507 | |||
508 | if (!p || p == current || p->state == TASK_RUNNING) | ||
509 | return 0; | ||
510 | stack = (unsigned long)task_stack_page(p); | ||
511 | if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE) | ||
512 | return 0; | ||
513 | fp = *(u64 *)(p->thread.sp); | ||
514 | do { | ||
515 | if (fp < (unsigned long)stack || | ||
516 | fp >= (unsigned long)stack+THREAD_SIZE) | ||
517 | return 0; | ||
518 | ip = *(u64 *)(fp+8); | ||
519 | if (!in_sched_functions(ip)) | ||
520 | return ip; | ||
521 | fp = *(u64 *)fp; | ||
522 | } while (count++ < 16); | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | 502 | long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) |
527 | { | 503 | { |
528 | int ret = 0; | 504 | int ret = 0; |