11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @file arch/alpha/oprofile/common.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @remark Copyright 2002 OProfile authors 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @remark Read the file COPYING 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @author Richard Henderson <rth@twiddle.net> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/oprofile.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/ptrace.h> 15d1b5153f3ec83789b71d64efaf2a880c8fe6358eMichael Cree#include <asm/special_insns.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "op_impl.h" 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct op_axp_model op_model_ev4 __attribute__((weak)); 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct op_axp_model op_model_ev5 __attribute__((weak)); 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct op_axp_model op_model_pca56 __attribute__((weak)); 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct op_axp_model op_model_ev6 __attribute__((weak)); 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct op_axp_model op_model_ev67 __attribute__((weak)); 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct op_axp_model *model; 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void (*perf_irq)(unsigned long, struct pt_regs *); 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void (*save_perf_irq)(unsigned long, struct pt_regs *); 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct op_counter_config ctr[20]; 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct op_system_config sys; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct op_register_config reg; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Called from do_entInt to handle the performance monitor interrupt. */ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsop_handle_interrupt(unsigned long which, struct pt_regs *regs) 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds model->handle_interrupt(which, regs, ctr); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If the user has selected an interrupt frequency that is 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds not exactly the width of the counter, write a new value 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds into the counter such that it'll overflow after N more 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds events. */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((reg.need_reset >> which) & 1) 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds model->reset_ctr(®, which); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsop_axp_setup(void) 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long i, e; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Install our interrupt handler into the existing hook. */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save_perf_irq = perf_irq; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perf_irq = op_handle_interrupt; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Compute the mask of enabled counters. */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = e = 0; i < model->num_counters; ++i) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ctr[i].enabled) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e |= 1 << i; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg.enable = e; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Pre-compute the values to stuff in the hardware registers. */ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds model->reg_setup(®, ctr, &sys); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Configure the registers on all cpus. */ 688691e5a8f691cc2a4fda0651e8d307aaba0e7d68Jens Axboe (void)smp_call_function(model->cpu_setup, ®, 1); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds model->cpu_setup(®); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsop_axp_shutdown(void) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove our interrupt handler. We may be removing this module. */ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perf_irq = save_perf_irq; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsop_axp_cpu_start(void *dummy) 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wrperfmon(1, reg.enable); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsop_axp_start(void) 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 898691e5a8f691cc2a4fda0651e8d307aaba0e7d68Jens Axboe (void)smp_call_function(op_axp_cpu_start, NULL, 1); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op_axp_cpu_start(NULL); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsop_axp_cpu_stop(void *dummy) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Disable performance monitoring for all counters. */ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wrperfmon(0, -1); 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsop_axp_stop(void) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1048691e5a8f691cc2a4fda0651e8d307aaba0e7d68Jens Axboe (void)smp_call_function(op_axp_cpu_stop, NULL, 1); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op_axp_cpu_stop(NULL); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 109ef7bca1456e7f65e66b9466c3b149601fe32eec0Al Viroop_axp_create_files(struct dentry *root) 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < model->num_counters; ++i) { 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct dentry *dir; 1150c6856f702732d3cfc33eb59303e998ad6961de8Markus Armbruster char buf[4]; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snprintf(buf, sizeof buf, "%d", i); 118ecde28237e10de3750a97579f42bc2ec65b8a0e1Al Viro dir = oprofilefs_mkdir(root, buf); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1206af4ea0ba708172be8caf1ba5047b2b8a9d2fea3Al Viro oprofilefs_create_ulong(dir, "enabled", &ctr[i].enabled); 1216af4ea0ba708172be8caf1ba5047b2b8a9d2fea3Al Viro oprofilefs_create_ulong(dir, "event", &ctr[i].event); 1226af4ea0ba708172be8caf1ba5047b2b8a9d2fea3Al Viro oprofilefs_create_ulong(dir, "count", &ctr[i].count); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Dummies. */ 1246af4ea0ba708172be8caf1ba5047b2b8a9d2fea3Al Viro oprofilefs_create_ulong(dir, "kernel", &ctr[i].kernel); 1256af4ea0ba708172be8caf1ba5047b2b8a9d2fea3Al Viro oprofilefs_create_ulong(dir, "user", &ctr[i].user); 1266af4ea0ba708172be8caf1ba5047b2b8a9d2fea3Al Viro oprofilefs_create_ulong(dir, "unit_mask", &ctr[i].unit_mask); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (model->can_set_proc_mode) { 1306af4ea0ba708172be8caf1ba5047b2b8a9d2fea3Al Viro oprofilefs_create_ulong(root, "enable_pal", 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &sys.enable_pal); 1326af4ea0ba708172be8caf1ba5047b2b8a9d2fea3Al Viro oprofilefs_create_ulong(root, "enable_kernel", 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &sys.enable_kernel); 1346af4ea0ba708172be8caf1ba5047b2b8a9d2fea3Al Viro oprofilefs_create_ulong(root, "enable_user", 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &sys.enable_user); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoprofile_arch_init(struct oprofile_operations *ops) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct op_axp_model *lmodel = NULL; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (implver()) { 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IMPLVER_EV4: 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lmodel = &op_model_ev4; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IMPLVER_EV5: 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 21164PC has a slightly different set of events. 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Recognize the chip by the presence of the MAX insns. */ 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!amask(AMASK_MAX)) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lmodel = &op_model_pca56; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lmodel = &op_model_ev5; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IMPLVER_EV6: 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 21264A supports ProfileMe. 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Recognize the chip by the presence of the CIX insns. */ 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!amask(AMASK_CIX)) 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lmodel = &op_model_ev67; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lmodel = &op_model_ev6; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lmodel) 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds model = lmodel; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->create_files = op_axp_create_files; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->setup = op_axp_setup; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->shutdown = op_axp_shutdown; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->start = op_axp_start; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->stop = op_axp_stop; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ops->cpu_type = lmodel->cpu_type; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "oprofile: using %s performance monitoring.\n", 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lmodel->cpu_type); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoprofile_arch_exit(void) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 190