[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>
This commit is contained in:
parent
0cb91a2293
commit
31679f38d8
1 changed files with 8 additions and 13 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Reference in a new issue