Skip to contentSkip to conversation

Patch "ARC: make sure instruction_pointer() returns unsigned value" has been added to the 3.10-stable tree

PATCH [email protected] 1 participant 1 message Aug 7, 2015

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

ARC: make sure instruction_pointer() returns unsigned value

to the 3.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
arc-make-sure-instruction_pointer-returns-unsigned-value.patch
and it can be found in the queue-3.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From f51e2f1911122879eefefa4c592dea8bf794b39c Mon Sep 17 00:00:00 2001

From: Alexey Brodkin <[email protected]>
Date: Mon, 13 Jul 2015 10:25:17 +0300
Subject: ARC: make sure instruction_pointer() returns unsigned value

From: Alexey Brodkin <[email protected]>

commit f51e2f1911122879eefefa4c592dea8bf794b39c upstream.

Currently instruction_pointer() returns pt_regs->ret and so return value is of type "long", which implicitly stands for "signed long".

While that's perfectly fine when dealing with 32-bit values if return value of instruction_pointer() gets assigned to 64-bit variable sign extension may happen.

And at least in one real use-case it happens already.
In perf_prepare_sample() return value of perf_instruction_pointer() (which is an alias to instruction_pointer() in case of ARC) is assigned to (struct perf_sample_data)->ip (which type is "u64").

And what we see if instuction pointer points to user-space application that in case of ARC lays below 0x8000_0000 "ip" gets set properly with leading 32 zeros. But if instruction pointer points to kernel address space that starts from 0x8000_0000 then "ip" is set with 32 leadig "f"-s. I.e. id instruction_pointer() returns 0x8100_0000, "ip" will be assigned with 0xffff_ffff__8100_0000. Which is obviously wrong.

In particular that issuse broke output of perf, because perf was unable to associate addresses like 0xffff_ffff__8100_0000 with anything from /proc/kallsyms.

That's what we used to see:
----------->8----------

  6.27%  ls       [unknown]                [k] 0xffffffff8046c5cc
  2.96%  ls       libuClibc-0.9.34-git.so  [.] memcpy
  2.25%  ls       libuClibc-0.9.34-git.so  [.] memset
  1.66%  ls       [unknown]                [k] 0xffffffff80666536
  1.54%  ls       libuClibc-0.9.34-git.so  [.] 0x000224d6
  1.18%  ls       libuClibc-0.9.34-git.so  [.] 0x00022472

----------->8----------

With that change perf output looks much better now:
----------->8----------

  8.21%  ls       [kernel.kallsyms]        [k] memset
  3.52%  ls       libuClibc-0.9.34-git.so  [.] memcpy
  2.11%  ls       libuClibc-0.9.34-git.so  [.] malloc
  1.88%  ls       libuClibc-0.9.34-git.so  [.] memset
  1.64%  ls       [kernel.kallsyms]        [k] _raw_spin_unlock_irqrestore
  1.41%  ls       [kernel.kallsyms]        [k] __d_lookup_rcu

----------->8----------

---
 arch/arc/include/asm/ptrace.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arc/include/asm/ptrace.h +1 -1
@@ -83,7 +83,7 @@ struct callee_regs {
 	long r13;
 };
 
-#define instruction_pointer(regs)	((regs)->ret)
+#define instruction_pointer(regs)	(unsigned long)((regs)->ret)
 #define profile_pc(regs)		instruction_pointer(regs)
 
 /* return 1 if user mode or 0 if kernel mode */

Patches currently in stable-queue which might be from [email protected] are

queue-3.10/arc-make-sure-instruction_pointer-returns-unsigned-value.patch