45 #include <linux/capability.h>
51 #include <asm/uaccess.h>
54 #include <asm/processor.h>
60 #define MAX_RDR_WORDS 24
61 #define PERF_VERSION 2
76 static const int perf_rdrs_W[] =
77 { 0, 1, 4, 5, 6, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
80 static const int perf_rdrs_U[] =
81 { 0, 1, 4, 5, 6, 7, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
84 static const struct rdr_tbl_ent perf_rdr_tbl_W[] = {
120 static const struct rdr_tbl_ent perf_rdr_tbl_U[] = {
159 static const uint64_t perf_bitmasks[] = {
160 0x0000000000000000ul,
161 0xfdffe00000000000ul,
162 0x003f000000000000ul,
163 0x00fffffffffffffful,
164 0xfffffffffffffffful,
165 0xfffffffc00000000ul,
166 0xfffffffffffffffful,
167 0xfffffffffffffffful,
168 0xfffffffffffffffcul,
176 static const uint64_t perf_bitmasks_piranha[] = {
177 0x0000000000000000ul,
178 0xfdffe00000000000ul,
179 0x003f000000000000ul,
180 0x00fffffffffffffful,
181 0xfffffffffffffffful,
182 0xfffffffc00000000ul,
183 0xfffffffffffffffful,
184 0xfffffffffffffffful,
185 0xfffffffffffffffful,
189 static const uint64_t *bitmask_array;
194 static int perf_config(
uint32_t *image_ptr);
200 static long perf_ioctl(
struct file *
file,
unsigned int cmd,
unsigned long arg);
201 static void perf_start_counters(
void);
205 static int perf_rdr_clear(
uint32_t rdr_num);
228 static int perf_config(
uint32_t *image_ptr)
234 error = perf_stop_counters(raddr);
236 printk(
"perf_config: perf_stop_counters = %ld\n", error);
240 printk(
"Preparing to write image\n");
242 error = perf_write_image((
uint64_t *)image_ptr);
244 printk(
"perf_config: DOWNLOAD = %ld\n", error);
248 printk(
"Preparing to start counters\n");
251 perf_start_counters();
263 spin_lock(&perf_lock);
265 spin_unlock(&perf_lock);
269 spin_unlock(&perf_lock);
277 static int perf_release(
struct inode *inode,
struct file *file)
279 spin_lock(&perf_lock);
281 spin_unlock(&perf_lock);
289 static ssize_t perf_read(
struct file *file,
char __user *
buf,
size_t cnt, loff_t *ppos)
301 static ssize_t perf_write(
struct file *file,
const char __user *
buf,
size_t count,
310 if (perf_processor_interface ==
ONYX_INTF)
312 else if (perf_processor_interface ==
CUDA_INTF)
327 interface_type = (image_type >> 16) & 0xffff;
328 test = (image_type & 0xffff);
334 if (((perf_processor_interface ==
CUDA_INTF) &&
336 ((perf_processor_interface ==
ONYX_INTF) &&
350 return perf_config(cuda_images[test]);
352 return perf_config(onyx_images[test]);
360 static void perf_patch_images(
void)
367 extern void $i_itlb_miss_2_0();
368 extern void $i_dtlb_miss_2_0();
369 extern void PA2_0_iva();
379 if (perf_processor_interface ==
ONYX_INTF) {
381 onyx_images[
TLBMISS][15] &= 0xffffff00;
383 onyx_images[
TLBMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
384 onyx_images[
TLBMISS][16] = (dtlb_addr << 8)&0xffffff00;
385 onyx_images[
TLBMISS][17] = itlb_addr;
390 onyx_images[
TLBHANDMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
391 onyx_images[
TLBHANDMISS][16] = (dtlb_addr << 8)&0xffffff00;
395 onyx_images[
BIG_CPI][15] &= 0xffffff00;
397 onyx_images[
BIG_CPI][15] |= (0x000000ff&((dtlb_addr) >> 24));
398 onyx_images[
BIG_CPI][16] = (dtlb_addr << 8)&0xffffff00;
399 onyx_images[
BIG_CPI][17] = itlb_addr;
401 onyx_images[
PANIC][15] &= 0xffffff00;
402 onyx_images[
PANIC][15] |= (0x000000ff&((IVAaddress) >> 24));
403 onyx_images[
PANIC][16] = (IVAaddress << 8)&0xffffff00;
406 }
else if (perf_processor_interface ==
CUDA_INTF) {
409 (cuda_images[
TLBMISS][16]&0xffff0000) |
410 ((dtlb_addr >> 8)&0x0000ffff);
412 ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
413 cuda_images[
TLBMISS][18] = (itlb_addr << 16)&0xffff0000;
417 ((dtlb_addr >> 8)&0x0000ffff);
419 ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
420 cuda_images[
TLBHANDMISS][18] = (itlb_addr << 16)&0xffff0000;
423 (cuda_images[
BIG_CPI][16]&0xffff0000) |
424 ((dtlb_addr >> 8)&0x0000ffff);
426 ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
427 cuda_images[
BIG_CPI][18] = (itlb_addr << 16)&0xffff0000;
441 static long perf_ioctl(
struct file *file,
unsigned int cmd,
unsigned long arg)
451 perf_start_counters();
455 error_start = perf_stop_counters(raddr);
456 if (error_start != 0) {
457 printk(
KERN_ERR "perf_off: perf_stop_counters = %ld\n", error_start);
464 sizeof (raddr)) != 0) {
486 .unlocked_ioctl = perf_ioctl,
487 .compat_ioctl = perf_ioctl,
489 .release = perf_release
501 static int __init perf_init(
void)
506 bitmask_array = perf_bitmasks;
520 bitmask_array = perf_bitmasks_piranha;
523 printk(
"Performance monitoring counters not supported on this processor\n");
530 "cannot register misc device.\n");
541 printk(
"Performance monitoring counters enabled for %s\n",
552 static void perf_start_counters(
void)
564 static int perf_stop_counters(
uint32_t *raddr)
571 if (perf_processor_interface ==
ONYX_INTF) {
576 if (!perf_rdr_read_ubuf(16, userbuf))
580 tmp64 = (userbuf[21] << 22) & 0x00000000ffc00000;
581 tmp64 |= (userbuf[22] >> 42) & 0x00000000003fffff;
583 tmp64 |= (userbuf[22] >> 10) & 0x0000000080000000;
587 tmp64 = (userbuf[22] >> 9) & 0x00000000ffffffff;
589 tmp64 |= (userbuf[22] << 23) & 0x0000000080000000;
593 tmp64 = (userbuf[22] << 24) & 0x00000000ff000000;
594 tmp64 |= (userbuf[23] >> 40) & 0x0000000000ffffff;
596 tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000;
600 tmp64 = (userbuf[23] >> 7) & 0x00000000ffffffff;
602 tmp64 |= (userbuf[23] << 25) & 0x0000000080000000;
616 userbuf[21] &= 0xfffffffffffffc00ul;
624 perf_rdr_write(16, userbuf);
630 if (!perf_rdr_read_ubuf(15, userbuf)) {
642 raddr[0] = (
uint32_t)((userbuf[0] >> 32) & 0x00000000ffffffff
UL);
643 raddr[1] = (
uint32_t)(userbuf[0] & 0x00000000ffffffffUL);
644 raddr[2] = (
uint32_t)((userbuf[1] >> 32) & 0x00000000ffffffff
UL);
645 raddr[3] = (
uint32_t)(userbuf[1] & 0x00000000ffffffffUL);
659 if (perf_processor_interface ==
ONYX_INTF) {
660 return &perf_rdr_tbl_U[rdr_num];
662 return &perf_rdr_tbl_W[rdr_num];
677 tentry = perf_rdr_get_entry(rdr_num);
678 if ((width = tentry->
width) == 0)
688 if ((xbits = width & 0x03f) != 0) {
690 data_mask <<= (64 - xbits);
698 if (perf_processor_interface ==
ONYX_INTF) {
704 buffer[
i] |= (data << (64 - xbits));
706 buffer[i-1] |= ((data >> xbits) & data_mask);
721 static int perf_rdr_clear(
uint32_t rdr_num)
726 tentry = perf_rdr_get_entry(rdr_num);
728 if (tentry->
width == 0) {
734 if (perf_processor_interface ==
ONYX_INTF) {
763 if (perf_processor_interface ==
ONYX_INTF) {
771 intrigue_rdr = perf_rdrs_U;
774 intrigue_rdr = perf_rdrs_W;
778 while (*intrigue_rdr != -1) {
779 tentry = perf_rdr_get_entry(*intrigue_rdr);
780 perf_rdr_read_ubuf(*intrigue_rdr, buffer);
784 intrigue_bitmask = &bitmask_array[tentry->
write_control >> 3];
786 tmp64 = *intrigue_bitmask & *memaddr++;
787 tmp64 |= (~(*intrigue_bitmask++)) & *bptr;
792 *bptr++ = *memaddr++;
796 perf_rdr_write(*intrigue_rdr, buffer);
804 if (cpu_device ==
NULL)
806 printk(
KERN_ERR "write_image: cpu_device not yet initialized!\n");
813 tmp64 =
__raw_readq(runway + RUNWAY_STATUS) & 0xffecfffffffffffful;
814 __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul),
815 runway + RUNWAY_STATUS);
818 for (i = 0; i < 8; i++) {
836 printk(
"perf_rdr_write\n");
837 tentry = perf_rdr_get_entry(rdr_num);
838 if (tentry->
width == 0) {
return; }
842 if (perf_processor_interface ==
ONYX_INTF) {
848 printk(
"perf_rdr_write done\n");