[parisc-linux-cvs] linux-2.5 tausq
Randolph Chung
Randolph Chung <randolph@tausq.org>
Sun, 5 Jan 2003 22:06:52 -0800
> -pa3
> preliminary oprofile support; boots but not yet tested. 64-bit kernels are
> not well supported upstream
Here's the diff...
32-bit should work, although i don't have a setup to test it at the
moment. 64-bit kernel with 32-bit userspace is not supported upstream
yet, but that is more of a userspace tools problem than a kernel one.
Index: Makefile
===================================================================
RCS file: /var/cvs/linux-2.5/Makefile,v
retrieving revision 1.60
diff -u -p -r1.60 Makefile
--- Makefile 25 Dec 2002 00:39:09 -0000 1.60
+++ Makefile 6 Jan 2003 05:54:53 -0000
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 53
-EXTRAVERSION = -pa2
+EXTRAVERSION = -pa3
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
Index: arch/parisc/Kconfig
===================================================================
RCS file: /var/cvs/linux-2.5/arch/parisc/Kconfig,v
retrieving revision 1.11
diff -u -p -r1.11 Kconfig
--- arch/parisc/Kconfig 10 Dec 2002 22:01:55 -0000 1.11
+++ arch/parisc/Kconfig 6 Jan 2003 05:54:54 -0000
@@ -377,6 +377,8 @@ source "drivers/usb/Kconfig"
source "net/bluetooth/Kconfig"
+source "arch/parisc/oprofile/Kconfig"
+
menu "Kernel hacking"
config DEBUG_KERNEL
Index: arch/parisc/Makefile
===================================================================
RCS file: /var/cvs/linux-2.5/arch/parisc/Makefile,v
retrieving revision 1.17
diff -u -p -r1.17 Makefile
--- arch/parisc/Makefile 5 Nov 2002 19:38:52 -0000 1.17
+++ arch/parisc/Makefile 6 Jan 2003 05:54:54 -0000
@@ -82,6 +82,9 @@ core-y += arch/parisc/kernel/pdc_con
libs-y += arch/parisc/lib/ \
`$(CC) -print-libgcc-file-name`
+# FIXME: is drivers- right ?
+drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/
+
palo: vmlinux
@if [ $$(palo -f /dev/null >/dev/null 2>&1 ; echo $$?) != 2 ]; then \
echo 'ERROR: Please install palo first (apt-get install palo)';\
Index: arch/parisc/kernel/Makefile
===================================================================
RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/Makefile,v
retrieving revision 1.16
diff -u -p -r1.16 Makefile
--- arch/parisc/kernel/Makefile 30 Nov 2002 05:48:59 -0000 1.16
+++ arch/parisc/kernel/Makefile 6 Jan 2003 05:54:54 -0000
@@ -20,6 +20,7 @@ obj-y := cache.o pacache.o setup.o
processor.o pdc_chassis.o
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_PROFILING) += profile.o
obj-$(CONFIG_PA11) += pci-dma.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_MODULES) += module.o
Index: arch/parisc/kernel/parisc_ksyms.c
===================================================================
RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/parisc_ksyms.c,v
retrieving revision 1.11
diff -u -p -r1.11 parisc_ksyms.c
--- arch/parisc/kernel/parisc_ksyms.c 21 Nov 2002 21:50:53 -0000 1.11
+++ arch/parisc/kernel/parisc_ksyms.c 6 Jan 2003 05:54:54 -0000
@@ -211,5 +211,10 @@ extern void $$dyncall(void);
EXPORT_SYMBOL_NOVERS($$dyncall);
#endif
+#ifdef CONFIG_PROFILING
+EXPORT_SYMBOL_GPL(register_profile_notifier);
+EXPORT_SYMBOL_GPL(unregister_profile_notifier);
+#endif
+
#include <asm/pgtable.h>
EXPORT_SYMBOL_NOVERS(vmalloc_start);
Index: arch/parisc/kernel/profile.c
===================================================================
RCS file: arch/parisc/kernel/profile.c
diff -N arch/parisc/kernel/profile.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/parisc/kernel/profile.c 6 Jan 2003 05:54:54 -0000
@@ -0,0 +1,43 @@
+/* arch/parisc/kernel/profile.c
+ *
+ * Almost entirely copied from ppc64 which is:
+ * (C) 2002 John Levon <levon@movementarian.org>
+ */
+
+#include <linux/profile.h>
+#include <linux/spinlock.h>
+#include <linux/notifier.h>
+#include <asm/irq.h>
+
+static struct notifier_block *profile_listeners;
+static rwlock_t profile_lock = RW_LOCK_UNLOCKED;
+
+int register_profile_notifier(struct notifier_block *nb)
+{
+ int err;
+
+ write_lock_irq(&profile_lock);
+ err = notifier_chain_register(&profile_listeners, nb);
+ write_unlock_irq(&profile_lock);
+
+ return err;
+}
+
+int unregister_profile_notifier(struct notifier_block *nb)
+{
+ int err;
+
+ write_lock_irq(&profile_lock);
+ err = notifier_chain_unregister(&profile_listeners, nb);
+ write_unlock_irq(&profile_lock);
+
+ return err;
+}
+
+void parisc_profile_hook(struct pt_regs *regs)
+{
+ read_lock(&profile_lock);
+ notifier_call_chain(&profile_listeners, 0, regs);
+ read_unlock(&profile_lock);
+}
+
Index: arch/parisc/kernel/time.c
===================================================================
RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/time.c,v
retrieving revision 1.6
diff -u -p -r1.6 time.c
--- arch/parisc/kernel/time.c 21 Oct 2002 15:30:32 -0000 1.6
+++ arch/parisc/kernel/time.c 6 Jan 2003 05:54:54 -0000
@@ -46,13 +46,29 @@ extern void smp_do_timer(struct pt_regs
#endif
static inline void
-parisc_do_profile(unsigned long pc)
+parisc_do_profile(struct pt_regs *regs)
{
+ unsigned long pc = regs->iaoq[0];
+ extern unsigned long prof_cpu_mask;
extern char _stext;
+#ifdef CONFIG_PROFILING
+ extern void parisc_profile_hook(struct pt_regs *);
+
+ parisc_profile_hook(regs);
+#endif
+
+ if (user_mode(regs))
+ return;
+
if (!prof_buffer)
return;
+#if 0
+ if (!((1 << smp_processor_id()) & prof_cpu_mask))
+ return;
+#endif
+
pc -= (unsigned long) &_stext;
pc >>= prof_shift;
/*
@@ -67,13 +83,15 @@ parisc_do_profile(unsigned long pc)
void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- long now = mfctl(16);
+ long now;
long next_tick;
int nticks;
int cpu = smp_processor_id();
- /* initialize next_tick to time at last clocktick */
+ parisc_do_profile(regs);
+ now = mfctl(16);
+ /* initialize next_tick to time at last clocktick */
next_tick = cpu_data[cpu].it_value;
/* since time passes between the interrupt and the mfctl()
@@ -98,13 +116,6 @@ void timer_interrupt(int irq, void *dev_
#endif
if (cpu == 0) {
write_lock(&xtime_lock);
-#ifndef CONFIG_SMP
- extern int pc_in_user_space;
- if (!user_mode(regs))
- parisc_do_profile(regs->iaoq[0]);
- else
- parisc_do_profile((unsigned long)&pc_in_user_space);
-#endif
do_timer(regs);
write_unlock(&xtime_lock);
}
@@ -240,3 +251,4 @@ void __init time_init(void)
xtime.tv_nsec = 0;
}
}
+
Index: arch/parisc/oprofile/Kconfig
===================================================================
RCS file: arch/parisc/oprofile/Kconfig
diff -N arch/parisc/oprofile/Kconfig
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/parisc/oprofile/Kconfig 6 Jan 2003 05:54:54 -0000
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+ depends on EXPERIMENTAL
+
+config PROFILING
+ bool "Profiling support (EXPERIMENTAL)"
+ help
+ Say Y here to enable the extended profiling support mechanisms used
+ by profilers such as OProfile.
+
+
+config OPROFILE
+ tristate "OProfile system profiling (EXPERIMENTAL)"
+ depends on PROFILING
+ help
+ OProfile is a profiling system capable of profiling the
+ whole system, include the kernel, kernel modules, libraries,
+ and applications.
+
+ If unsure, say N.
+
+endmenu
+
Index: arch/parisc/oprofile/Makefile
===================================================================
RCS file: arch/parisc/oprofile/Makefile
diff -N arch/parisc/oprofile/Makefile
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/parisc/oprofile/Makefile 6 Jan 2003 05:54:54 -0000
@@ -0,0 +1,8 @@
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+ oprof.o cpu_buffer.o buffer_sync.o \
+ event_buffer.o oprofile_files.o \
+ oprofilefs.o oprofile_stats.o )
+
+oprofile-y := $(DRIVER_OBJS) init.o timer_int.o
Index: arch/parisc/oprofile/init.c
===================================================================
RCS file: arch/parisc/oprofile/init.c
diff -N arch/parisc/oprofile/init.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/parisc/oprofile/init.c 6 Jan 2003 05:54:54 -0000
@@ -0,0 +1,20 @@
+/**
+ * @file init.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/oprofile.h>
+#include <linux/init.h>
+
+extern void timer_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu);
+
+int __init oprofile_arch_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu)
+{
+ timer_init(ops, cpu);
+ return 0;
+}
Index: arch/parisc/oprofile/timer_int.c
===================================================================
RCS file: arch/parisc/oprofile/timer_int.c
diff -N arch/parisc/oprofile/timer_int.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/parisc/oprofile/timer_int.c 6 Jan 2003 05:54:54 -0000
@@ -0,0 +1,56 @@
+/**
+ * @file timer_int.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/smp.h>
+#include <linux/irq.h>
+#include <linux/oprofile.h>
+#include <asm/ptrace.h>
+
+static int timer_notify(struct notifier_block * self, unsigned long val, void * data)
+{
+ struct pt_regs * regs = (struct pt_regs *)data;
+ int cpu = smp_processor_id();
+
+ oprofile_add_sample(regs->iaoq[0], 0, cpu);
+ return 0;
+}
+
+
+static struct notifier_block timer_notifier = {
+ .notifier_call = timer_notify,
+};
+
+
+static int timer_start(void)
+{
+ return register_profile_notifier(&timer_notifier);
+}
+
+
+static void timer_stop(void)
+{
+ unregister_profile_notifier(&timer_notifier);
+}
+
+
+static struct oprofile_operations timer_ops = {
+ .start = timer_start,
+ .stop = timer_stop
+};
+
+
+void __init timer_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu)
+{
+ *ops = &timer_ops;
+ *cpu = OPROFILE_CPU_TIMER;
+ printk(KERN_INFO "oprofile: using timer interrupt.\n");
+}
Index: include/asm-parisc/irq.h
===================================================================
RCS file: /var/cvs/linux-2.5/include/asm-parisc/irq.h,v
retrieving revision 1.3
diff -u -p -r1.3 irq.h
--- include/asm-parisc/irq.h 20 Jul 2002 15:52:25 -0000 1.3
+++ include/asm-parisc/irq.h 6 Jan 2003 05:54:59 -0000
@@ -94,4 +94,21 @@ extern unsigned long txn_alloc_addr(int)
/* soft power switch support (power.c) */
extern struct tasklet_struct power_tasklet;
+struct notifier_block;
+
+#ifdef CONFIG_PROFILING
+int register_profile_notifier(struct notifier_block *nb);
+int unregister_profile_notifier(struct notifier_block *nb);
+#else
+static inline int register_profile_notifier(struct notifier_block *nb)
+{
+ return -ENOSYS;
+}
+
+static inline int unregister_profile_notifier(struct notifier_block *nb)
+{
+ return -ENOSYS;
+}
+#endif
+
#endif /* _ASM_PARISC_IRQ_H */
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/