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) |