aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-09-26 04:52:28 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:28 -0400
commit31679f38d88696ed032d59e457f1605c97e7d719 (patch)
tree901c0e9a3ce8696a1c0560c53edde36a85db9aa6 /arch/x86_64
parent0cb91a2293648507886563ccb91979cfc94d6a4b (diff)
[PATCH] Simplify profile_pc on x86-64
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>
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/kernel/time.c21
1 files changed, 8 insertions, 13 deletions
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 560ed944dc0e..ea00915d393a 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -189,20 +189,15 @@ unsigned long profile_pc(struct pt_regs *regs)
189{ 189{
190 unsigned long pc = instruction_pointer(regs); 190 unsigned long pc = instruction_pointer(regs);
191 191
192 /* Assume the lock function has either no stack frame or only a single 192 /* Assume the lock function has either no stack frame or a copy
193 word. This checks if the address on the stack looks like a kernel 193 of eflags from PUSHF
194 text address. 194 Eflags always has bits 22 and up cleared unlike kernel addresses. */
195 There is a small window for false hits, but in that case the tick
196 is just accounted to the spinlock function.
197 Better would be to write these functions in assembler again
198 and check exactly. */
199 if (!user_mode(regs) && in_lock_functions(pc)) { 195 if (!user_mode(regs) && in_lock_functions(pc)) {
200 char *v = *(char **)regs->rsp; 196 unsigned long *sp = (unsigned long *)regs->rsp;
201 if ((v >= _stext && v <= _etext) || 197 if (sp[0] >> 22)
202 (v >= _sinittext && v <= _einittext) || 198 return sp[0];
203 (v >= (char *)MODULES_VADDR && v <= (char *)MODULES_END)) 199 if (sp[1] >> 22)
204 return (unsigned long)v; 200 return sp[1];
205 return ((unsigned long *)regs->rsp)[1];
206 } 201 }
207 return pc; 202 return pc;
208} 203}