]> err.no Git - linux-2.6/commitdiff
[PATCH] Simplify profile_pc on x86-64
authorAndi Kleen <ak@suse.de>
Tue, 26 Sep 2006 08:52:28 +0000 (10:52 +0200)
committerAndi Kleen <andi@basil.nowhere.org>
Tue, 26 Sep 2006 08:52:28 +0000 (10:52 +0200)
Use knowledge about EFLAGS layout (bits 22:63 are always 0) to distingush
EFLAGS word and kernel address in the spin lock stack frame.

Signed-off-by: Andi Kleen <ak@suse.de>
arch/x86_64/kernel/time.c

index 560ed944dc0e304aa9831895ab7b43799f28f033..ea00915d393a74a337c9867556370ea7d95e08c8 100644 (file)
@@ -189,20 +189,15 @@ unsigned long profile_pc(struct pt_regs *regs)
 {
        unsigned long pc = instruction_pointer(regs);
 
-       /* Assume the lock function has either no stack frame or only a single 
-          word.  This checks if the address on the stack looks like a kernel 
-          text address.
-          There is a small window for false hits, but in that case the tick
-          is just accounted to the spinlock function.
-          Better would be to write these functions in assembler again
-          and check exactly. */
+       /* Assume the lock function has either no stack frame or a copy
+          of eflags from PUSHF
+          Eflags always has bits 22 and up cleared unlike kernel addresses. */
        if (!user_mode(regs) && in_lock_functions(pc)) {
-               char *v = *(char **)regs->rsp;
-               if ((v >= _stext && v <= _etext) ||
-                       (v >= _sinittext && v <= _einittext) ||
-                       (v >= (char *)MODULES_VADDR  && v <= (char *)MODULES_END))
-                       return (unsigned long)v;
-               return ((unsigned long *)regs->rsp)[1];
+               unsigned long *sp = (unsigned long *)regs->rsp;
+               if (sp[0] >> 22)
+                       return sp[0];
+               if (sp[1] >> 22)
+                       return sp[1];
        }
        return pc;
 }