[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/