diff options
| -rw-r--r-- | arch/x86/kernel/time_32.c | 13 | ||||
| -rw-r--r-- | arch/x86/kernel/time_64.c | 8 |
2 files changed, 11 insertions, 10 deletions
diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c index fd876cc77487..fda0c34da757 100644 --- a/arch/x86/kernel/time_32.c +++ b/arch/x86/kernel/time_32.c | |||
| @@ -34,23 +34,22 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
| 34 | { | 34 | { |
| 35 | unsigned long pc = instruction_pointer(regs); | 35 | unsigned long pc = instruction_pointer(regs); |
| 36 | 36 | ||
| 37 | #ifdef CONFIG_SMP | ||
| 38 | if (!user_mode_vm(regs) && in_lock_functions(pc)) { | 37 | if (!user_mode_vm(regs) && in_lock_functions(pc)) { |
| 39 | #ifdef CONFIG_FRAME_POINTER | 38 | #ifdef CONFIG_FRAME_POINTER |
| 40 | return *(unsigned long *)(regs->bp + sizeof(long)); | 39 | return *(unsigned long *)(regs->bp + sizeof(long)); |
| 41 | #else | 40 | #else |
| 42 | unsigned long *sp = (unsigned long *)®s->sp; | 41 | unsigned long *sp = (unsigned long *)regs->sp; |
| 43 | 42 | /* | |
| 44 | /* Return address is either directly at stack pointer | 43 | * Return address is either directly at stack pointer |
| 45 | or above a saved flags. Eflags has bits 22-31 zero, | 44 | * or above a saved flags. Eflags has bits 22-31 zero, |
| 46 | kernel addresses don't. */ | 45 | * kernel addresses don't. |
| 46 | */ | ||
| 47 | if (sp[0] >> 22) | 47 | if (sp[0] >> 22) |
| 48 | return sp[0]; | 48 | return sp[0]; |
| 49 | if (sp[1] >> 22) | 49 | if (sp[1] >> 22) |
| 50 | return sp[1]; | 50 | return sp[1]; |
| 51 | #endif | 51 | #endif |
| 52 | } | 52 | } |
| 53 | #endif | ||
| 54 | return pc; | 53 | return pc; |
| 55 | } | 54 | } |
| 56 | EXPORT_SYMBOL(profile_pc); | 55 | EXPORT_SYMBOL(profile_pc); |
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c index e59a40ebff14..fda0c34da757 100644 --- a/arch/x86/kernel/time_64.c +++ b/arch/x86/kernel/time_64.c | |||
| @@ -34,14 +34,16 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
| 34 | { | 34 | { |
| 35 | unsigned long pc = instruction_pointer(regs); | 35 | unsigned long pc = instruction_pointer(regs); |
| 36 | 36 | ||
| 37 | /* Assume the lock function has either no stack frame or a copy | ||
| 38 | of flags from PUSHF | ||
| 39 | Eflags always has bits 22 and up cleared unlike kernel addresses. */ | ||
| 40 | if (!user_mode_vm(regs) && in_lock_functions(pc)) { | 37 | if (!user_mode_vm(regs) && in_lock_functions(pc)) { |
| 41 | #ifdef CONFIG_FRAME_POINTER | 38 | #ifdef CONFIG_FRAME_POINTER |
| 42 | return *(unsigned long *)(regs->bp + sizeof(long)); | 39 | return *(unsigned long *)(regs->bp + sizeof(long)); |
| 43 | #else | 40 | #else |
| 44 | unsigned long *sp = (unsigned long *)regs->sp; | 41 | unsigned long *sp = (unsigned long *)regs->sp; |
| 42 | /* | ||
| 43 | * Return address is either directly at stack pointer | ||
| 44 | * or above a saved flags. Eflags has bits 22-31 zero, | ||
| 45 | * kernel addresses don't. | ||
| 46 | */ | ||
| 45 | if (sp[0] >> 22) | 47 | if (sp[0] >> 22) |
| 46 | return sp[0]; | 48 | return sp[0]; |
| 47 | if (sp[1] >> 22) | 49 | if (sp[1] >> 22) |
