Skip to content

Commit

Permalink
[PATCH] powerpc: G4+ oprofile support
Browse files Browse the repository at this point in the history
This patch adds oprofile support for the 7450 and all its multitudinous
derivatives.

* Added 7450 (and derivatives) support for oprofile
* Changed e500 cputable to have oprofile model and cpu_type fields
* Added support for classic 32-bit performance monitor interrupt
* Cleaned up common powerpc oprofile code to be as common as possible
* Cleaned up oprofile_impl.h to reflect 32 bit classic code
* Added 32-bit MMCRx bitfield definitions and SPR numbers

Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
Andy Fleming authored and Paul Mackerras committed Jan 9, 2006
1 parent e5cd040 commit 555d97a
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 84 deletions.
74 changes: 63 additions & 11 deletions arch/powerpc/kernel/cputable.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7450 2.1 */
.pvr_mask = 0xffffffff,
Expand All @@ -556,7 +560,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7450 2.3 and newer */
.pvr_mask = 0xffff0000,
Expand All @@ -567,7 +575,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7455 rev 1.x */
.pvr_mask = 0xffffff00,
Expand All @@ -578,7 +590,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7455 rev 2.0 */
.pvr_mask = 0xffffffff,
Expand All @@ -589,7 +605,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7455 others */
.pvr_mask = 0xffff0000,
Expand All @@ -600,7 +620,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7447/7457 Rev 1.0 */
.pvr_mask = 0xffffffff,
Expand All @@ -611,7 +635,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7447/7457 Rev 1.1 */
.pvr_mask = 0xffffffff,
Expand All @@ -622,7 +650,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7447/7457 Rev 1.2 and later */
.pvr_mask = 0xffff0000,
Expand All @@ -633,7 +665,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7447A */
.pvr_mask = 0xffff0000,
Expand All @@ -644,7 +680,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 7448 */
.pvr_mask = 0xffff0000,
Expand All @@ -655,7 +695,11 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
.cpu_setup = __setup_cpu_745x,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/7450",
.oprofile_model = &op_model_7450,
#endif
},
{ /* 82xx (8240, 8245, 8260 are all 603e cores) */
.pvr_mask = 0x7fff0000,
Expand Down Expand Up @@ -979,6 +1023,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/e500",
.oprofile_model = &op_model_fsl_booke,
#endif
},
{ /* e500v2 */
.pvr_mask = 0xffff0000,
Expand All @@ -992,6 +1040,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc/e500",
.oprofile_model = &op_model_fsl_booke,
#endif
},
#endif
#if !CLASSIC_PPC
Expand Down
12 changes: 6 additions & 6 deletions arch/powerpc/kernel/head_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -466,16 +466,11 @@ SystemCall:
* by executing an altivec instruction.
*/
. = 0xf00
b Trap_0f
b PerformanceMonitor

. = 0xf20
b AltiVecUnavailable

Trap_0f:
EXCEPTION_PROLOG
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_EE(0xf00, unknown_exception)

/*
* Handle TLB miss for instruction on 603/603e.
* Note: we get an alternate set of r0 - r3 to use automatically.
Expand Down Expand Up @@ -719,6 +714,11 @@ AltiVecUnavailable:
#endif /* CONFIG_ALTIVEC */
EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)

PerformanceMonitor:
EXCEPTION_PROLOG
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_STD(0xf00, performance_monitor_exception)

#ifdef CONFIG_ALTIVEC
/* Note that the AltiVec support is closely modeled after the FP
* support. Changes to one are likely to be applicable to the
Expand Down
5 changes: 5 additions & 0 deletions arch/powerpc/kernel/pmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,13 @@ static void dummy_perf(struct pt_regs *regs)
mtspr(SPRN_MMCR0, mmcr0);
}
#else
/* Ensure exceptions are disabled */
static void dummy_perf(struct pt_regs *regs)
{
unsigned int mmcr0 = mfspr(SPRN_MMCR0);

mmcr0 &= ~(MMCR0_PMXE);
mtspr(SPRN_MMCR0, mmcr0);
}
#endif

Expand Down
2 changes: 0 additions & 2 deletions arch/powerpc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -901,12 +901,10 @@ void altivec_unavailable_exception(struct pt_regs *regs)
die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
}

#if defined(CONFIG_PPC64) || defined(CONFIG_E500)
void performance_monitor_exception(struct pt_regs *regs)
{
perf_irq(regs);
}
#endif

#ifdef CONFIG_8xx
void SoftwareEmulation(struct pt_regs *regs)
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/oprofile/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
oprofile-y := $(DRIVER_OBJS) common.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
oprofile-$(CONFIG_PPC32) += op_model_7450.o
61 changes: 12 additions & 49 deletions arch/powerpc/oprofile/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
*/

#include <linux/oprofile.h>
#ifndef __powerpc64__
#include <linux/slab.h>
#endif /* ! __powerpc64__ */
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/errno.h>
Expand All @@ -31,10 +28,6 @@ static struct op_powerpc_model *model;
static struct op_counter_config ctr[OP_MAX_COUNTER];
static struct op_system_config sys;

#ifndef __powerpc64__
static char *cpu_type;
#endif /* ! __powerpc64__ */

static void op_handle_interrupt(struct pt_regs *regs)
{
model->handle_interrupt(regs, ctr);
Expand All @@ -53,14 +46,7 @@ static int op_powerpc_setup(void)
model->reg_setup(ctr, &sys, model->num_counters);

/* Configure the registers on all cpus. */
#ifdef __powerpc64__
on_each_cpu(model->cpu_setup, NULL, 0, 1);
#else /* __powerpc64__ */
#if 0
/* FIXME: Make multi-cpu work */
on_each_cpu(model->reg_setup, NULL, 0, 1);
#endif
#endif /* __powerpc64__ */

return 0;
}
Expand Down Expand Up @@ -95,15 +81,15 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
{
int i;

#ifdef __powerpc64__
#ifdef CONFIG_PPC64
/*
* There is one mmcr0, mmcr1 and mmcra for setting the events for
* all of the counters.
*/
oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
#endif /* __powerpc64__ */
#endif

for (i = 0; i < model->num_counters; ++i) {
struct dentry *dir;
Expand All @@ -115,65 +101,46 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
#ifdef __powerpc64__

/*
* We dont support per counter user/kernel selection, but
* we leave the entries because userspace expects them
* Classic PowerPC doesn't support per-counter
* control like this, but the options are
* expected, so they remain. For Freescale
* Book-E style performance monitors, we do
* support them.
*/
#endif /* __powerpc64__ */
oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);

#ifndef __powerpc64__
/* FIXME: Not sure if this is used */
#endif /* ! __powerpc64__ */
oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
}

oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
#ifdef __powerpc64__
#ifdef CONFIG_PPC64
oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
&sys.backtrace_spinlocks);
#endif /* __powerpc64__ */
#endif

/* Default to tracing both kernel and user */
sys.enable_kernel = 1;
sys.enable_user = 1;
#ifdef __powerpc64__
#ifdef CONFIG_PPC64
/* Turn on backtracing through spinlocks by default */
sys.backtrace_spinlocks = 1;
#endif /* __powerpc64__ */
#endif

return 0;
}

int __init oprofile_arch_init(struct oprofile_operations *ops)
{
#ifndef __powerpc64__
#ifdef CONFIG_FSL_BOOKE
model = &op_model_fsl_booke;
#else
return -ENODEV;
#endif

cpu_type = kmalloc(32, GFP_KERNEL);
if (NULL == cpu_type)
return -ENOMEM;

sprintf(cpu_type, "ppc/%s", cur_cpu_spec->cpu_name);

model->num_counters = cur_cpu_spec->num_pmcs;

ops->cpu_type = cpu_type;
#else /* __powerpc64__ */
if (!cur_cpu_spec->oprofile_model || !cur_cpu_spec->oprofile_cpu_type)
return -ENODEV;
model = cur_cpu_spec->oprofile_model;
model->num_counters = cur_cpu_spec->num_pmcs;

ops->cpu_type = cur_cpu_spec->oprofile_cpu_type;
#endif /* __powerpc64__ */
ops->create_files = op_powerpc_create_files;
ops->setup = op_powerpc_setup;
ops->shutdown = op_powerpc_shutdown;
Expand All @@ -188,8 +155,4 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)

void oprofile_arch_exit(void)
{
#ifndef __powerpc64__
kfree(cpu_type);
cpu_type = NULL;
#endif /* ! __powerpc64__ */
}
Loading

0 comments on commit 555d97a

Please sign in to comment.