aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}