]> git.hungrycats.org Git - linux/commitdiff
[PATCH] introduce profile_pc()
authorWilliam Lee Irwin III <wli@holomorphy.com>
Fri, 27 Aug 2004 03:31:20 +0000 (20:31 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 27 Aug 2004 03:31:20 +0000 (20:31 -0700)
The program counter calculation from pt_regs is the only portion of profile
accounting that differs across various architectures.  This is usually
instruction_pointer(regs), but to handle the few arches where it isn't,
introduce profile_pc().

Signed-off-by: William Irwin <wli@holomorphy.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
27 files changed:
arch/ia64/kernel/time.c
arch/sh/kernel/time.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc/kernel/time.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/time.c
include/asm-alpha/ptrace.h
include/asm-arm/ptrace.h
include/asm-arm26/ptrace.h
include/asm-cris/arch-v10/ptrace.h
include/asm-h8300/ptrace.h
include/asm-i386/ptrace.h
include/asm-ia64/ptrace.h
include/asm-m68k/ptrace.h
include/asm-m68knommu/ptrace.h
include/asm-mips/ptrace.h
include/asm-parisc/ptrace.h
include/asm-ppc/ptrace.h
include/asm-ppc64/ptrace.h
include/asm-s390/ptrace.h
include/asm-sh/ptrace.h
include/asm-sh64/ptrace.h
include/asm-sparc/ptrace.h
include/asm-sparc64/ptrace.h
include/asm-v850/ptrace.h
include/asm-x86_64/ptrace.h

index 837f172b61f0bfdf28f58a84e4b4124954407654..6421fd877868e8d7438d84db8905c1f3dec30917 100644 (file)
@@ -195,7 +195,7 @@ EXPORT_SYMBOL(do_gettimeofday);
 static inline void
 ia64_do_profile (struct pt_regs * regs)
 {
-       unsigned long ip, slot;
+       unsigned long ip;
 
        profile_hook(regs);
 
@@ -205,12 +205,10 @@ ia64_do_profile (struct pt_regs * regs)
        if (!prof_buffer)
                return;
 
-       ip = instruction_pointer(regs);
        /* Conserve space in histogram by encoding slot bits in address
         * bits 2 and 3 rather than bits 0 and 1.
         */
-       slot = ip & 3;
-       ip = (ip & ~3UL) + 4*slot;
+       ip = profile_pc(regs);
 
        /*
         * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
index b81bf1ff89b7a00f80998be6d57eb8713823e57d..514628fb54e386633d25153d5a5b30893ac263bc 100644 (file)
@@ -262,9 +262,6 @@ static inline void sh_do_profile(unsigned long pc)
        if (!prof_buffer || !current->pid)
                return;
 
-       if (pc >= 0xa0000000UL && pc < 0xc0000000UL)
-               pc -= 0x20000000;
-
        pc -= (unsigned long)&_stext;
        pc >>= prof_shift;
 
@@ -288,7 +285,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
        do_timer(regs);
 
        if (!user_mode(regs))
-               sh_do_profile(regs->pc);
+               sh_do_profile(profile_pc(regs));
 
 #ifdef CONFIG_HEARTBEAT
        if (sh_mv.mv_heartbeat != NULL) 
index 751b551da2b084475cea2544d74447ca844bab8d..287a99f118910ba1548acd6fbb1c8c2283a9e3ce 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
+#include <linux/profile.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
index 0975885dbb788312906484f72ed5b7ec06502d45..94b1f250b40361bca4b93da5d5775da212ecdab7 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
+#include <linux/profile.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
index bdec61be6f777e32ce935d5de86bebcdf1d08313..21eb301bebfbe8847c0429193d5402c4ab383d73 100644 (file)
@@ -79,6 +79,26 @@ struct intersil *intersil_clock;
 
 #endif
 
+unsigned long profile_pc(struct pt_regs *regs)
+{
+       extern int __copy_user_begin, __copy_user_end;
+       extern int __atomic_begin, __atomic_end;
+       extern int __bzero_begin, __bzero_end;
+       extern int __bitops_begin, __bitops_end;
+       unsigned long pc = regs->pc;
+
+       if ((pc >= (unsigned long) &__copy_user_begin &&
+            pc < (unsigned long) &__copy_user_end) ||
+           (pc >= (unsigned long) &__atomic_begin &&
+            pc < (unsigned long) &__atomic_end) ||
+           (pc >= (unsigned long) &__bzero_begin &&
+            pc < (unsigned long) &__bzero_end) ||
+           (pc >= (unsigned long) &__bitops_begin &&
+            pc < (unsigned long) &__bitops_end))
+               pc = regs->u_regs[UREG_RETPC];
+       return pc;
+}
+
 static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
 
 /* 32-bit Sparc specific profiling function. */
@@ -86,20 +106,6 @@ void sparc_do_profile(unsigned long pc, unsigned long o7)
 {
        if(prof_buffer && current->pid) {
                extern int _stext;
-               extern int __copy_user_begin, __copy_user_end;
-               extern int __atomic_begin, __atomic_end;
-               extern int __bzero_begin, __bzero_end;
-               extern int __bitops_begin, __bitops_end;
-
-               if ((pc >= (unsigned long) &__copy_user_begin &&
-                    pc < (unsigned long) &__copy_user_end) ||
-                   (pc >= (unsigned long) &__atomic_begin &&
-                    pc < (unsigned long) &__atomic_end) ||
-                   (pc >= (unsigned long) &__bzero_begin &&
-                    pc < (unsigned long) &__bzero_end) ||
-                   (pc >= (unsigned long) &__bitops_begin &&
-                    pc < (unsigned long) &__bitops_end))
-                       pc = o7;
 
                pc -= (unsigned long) &_stext;
                pc >>= prof_shift;
@@ -130,7 +136,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 
 #ifndef CONFIG_SMP
        if(!user_mode(regs))
-               sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+               sparc_do_profile(profile_pc(regs));
 #endif
 
        /* Protect counter clear so that do_gettimeoffset works */
index fd36facd91749ff344fcf2ed0ae6a6ff6c041824..d7f9d6d1490edc64dacf37880a805fdb0d95afb1 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/seq_file.h>
 #include <linux/cache.h>
 #include <linux/jiffies.h>
+#include <linux/profile.h>
 
 #include <asm/head.h>
 #include <asm/ptrace.h>
index f961a0d3b1290a412be5de381bb1508172e1c906..c0260e26ef9232051d0861117abb411038facdb6 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/jiffies.h>
 #include <linux/cpufreq.h>
 #include <linux/percpu.h>
+#include <linux/profile.h>
 
 #include <asm/oplib.h>
 #include <asm/mostek.h>
@@ -453,14 +454,8 @@ void sparc64_do_profile(struct pt_regs *regs)
        if (!prof_buffer)
                return;
 
-       pc = regs->tpc;
-
-       pc -= (unsigned long) _stext;
-       pc >>= prof_shift;
-
-       if(pc >= prof_len)
-               pc = prof_len - 1;
-       atomic_inc((atomic_t *)&prof_buffer[pc]);
+       pc = (profile_pc(regs) - (unsigned long)_stext) >> prof_shift;
+       atomic_inc((atomic_t *)&prof_buffer[min(pc, prof_len-1)]);
 }
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
index e77230f32b45f1e2fba4988fb8c21c8728b61c4a..d462c5e14c13e4d227c76df4099cbb904650ea53 100644 (file)
@@ -69,6 +69,7 @@ struct switch_stack {
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->ps & 8) != 0)
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
 #define alpha_task_regs(task) \
index 162c456638dbb6854414e2c792c6f761704db4ce..0b270a32c588078329d34856c454b370b28c0df6 100644 (file)
@@ -130,6 +130,7 @@ static inline int valid_user_regs(struct pt_regs *regs)
 
 #define instruction_pointer(regs) \
        (pc_pointer((regs)->ARM_pc))
+#define profile_pc(regs) instruction_pointer(regs)
 
 #ifdef __KERNEL__
 extern void show_regs(struct pt_regs *);
index 05aa6e25f3cf78cc596a1fde4caeefcb661ef719..6a46b5ae1156087ce49eae960ab5455a6279de15 100644 (file)
@@ -30,6 +30,7 @@
 
 #define pc_pointer(v) ((v) & ~PCMASK)   /* convert v to pc type address */
 #define instruction_pointer(regs) (pc_pointer((regs)->ARM_pc)) /* get pc */
+#define profile_pc(regs) instruction_pointer(regs)
 
 /* this struct defines the way the registers are stored on the
    stack during a system call. */
index 939d9846477eed9a49619824c3913b971b810642..fb14c5ee37f94e342bfb865c35dac478ec024dec 100644 (file)
@@ -109,6 +109,7 @@ struct switch_stack {
 /* bit 8 is user-mode flag */
 #define user_mode(regs) (((regs)->dccr & 0x100) != 0)
 #define instruction_pointer(regs) ((regs)->irp)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
 #endif
index 5effc8d14b0d522b44933fe557adcfe516406cfe..c2e05e4b512ec5a915ab98d0550cc50da54ba515 100644 (file)
@@ -57,6 +57,7 @@ struct pt_regs {
 
 #define user_mode(regs) (!((regs)->ccr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
index d80fd6557d052167939ec925302ca64efac43d5a..0e6725c46a7be63ca3c4dbcc804bdfe1b4b571da 100644 (file)
@@ -57,6 +57,7 @@ struct pt_regs {
 #ifdef __KERNEL__
 #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
+#define profile_pc(regs) instruction_pointer(regs)
 #endif
 
 #endif
index 48398a30de812c14aaa865fb8126f887edd1bcee..2af819be15eaababf7158840de5b5b6787d4bdb2 100644 (file)
@@ -229,6 +229,15 @@ struct switch_stack {
  * the canonical representation by adding to instruction pointer.
  */
 # define instruction_pointer(regs) ((regs)->cr_iip + ia64_psr(regs)->ri)
+/* Conserve space in histogram by encoding slot bits in address
+ * bits 2 and 3 rather than bits 0 and 1.
+ */
+#define profile_pc(regs)                                               \
+({                                                                     \
+       unsigned long __ip = instruction_pointer(regs);                 \
+       (__ip & ~3UL) + ((__ip & 3UL) << 2);                            \
+})
+
   /* given a pointer to a task_struct, return the user's pt_regs */
 # define ia64_task_regs(t)             (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
 # define ia64_psr(regs)                        ((struct ia64_psr *) &(regs)->cr_ipsr)
index f62c54ea2c2151b8110156fb0d2fc34e8602fbf2..57e763d79bf4cbdacbb7fb346dc50e1562e8a9fa 100644 (file)
@@ -73,6 +73,7 @@ struct switch_stack {
 
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
index ac386868f6854ac6738f83ec70353319c883cf05..f65bd90749e69277ad60b380024b8a87e4cf136e 100644 (file)
@@ -84,6 +84,7 @@ struct switch_stack {
 
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
index 19cadb6579fdf2f9e0b0163827bfc57725025efe..2a090cf369b7600855fca4187893d45b9a4f354e 100644 (file)
@@ -66,6 +66,7 @@ struct pt_regs {
 #define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER)
 
 #define instruction_pointer(regs) ((regs)->cp0_epc)
+#define profile_pc(regs) instruction_pointer(regs)
 
 extern void show_regs(struct pt_regs *);
 
index 181fc75a0228ed11f658d29cfb8225a5d6e31a1d..c276c096c167e441268f1c90a5ce10839a0f3172 100644 (file)
@@ -48,6 +48,7 @@ struct pt_regs {
 /* XXX should we use iaoq[1] or iaoq[0] ? */
 #define user_mode(regs)                        (((regs)->iaoq[0] &  3) ? 1 : 0)
 #define instruction_pointer(regs)      ((regs)->iaoq[0] & ~3)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif
 
index 2576a7f90cd63ef91031c944db12a0b1fcc83abb..3e5920032fc36772dff795de292d84c2c6968b92 100644 (file)
@@ -47,6 +47,7 @@ struct pt_regs {
 
 #ifndef __ASSEMBLY__
 #define instruction_pointer(regs) ((regs)->nip)
+#define profile_pc(regs) instruction_pointer(regs)
 #define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
 
 #define force_successful_syscall_return()   \
index 2ec5d7bc43fc13993ba8549caecaef8a2af909ef..9fd93d7d0b15d18e1034c8918bdde3ab1080a1ab 100644 (file)
@@ -69,6 +69,7 @@ struct pt_regs32 {
 #define __SIGNAL_FRAMESIZE32   64
 
 #define instruction_pointer(regs) ((regs)->nip)
+#define profile_pc(regs) instruction_pointer(regs)
 #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
 
 #define force_successful_syscall_return()   \
index fe6e1e3112399627b2a26b1807a00444eebd57e6..1dc80666e97e86d8834241397cf24fb30577f41a 100644 (file)
@@ -466,6 +466,7 @@ struct user_regs_struct
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs * regs);
 #endif
 
index d0ca02c926bf0b45a173f898f4981f0148ab00df..0f75e16a74150ec04eabc711c702fc2d12436fc6 100644 (file)
@@ -90,6 +90,15 @@ struct pt_dspregs {
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
 extern void show_regs(struct pt_regs *);
+
+static inline unsigned long profile_pc(struct pt_regs *regs)
+{
+       unsigned long pc = instruction_pointer(regs);
+
+       if (pc >= 0xa0000000UL && pc < 0xc0000000UL)
+               pc -= 0x20000000;
+       return pc;
+}
 #endif
 
 #endif /* __ASM_SH_PTRACE_H */
index 56f836e1ce7899495188d2b5efe44ba7d5997ef7..56190f5215872af48c72c30e78a59e9169fe13db 100644 (file)
@@ -28,6 +28,7 @@ struct pt_regs {
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif
 
index 68ecd782599f84565c1988030c8e39460a56b1e4..dd9d94d7e0ae46ba28fdd88db3c7a1041eb4e6be 100644 (file)
@@ -62,6 +62,7 @@ struct sparc_stackf {
 #ifdef __KERNEL__
 #define user_mode(regs) (!((regs)->psr & PSR_PS))
 #define instruction_pointer(regs) ((regs)->pc)
+unsigned long profile_pc(struct pt_regs *);
 extern void show_regs(struct pt_regs *);
 #endif
 
index c679d2c213aaf4269743fbc91d465bb71d4f580f..7b6766770848b07e5baa9ea062dc5e8105205d4f 100644 (file)
@@ -98,6 +98,7 @@ struct sparc_trapf {
        set_thread_flag(TIF_SYSCALL_SUCCESS)
 #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
 #define instruction_pointer(regs) ((regs)->tpc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif
 
index 62b2b3822d88de41efecf80034d277fb5ac72353..7bf72bb5078cf122036cb47c220973022c0b11a0 100644 (file)
@@ -76,6 +76,7 @@ struct pt_regs
 
 
 #define instruction_pointer(regs)      ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 #define user_mode(regs)                        (!(regs)->kernel_mode)
 
 /* When a struct pt_regs is used to save user state for a system call in
index cbc19a7783c396ffdc5a4b3bf50a18ab4d06ec69..22ecea2759c89c74167be8d2bfde67711f209153 100644 (file)
@@ -83,6 +83,7 @@ struct pt_regs {
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 
 #define user_mode(regs) (!!((regs)->cs & 3))
 #define instruction_pointer(regs) ((regs)->rip)
+#define profile_pc(regs) instruction_pointer(regs)
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
 enum {