Commit 6d8c651a authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: oprofile for s390

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

Add oprofile support for s/390.
parent eff7461e
......@@ -368,6 +368,7 @@ source "net/Kconfig"
source "fs/Kconfig"
source "arch/s390/oprofile/Kconfig"
menu "Kernel hacking"
......
......@@ -50,6 +50,9 @@ libs-y += arch/$(ARCH)/lib/
drivers-y += drivers/s390/
drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/
# must be linked after kernel
drivers-$(CONFIG_OPROFILE) += arch/s390/oprofile/
boot := arch/$(ARCH)/boot
all: image
......
......@@ -463,6 +463,11 @@ CONFIG_MSDOS_PARTITION=y
#
# CONFIG_NLS is not set
#
# Profiling support
#
# CONFIG_PROFILING is not set
#
# Kernel hacking
#
......
......@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional
obj-y := bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
semaphore.o s390_ext.o debug.o
semaphore.o s390_ext.o debug.o profile.o
extra-$(CONFIG_ARCH_S390_31) += head.o
extra-$(CONFIG_ARCH_S390X) += head64.o
......
......@@ -1234,6 +1234,14 @@ sys_epoll_wait_wrapper:
lgfr %r5,%r5 # int
jg sys_epoll_wait # branch to system call
.globl sys32_lookup_dcookie_wrapper
sys32_lookup_dcookie_wrapper:
sllg %r2,%r2,32 # get high word of 64bit dcookie
or %r2,%r3 # get low word of 64bit dcookie
llgtr %r3,%r4 # char *
llgfr %r4,%r5 # size_t
jg sys_lookup_dcookie
.globl sys32_fadvise64_wrapper
sys32_fadvise64_wrapper:
lgfr %r2,%r2 # int
......
/*
* arch/s390/kernel/profile.c
*
* Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Thomas Spatzier (tspat@de.ibm.com)
*
*/
#include <linux/proc_fs.h>
static struct proc_dir_entry * root_irq_dir;
static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
if (count - len < 2)
return -EINVAL;
len += sprintf(page + len, "\n");
return len;
}
static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
unsigned long count, void *data)
{
cpumask_t *mask = (cpumask_t *)data;
unsigned long full_count = count, err;
cpumask_t new_value;
err = cpumask_parse(buffer, count, new_value);
if (err)
return err;
*mask = new_value;
return full_count;
}
cpumask_t prof_cpu_mask = CPU_MASK_ALL;
void init_irq_proc(void)
{
struct proc_dir_entry *entry;
/* create /proc/irq */
root_irq_dir = proc_mkdir("irq", 0);
/* create /proc/irq/prof_cpu_mask */
entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
if (!entry)
return;
entry->nlink = 1;
entry->data = (void *)&prof_cpu_mask;
entry->read_proc = prof_cpu_mask_read_proc;
entry->write_proc = prof_cpu_mask_write_proc;
}
......@@ -118,7 +118,7 @@ SYSCALL(sys_newstat,sys_newstat,compat_sys_newstat_wrapper)
SYSCALL(sys_newlstat,sys_newlstat,compat_sys_newlstat_wrapper)
SYSCALL(sys_newfstat,sys_newfstat,compat_sys_newfstat_wrapper)
NI_SYSCALL /* old uname syscall */
NI_SYSCALL /* reserved for sys_lookup_dcache */
SYSCALL(sys_lookup_dcookie,sys_lookup_dcookie,sys32_lookup_dcookie_wrapper) /* 110 */
SYSCALL(sys_vhangup,sys_vhangup,sys_vhangup)
NI_SYSCALL /* old "idle" system call */
NI_SYSCALL /* vm86old for i386 */
......
......@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/types.h>
#include <linux/profile.h>
#include <linux/timex.h>
#include <linux/config.h>
......@@ -177,6 +178,54 @@ __calculate_ticks(__u64 elapsed)
#endif /* CONFIG_ARCH_S390X */
#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE)
extern char _stext, _etext;
/*
* The profiling function is SMP safe. (nothing can mess
* around with "current", and the profiling counters are
* updated with atomic operations). This is especially
* useful with a profiling multiplier != 1
*/
static inline void s390_do_profile(struct pt_regs * regs)
{
unsigned long eip;
extern cpumask_t prof_cpu_mask;
profile_hook(regs);
if (user_mode(regs))
return;
if (!prof_buffer)
return;
eip = instruction_pointer(regs);
/*
* Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
* (default is all CPUs.)
*/
if (!cpu_isset(smp_processor_id(), prof_cpu_mask))
return;
eip -= (unsigned long) &_stext;
eip >>= prof_shift;
/*
* Don't ignore out-of-bounds EIP values silently,
* put them into the last histogram slot, so if
* present, they will show up as a sharp peak.
*/
if (eip > prof_len-1)
eip = prof_len-1;
atomic_inc((atomic_t *)&prof_buffer[eip]);
}
#else
#define s390_do_profile(regs) do { ; } while(0)
#endif /* CONFIG_OPROFILE */
/*
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
......@@ -231,6 +280,7 @@ void account_ticks(struct pt_regs *regs)
while (ticks--)
do_timer(regs);
#endif
s390_do_profile(regs);
}
#ifdef CONFIG_VIRT_TIMER
......
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
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 \
timer_int.o )
oprofile-y := $(DRIVER_OBJS) init.o
/**
* arch/s390/oprofile/init.c
*
* S390 Version
* Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Thomas Spatzier (tspat@de.ibm.com)
*
* @remark Copyright 2002 OProfile authors
*/
#include <linux/oprofile.h>
#include <linux/init.h>
#include <linux/errno.h>
//extern int irq_init(struct oprofile_operations** ops);
extern void timer_init(struct oprofile_operations** ops);
int __init oprofile_arch_init(struct oprofile_operations** ops)
{
timer_init(ops);
return 0;
}
void oprofile_arch_exit(void)
{
}
......@@ -52,15 +52,6 @@ cio_setup (char *parm)
__setup ("cio_msg=", cio_setup);
#ifdef CONFIG_PROC_FS
void
init_irq_proc(void)
{
/* For now, nothing... */
}
#endif
/*
* Function: cio_debug_init
* Initializes three debug logs (under /proc/s390dbf) for common I/O:
......
......@@ -105,6 +105,7 @@
#define __NR_stat 106
#define __NR_lstat 107
#define __NR_fstat 108
#define __NR_lookup_dcookie 110
#define __NR_vhangup 111
#define __NR_idle 112
#define __NR_wait4 114
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment