#include <asm/timex.h>
#include <asm/proto.h>
#include <asm/hpet.h>
+#include <asm/sections.h>
#include <linux/cpufreq.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/apic.h>
EXPORT_SYMBOL(do_settimeofday);
-#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
unsigned long profile_pc(struct pt_regs *regs)
{
unsigned long pc = instruction_pointer(regs);
- if (in_lock_functions(pc))
- return *(unsigned long *)regs->rbp;
+ /* 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. */
+ if (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];
+ }
return pc;
}
EXPORT_SYMBOL(profile_pc);
-#endif
/*
* In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
#define user_mode(regs) (!!((regs)->cs & 3))
#define instruction_pointer(regs) ((regs)->rip)
-#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
extern unsigned long profile_pc(struct pt_regs *regs);
-#else
-#define profile_pc(regs) instruction_pointer(regs)
-#endif
void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
enum {