Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
This commit is contained in:
Linus Torvalds
2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

View File

@ -0,0 +1,26 @@
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.
Due to firmware bugs, you may need to use the "nohalt" boot
option if you're using OProfile with the hardware performance
counters.
If unsure, say N.
endmenu

View File

@ -0,0 +1,10 @@
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 backtrace.o
oprofile-$(CONFIG_PERFMON) += perfmon.o

View File

@ -0,0 +1,150 @@
/**
* @file backtrace.c
*
* @remark Copyright 2004 Silicon Graphics Inc. All Rights Reserved.
* @remark Read the file COPYING
*
* @author Greg Banks <gnb@melbourne.sgi.com>
* @author Keith Owens <kaos@melbourne.sgi.com>
* Based on work done for the ia64 port of the SGI kernprof patch, which is
* Copyright (c) 2003-2004 Silicon Graphics Inc. All Rights Reserved.
*/
#include <linux/oprofile.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/ptrace.h>
#include <asm/system.h>
/*
* For IA64 we need to perform a complex little dance to get both
* the struct pt_regs and a synthetic struct switch_stack in place
* to allow the unwind code to work. This dance requires our unwind
* using code to be called from a function called from unw_init_running().
* There we only get a single void* data pointer, so use this struct
* to hold all the data we need during the unwind.
*/
typedef struct
{
unsigned int depth;
struct pt_regs *regs;
struct unw_frame_info frame;
u64 *prev_pfs_loc; /* state for WAR for old spinlock ool code */
} ia64_backtrace_t;
#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
/*
* Returns non-zero if the PC is in the spinlock contention out-of-line code
* with non-standard calling sequence (on older compilers).
*/
static __inline__ int in_old_ool_spinlock_code(unsigned long pc)
{
extern const char ia64_spinlock_contention_pre3_4[] __attribute__ ((weak));
extern const char ia64_spinlock_contention_pre3_4_end[] __attribute__ ((weak));
unsigned long sc_start = (unsigned long)ia64_spinlock_contention_pre3_4;
unsigned long sc_end = (unsigned long)ia64_spinlock_contention_pre3_4_end;
return (sc_start && sc_end && pc >= sc_start && pc < sc_end);
}
#else
/* Newer spinlock code does a proper br.call and works fine with the unwinder */
#define in_old_ool_spinlock_code(pc) 0
#endif
/* Returns non-zero if the PC is in the Interrupt Vector Table */
static __inline__ int in_ivt_code(unsigned long pc)
{
extern char ia64_ivt[];
return (pc >= (u_long)ia64_ivt && pc < (u_long)ia64_ivt+32768);
}
/*
* Unwind to next stack frame.
*/
static __inline__ int next_frame(ia64_backtrace_t *bt)
{
/*
* Avoid unsightly console message from unw_unwind() when attempting
* to unwind through the Interrupt Vector Table which has no unwind
* information.
*/
if (in_ivt_code(bt->frame.ip))
return 0;
/*
* WAR for spinlock contention from leaf functions. ia64_spinlock_contention_pre3_4
* has ar.pfs == r0. Leaf functions do not modify ar.pfs so ar.pfs remains
* as 0, stopping the backtrace. Record the previous ar.pfs when the current
* IP is in ia64_spinlock_contention_pre3_4 then unwind, if pfs_loc has not changed
* after unwind then use pt_regs.ar_pfs which is where the real ar.pfs is for
* leaf functions.
*/
if (bt->prev_pfs_loc && bt->regs && bt->frame.pfs_loc == bt->prev_pfs_loc)
bt->frame.pfs_loc = &bt->regs->ar_pfs;
bt->prev_pfs_loc = (in_old_ool_spinlock_code(bt->frame.ip) ? bt->frame.pfs_loc : NULL);
return unw_unwind(&bt->frame) == 0;
}
static void do_ia64_backtrace(struct unw_frame_info *info, void *vdata)
{
ia64_backtrace_t *bt = vdata;
struct switch_stack *sw;
int count = 0;
u_long pc, sp;
sw = (struct switch_stack *)(info+1);
/* padding from unw_init_running */
sw = (struct switch_stack *)(((unsigned long)sw + 15) & ~15);
unw_init_frame_info(&bt->frame, current, sw);
/* skip over interrupt frame and oprofile calls */
do {
unw_get_sp(&bt->frame, &sp);
if (sp >= (u_long)bt->regs)
break;
if (!next_frame(bt))
return;
} while (count++ < 200);
/* finally, grab the actual sample */
while (bt->depth-- && next_frame(bt)) {
unw_get_ip(&bt->frame, &pc);
oprofile_add_trace(pc);
if (unw_is_intr_frame(&bt->frame)) {
/*
* Interrupt received on kernel stack; this can
* happen when timer interrupt fires while processing
* a softirq from the tail end of a hardware interrupt
* which interrupted a system call. Don't laugh, it
* happens! Splice the backtrace into two parts to
* avoid spurious cycles in the gprof output.
*/
/* TODO: split rather than drop the 2nd half */
break;
}
}
}
void
ia64_backtrace(struct pt_regs * const regs, unsigned int depth)
{
ia64_backtrace_t bt;
unsigned long flags;
/*
* On IA64 there is little hope of getting backtraces from
* user space programs -- the problems of getting the unwind
* information from arbitrary user programs are extreme.
*/
if (user_mode(regs))
return;
bt.depth = depth;
bt.regs = regs;
bt.prev_pfs_loc = NULL;
local_irq_save(flags);
unw_init_running(do_ia64_backtrace, &bt);
local_irq_restore(flags);
}

38
arch/ia64/oprofile/init.c Normal file
View File

@ -0,0 +1,38 @@
/**
* @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>
#include <linux/errno.h>
extern int perfmon_init(struct oprofile_operations * ops);
extern void perfmon_exit(void);
extern void ia64_backtrace(struct pt_regs * const regs, unsigned int depth);
int __init oprofile_arch_init(struct oprofile_operations * ops)
{
int ret = -ENODEV;
#ifdef CONFIG_PERFMON
/* perfmon_init() can fail, but we have no way to report it */
ret = perfmon_init(ops);
#endif
ops->backtrace = ia64_backtrace;
return ret;
}
void oprofile_arch_exit(void)
{
#ifdef CONFIG_PERFMON
perfmon_exit();
#endif
}

View File

@ -0,0 +1,100 @@
/**
* @file perfmon.c
*
* @remark Copyright 2003 OProfile authors
* @remark Read the file COPYING
*
* @author John Levon <levon@movementarian.org>
*/
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/oprofile.h>
#include <linux/sched.h>
#include <asm/perfmon.h>
#include <asm/ptrace.h>
#include <asm/errno.h>
static int allow_ints;
static int
perfmon_handler(struct task_struct *task, void *buf, pfm_ovfl_arg_t *arg,
struct pt_regs *regs, unsigned long stamp)
{
int event = arg->pmd_eventid;
arg->ovfl_ctrl.bits.reset_ovfl_pmds = 1;
/* the owner of the oprofile event buffer may have exited
* without perfmon being shutdown (e.g. SIGSEGV)
*/
if (allow_ints)
oprofile_add_sample(regs, event);
return 0;
}
static int perfmon_start(void)
{
allow_ints = 1;
return 0;
}
static void perfmon_stop(void)
{
allow_ints = 0;
}
#define OPROFILE_FMT_UUID { \
0x77, 0x7a, 0x6e, 0x61, 0x20, 0x65, 0x73, 0x69, 0x74, 0x6e, 0x72, 0x20, 0x61, 0x65, 0x0a, 0x6c }
static pfm_buffer_fmt_t oprofile_fmt = {
.fmt_name = "oprofile_format",
.fmt_uuid = OPROFILE_FMT_UUID,
.fmt_handler = perfmon_handler,
};
static char * get_cpu_type(void)
{
__u8 family = local_cpu_data->family;
switch (family) {
case 0x07:
return "ia64/itanium";
case 0x1f:
return "ia64/itanium2";
default:
return "ia64/ia64";
}
}
/* all the ops are handled via userspace for IA64 perfmon */
static int using_perfmon;
int perfmon_init(struct oprofile_operations * ops)
{
int ret = pfm_register_buffer_fmt(&oprofile_fmt);
if (ret)
return -ENODEV;
ops->cpu_type = get_cpu_type();
ops->start = perfmon_start;
ops->stop = perfmon_stop;
using_perfmon = 1;
printk(KERN_INFO "oprofile: using perfmon.\n");
return 0;
}
void perfmon_exit(void)
{
if (!using_perfmon)
return;
pfm_unregister_buffer_fmt(oprofile_fmt.fmt_uuid);
}