1 /* 2 * PS3 Logical Performance Monitor. 3 * 4 * Copyright (C) 2007 Sony Computer Entertainment Inc. 5 * Copyright 2007 Sony Corp. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include <linux/interrupt.h> 24 #include <linux/uaccess.h> 25 #include <asm/ps3.h> 26 #include <asm/lv1call.h> 27 #include <asm/cell-pmu.h> 28 29 30 /* BOOKMARK tag macros */ 31 #define PS3_PM_BOOKMARK_START 0x8000000000000000ULL 32 #define PS3_PM_BOOKMARK_STOP 0x4000000000000000ULL 33 #define PS3_PM_BOOKMARK_TAG_KERNEL 0x1000000000000000ULL 34 #define PS3_PM_BOOKMARK_TAG_USER 0x3000000000000000ULL 35 #define PS3_PM_BOOKMARK_TAG_MASK_HI 0xF000000000000000ULL 36 #define PS3_PM_BOOKMARK_TAG_MASK_LO 0x0F00000000000000ULL 37 38 /* CBE PM CONTROL register macros */ 39 #define PS3_PM_CONTROL_PPU_TH0_BOOKMARK 0x00001000 40 #define PS3_PM_CONTROL_PPU_TH1_BOOKMARK 0x00000800 41 #define PS3_PM_CONTROL_PPU_COUNT_MODE_MASK 0x000C0000 42 #define PS3_PM_CONTROL_PPU_COUNT_MODE_PROBLEM 0x00080000 43 #define PS3_WRITE_PM_MASK 0xFFFFFFFFFFFFFFFFULL 44 45 /* CBE PM START STOP register macros */ 46 #define PS3_PM_START_STOP_PPU_TH0_BOOKMARK_START 0x02000000 47 #define PS3_PM_START_STOP_PPU_TH1_BOOKMARK_START 0x01000000 48 #define PS3_PM_START_STOP_PPU_TH0_BOOKMARK_STOP 0x00020000 49 #define PS3_PM_START_STOP_PPU_TH1_BOOKMARK_STOP 0x00010000 50 #define PS3_PM_START_STOP_START_MASK 0xFF000000 51 #define PS3_PM_START_STOP_STOP_MASK 0x00FF0000 52 53 /* CBE PM COUNTER register macres */ 54 #define PS3_PM_COUNTER_MASK_HI 0xFFFFFFFF00000000ULL 55 #define PS3_PM_COUNTER_MASK_LO 0x00000000FFFFFFFFULL 56 57 /* BASE SIGNAL GROUP NUMBER macros */ 58 #define PM_ISLAND2_BASE_SIGNAL_GROUP_NUMBER 0 59 #define PM_ISLAND2_SIGNAL_GROUP_NUMBER1 6 60 #define PM_ISLAND2_SIGNAL_GROUP_NUMBER2 7 61 #define PM_ISLAND3_BASE_SIGNAL_GROUP_NUMBER 7 62 #define PM_ISLAND4_BASE_SIGNAL_GROUP_NUMBER 15 63 #define PM_SPU_TRIGGER_SIGNAL_GROUP_NUMBER 17 64 #define PM_SPU_EVENT_SIGNAL_GROUP_NUMBER 18 65 #define PM_ISLAND5_BASE_SIGNAL_GROUP_NUMBER 18 66 #define PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER 24 67 #define PM_ISLAND7_BASE_SIGNAL_GROUP_NUMBER 49 68 #define PM_ISLAND8_BASE_SIGNAL_GROUP_NUMBER 52 69 #define PM_SIG_GROUP_SPU 41 70 #define PM_SIG_GROUP_SPU_TRIGGER 42 71 #define PM_SIG_GROUP_SPU_EVENT 43 72 #define PM_SIG_GROUP_MFC_MAX 60 73 74 /** 75 * struct ps3_lpm_shadow_regs - Performance monitor shadow registers. 76 * 77 * @pm_control: Shadow of the processor's pm_control register. 78 * @pm_start_stop: Shadow of the processor's pm_start_stop register. 79 * @pm_interval: Shadow of the processor's pm_interval register. 80 * @group_control: Shadow of the processor's group_control register. 81 * @debug_bus_control: Shadow of the processor's debug_bus_control register. 82 * 83 * The logical performance monitor provides a write-only interface to 84 * these processor registers. These shadow variables cache the processor 85 * register values for reading. 86 * 87 * The initial value of the shadow registers at lpm creation is 88 * PS3_LPM_SHADOW_REG_INIT. 89 */ 90 91 struct ps3_lpm_shadow_regs { 92 u64 pm_control; 93 u64 pm_start_stop; 94 u64 pm_interval; 95 u64 group_control; 96 u64 debug_bus_control; 97 }; 98 99 #define PS3_LPM_SHADOW_REG_INIT 0xFFFFFFFF00000000ULL 100 101 /** 102 * struct ps3_lpm_priv - Private lpm device data. 103 * 104 * @open: An atomic variable indicating the lpm driver has been opened. 105 * @rights: The lpm rigths granted by the system policy module. A logical 106 * OR of enum ps3_lpm_rights. 107 * @node_id: The node id of a BE prosessor whose performance monitor this 108 * lpar has the right to use. 109 * @pu_id: The lv1 id of the logical PU. 110 * @lpm_id: The lv1 id of this lpm instance. 111 * @outlet_id: The outlet created by lv1 for this lpm instance. 112 * @tb_count: The number of bytes of data held in the lv1 trace buffer. 113 * @tb_cache: Kernel buffer to receive the data from the lv1 trace buffer. 114 * Must be 128 byte aligned. 115 * @tb_cache_size: Size of the kernel @tb_cache buffer. Must be 128 byte 116 * aligned. 117 * @tb_cache_internal: An unaligned buffer allocated by this driver to be 118 * used for the trace buffer cache when ps3_lpm_open() is called with a 119 * NULL tb_cache argument. Otherwise unused. 120 * @shadow: Processor register shadow of type struct ps3_lpm_shadow_regs. 121 * @sbd: The struct ps3_system_bus_device attached to this driver. 122 * 123 * The trace buffer is a buffer allocated and used internally to the lv1 124 * hypervisor to collect trace data. The trace buffer cache is a guest 125 * buffer that accepts the trace data from the trace buffer. 126 */ 127 128 struct ps3_lpm_priv { 129 atomic_t open; 130 u64 rights; 131 u64 node_id; 132 u64 pu_id; 133 u64 lpm_id; 134 u64 outlet_id; 135 u64 tb_count; 136 void *tb_cache; 137 u64 tb_cache_size; 138 void *tb_cache_internal; 139 struct ps3_lpm_shadow_regs shadow; 140 struct ps3_system_bus_device *sbd; 141 }; 142 143 enum { 144 PS3_LPM_DEFAULT_TB_CACHE_SIZE = 0x4000, 145 }; 146 147 /** 148 * lpm_priv - Static instance of the lpm data. 149 * 150 * Since the exported routines don't support the notion of a device 151 * instance we need to hold the instance in this static variable 152 * and then only allow at most one instance at a time to be created. 153 */ 154 155 static struct ps3_lpm_priv *lpm_priv; 156 157 static struct device *sbd_core(void) 158 { 159 BUG_ON(!lpm_priv || !lpm_priv->sbd); 160 return &lpm_priv->sbd->core; 161 } 162 163 /** 164 * use_start_stop_bookmark - Enable the PPU bookmark trace. 165 * 166 * And it enables PPU bookmark triggers ONLY if the other triggers are not set. 167 * The start/stop bookmarks are inserted at ps3_enable_pm() and ps3_disable_pm() 168 * to start/stop LPM. 169 * 170 * Used to get good quality of the performance counter. 171 */ 172 173 enum {use_start_stop_bookmark = 1,}; 174 175 void ps3_set_bookmark(u64 bookmark) 176 { 177 /* 178 * As per the PPE book IV, to avoid bookmark loss there must 179 * not be a traced branch within 10 cycles of setting the 180 * SPRN_BKMK register. The actual text is unclear if 'within' 181 * includes cycles before the call. 182 */ 183 184 asm volatile("or 29, 29, 29;"); /* db10cyc */ 185 mtspr(SPRN_BKMK, bookmark); 186 asm volatile("or 29, 29, 29;"); /* db10cyc */ 187 } 188 EXPORT_SYMBOL_GPL(ps3_set_bookmark); 189 190 void ps3_set_pm_bookmark(u64 tag, u64 incident, u64 th_id) 191 { 192 u64 bookmark; 193 194 bookmark = (get_tb() & 0x00000000FFFFFFFFULL) | 195 PS3_PM_BOOKMARK_TAG_KERNEL; 196 bookmark = ((tag << 56) & PS3_PM_BOOKMARK_TAG_MASK_LO) | 197 (incident << 48) | (th_id << 32) | bookmark; 198 ps3_set_bookmark(bookmark); 199 } 200 EXPORT_SYMBOL_GPL(ps3_set_pm_bookmark); 201 202 /** 203 * ps3_read_phys_ctr - Read physical counter registers. 204 * 205 * Each physical counter can act as one 32 bit counter or as two 16 bit 206 * counters. 207 */ 208 209 u32 ps3_read_phys_ctr(u32 cpu, u32 phys_ctr) 210 { 211 int result; 212 u64 counter0415; 213 u64 counter2637; 214 215 if (phys_ctr >= NR_PHYS_CTRS) { 216 dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__, 217 __LINE__, phys_ctr); 218 return 0; 219 } 220 221 result = lv1_set_lpm_counter(lpm_priv->lpm_id, 0, 0, 0, 0, &counter0415, 222 &counter2637); 223 if (result) { 224 dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter failed: " 225 "phys_ctr %u, %s\n", __func__, __LINE__, phys_ctr, 226 ps3_result(result)); 227 return 0; 228 } 229 230 switch (phys_ctr) { 231 case 0: 232 return counter0415 >> 32; 233 case 1: 234 return counter0415 & PS3_PM_COUNTER_MASK_LO; 235 case 2: 236 return counter2637 >> 32; 237 case 3: 238 return counter2637 & PS3_PM_COUNTER_MASK_LO; 239 default: 240 BUG(); 241 } 242 return 0; 243 } 244 EXPORT_SYMBOL_GPL(ps3_read_phys_ctr); 245 246 /** 247 * ps3_write_phys_ctr - Write physical counter registers. 248 * 249 * Each physical counter can act as one 32 bit counter or as two 16 bit 250 * counters. 251 */ 252 253 void ps3_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val) 254 { 255 u64 counter0415; 256 u64 counter0415_mask; 257 u64 counter2637; 258 u64 counter2637_mask; 259 int result; 260 261 if (phys_ctr >= NR_PHYS_CTRS) { 262 dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__, 263 __LINE__, phys_ctr); 264 return; 265 } 266 267 switch (phys_ctr) { 268 case 0: 269 counter0415 = (u64)val << 32; 270 counter0415_mask = PS3_PM_COUNTER_MASK_HI; 271 counter2637 = 0x0; 272 counter2637_mask = 0x0; 273 break; 274 case 1: 275 counter0415 = (u64)val; 276 counter0415_mask = PS3_PM_COUNTER_MASK_LO; 277 counter2637 = 0x0; 278 counter2637_mask = 0x0; 279 break; 280 case 2: 281 counter0415 = 0x0; 282 counter0415_mask = 0x0; 283 counter2637 = (u64)val << 32; 284 counter2637_mask = PS3_PM_COUNTER_MASK_HI; 285 break; 286 case 3: 287 counter0415 = 0x0; 288 counter0415_mask = 0x0; 289 counter2637 = (u64)val; 290 counter2637_mask = PS3_PM_COUNTER_MASK_LO; 291 break; 292 default: 293 BUG(); 294 } 295 296 result = lv1_set_lpm_counter(lpm_priv->lpm_id, 297 counter0415, counter0415_mask, 298 counter2637, counter2637_mask, 299 &counter0415, &counter2637); 300 if (result) 301 dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter failed: " 302 "phys_ctr %u, val %u, %s\n", __func__, __LINE__, 303 phys_ctr, val, ps3_result(result)); 304 } 305 EXPORT_SYMBOL_GPL(ps3_write_phys_ctr); 306 307 /** 308 * ps3_read_ctr - Read counter. 309 * 310 * Read 16 or 32 bits depending on the current size of the counter. 311 * Counters 4, 5, 6 & 7 are always 16 bit. 312 */ 313 314 u32 ps3_read_ctr(u32 cpu, u32 ctr) 315 { 316 u32 val; 317 u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1); 318 319 val = ps3_read_phys_ctr(cpu, phys_ctr); 320 321 if (ps3_get_ctr_size(cpu, phys_ctr) == 16) 322 val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff); 323 324 return val; 325 } 326 EXPORT_SYMBOL_GPL(ps3_read_ctr); 327 328 /** 329 * ps3_write_ctr - Write counter. 330 * 331 * Write 16 or 32 bits depending on the current size of the counter. 332 * Counters 4, 5, 6 & 7 are always 16 bit. 333 */ 334 335 void ps3_write_ctr(u32 cpu, u32 ctr, u32 val) 336 { 337 u32 phys_ctr; 338 u32 phys_val; 339 340 phys_ctr = ctr & (NR_PHYS_CTRS - 1); 341 342 if (ps3_get_ctr_size(cpu, phys_ctr) == 16) { 343 phys_val = ps3_read_phys_ctr(cpu, phys_ctr); 344 345 if (ctr < NR_PHYS_CTRS) 346 val = (val << 16) | (phys_val & 0xffff); 347 else 348 val = (val & 0xffff) | (phys_val & 0xffff0000); 349 } 350 351 ps3_write_phys_ctr(cpu, phys_ctr, val); 352 } 353 EXPORT_SYMBOL_GPL(ps3_write_ctr); 354 355 /** 356 * ps3_read_pm07_control - Read counter control registers. 357 * 358 * Each logical counter has a corresponding control register. 359 */ 360 361 u32 ps3_read_pm07_control(u32 cpu, u32 ctr) 362 { 363 return 0; 364 } 365 EXPORT_SYMBOL_GPL(ps3_read_pm07_control); 366 367 /** 368 * ps3_write_pm07_control - Write counter control registers. 369 * 370 * Each logical counter has a corresponding control register. 371 */ 372 373 void ps3_write_pm07_control(u32 cpu, u32 ctr, u32 val) 374 { 375 int result; 376 static const u64 mask = 0xFFFFFFFFFFFFFFFFULL; 377 u64 old_value; 378 379 if (ctr >= NR_CTRS) { 380 dev_dbg(sbd_core(), "%s:%u: ctr too big: %u\n", __func__, 381 __LINE__, ctr); 382 return; 383 } 384 385 result = lv1_set_lpm_counter_control(lpm_priv->lpm_id, ctr, val, mask, 386 &old_value); 387 if (result) 388 dev_err(sbd_core(), "%s:%u: lv1_set_lpm_counter_control " 389 "failed: ctr %u, %s\n", __func__, __LINE__, ctr, 390 ps3_result(result)); 391 } 392 EXPORT_SYMBOL_GPL(ps3_write_pm07_control); 393 394 /** 395 * ps3_read_pm - Read Other LPM control registers. 396 */ 397 398 u32 ps3_read_pm(u32 cpu, enum pm_reg_name reg) 399 { 400 int result = 0; 401 u64 val = 0; 402 403 switch (reg) { 404 case pm_control: 405 return lpm_priv->shadow.pm_control; 406 case trace_address: 407 return CBE_PM_TRACE_BUF_EMPTY; 408 case pm_start_stop: 409 return lpm_priv->shadow.pm_start_stop; 410 case pm_interval: 411 return lpm_priv->shadow.pm_interval; 412 case group_control: 413 return lpm_priv->shadow.group_control; 414 case debug_bus_control: 415 return lpm_priv->shadow.debug_bus_control; 416 case pm_status: 417 result = lv1_get_lpm_interrupt_status(lpm_priv->lpm_id, 418 &val); 419 if (result) { 420 val = 0; 421 dev_dbg(sbd_core(), "%s:%u: lv1 get_lpm_status failed: " 422 "reg %u, %s\n", __func__, __LINE__, reg, 423 ps3_result(result)); 424 } 425 return (u32)val; 426 case ext_tr_timer: 427 return 0; 428 default: 429 dev_dbg(sbd_core(), "%s:%u: unknown reg: %d\n", __func__, 430 __LINE__, reg); 431 BUG(); 432 break; 433 } 434 435 return 0; 436 } 437 EXPORT_SYMBOL_GPL(ps3_read_pm); 438 439 /** 440 * ps3_write_pm - Write Other LPM control registers. 441 */ 442 443 void ps3_write_pm(u32 cpu, enum pm_reg_name reg, u32 val) 444 { 445 int result = 0; 446 u64 dummy; 447 448 switch (reg) { 449 case group_control: 450 if (val != lpm_priv->shadow.group_control) 451 result = lv1_set_lpm_group_control(lpm_priv->lpm_id, 452 val, 453 PS3_WRITE_PM_MASK, 454 &dummy); 455 lpm_priv->shadow.group_control = val; 456 break; 457 case debug_bus_control: 458 if (val != lpm_priv->shadow.debug_bus_control) 459 result = lv1_set_lpm_debug_bus_control(lpm_priv->lpm_id, 460 val, 461 PS3_WRITE_PM_MASK, 462 &dummy); 463 lpm_priv->shadow.debug_bus_control = val; 464 break; 465 case pm_control: 466 if (use_start_stop_bookmark) 467 val |= (PS3_PM_CONTROL_PPU_TH0_BOOKMARK | 468 PS3_PM_CONTROL_PPU_TH1_BOOKMARK); 469 if (val != lpm_priv->shadow.pm_control) 470 result = lv1_set_lpm_general_control(lpm_priv->lpm_id, 471 val, 472 PS3_WRITE_PM_MASK, 473 0, 0, &dummy, 474 &dummy); 475 lpm_priv->shadow.pm_control = val; 476 break; 477 case pm_interval: 478 if (val != lpm_priv->shadow.pm_interval) 479 result = lv1_set_lpm_interval(lpm_priv->lpm_id, val, 480 PS3_WRITE_PM_MASK, &dummy); 481 lpm_priv->shadow.pm_interval = val; 482 break; 483 case pm_start_stop: 484 if (val != lpm_priv->shadow.pm_start_stop) 485 result = lv1_set_lpm_trigger_control(lpm_priv->lpm_id, 486 val, 487 PS3_WRITE_PM_MASK, 488 &dummy); 489 lpm_priv->shadow.pm_start_stop = val; 490 break; 491 case trace_address: 492 case ext_tr_timer: 493 case pm_status: 494 break; 495 default: 496 dev_dbg(sbd_core(), "%s:%u: unknown reg: %d\n", __func__, 497 __LINE__, reg); 498 BUG(); 499 break; 500 } 501 502 if (result) 503 dev_err(sbd_core(), "%s:%u: lv1 set_control failed: " 504 "reg %u, %s\n", __func__, __LINE__, reg, 505 ps3_result(result)); 506 } 507 EXPORT_SYMBOL_GPL(ps3_write_pm); 508 509 /** 510 * ps3_get_ctr_size - Get the size of a physical counter. 511 * 512 * Returns either 16 or 32. 513 */ 514 515 u32 ps3_get_ctr_size(u32 cpu, u32 phys_ctr) 516 { 517 u32 pm_ctrl; 518 519 if (phys_ctr >= NR_PHYS_CTRS) { 520 dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__, 521 __LINE__, phys_ctr); 522 return 0; 523 } 524 525 pm_ctrl = ps3_read_pm(cpu, pm_control); 526 return (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32; 527 } 528 EXPORT_SYMBOL_GPL(ps3_get_ctr_size); 529 530 /** 531 * ps3_set_ctr_size - Set the size of a physical counter to 16 or 32 bits. 532 */ 533 534 void ps3_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size) 535 { 536 u32 pm_ctrl; 537 538 if (phys_ctr >= NR_PHYS_CTRS) { 539 dev_dbg(sbd_core(), "%s:%u: phys_ctr too big: %u\n", __func__, 540 __LINE__, phys_ctr); 541 return; 542 } 543 544 pm_ctrl = ps3_read_pm(cpu, pm_control); 545 546 switch (ctr_size) { 547 case 16: 548 pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr); 549 ps3_write_pm(cpu, pm_control, pm_ctrl); 550 break; 551 552 case 32: 553 pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr); 554 ps3_write_pm(cpu, pm_control, pm_ctrl); 555 break; 556 default: 557 BUG(); 558 } 559 } 560 EXPORT_SYMBOL_GPL(ps3_set_ctr_size); 561 562 static u64 pm_translate_signal_group_number_on_island2(u64 subgroup) 563 { 564 565 if (subgroup == 2) 566 subgroup = 3; 567 568 if (subgroup <= 6) 569 return PM_ISLAND2_BASE_SIGNAL_GROUP_NUMBER + subgroup; 570 else if (subgroup == 7) 571 return PM_ISLAND2_SIGNAL_GROUP_NUMBER1; 572 else 573 return PM_ISLAND2_SIGNAL_GROUP_NUMBER2; 574 } 575 576 static u64 pm_translate_signal_group_number_on_island3(u64 subgroup) 577 { 578 579 switch (subgroup) { 580 case 2: 581 case 3: 582 case 4: 583 subgroup += 2; 584 break; 585 case 5: 586 subgroup = 8; 587 break; 588 default: 589 break; 590 } 591 return PM_ISLAND3_BASE_SIGNAL_GROUP_NUMBER + subgroup; 592 } 593 594 static u64 pm_translate_signal_group_number_on_island4(u64 subgroup) 595 { 596 return PM_ISLAND4_BASE_SIGNAL_GROUP_NUMBER + subgroup; 597 } 598 599 static u64 pm_translate_signal_group_number_on_island5(u64 subgroup) 600 { 601 602 switch (subgroup) { 603 case 3: 604 subgroup = 4; 605 break; 606 case 4: 607 subgroup = 6; 608 break; 609 default: 610 break; 611 } 612 return PM_ISLAND5_BASE_SIGNAL_GROUP_NUMBER + subgroup; 613 } 614 615 static u64 pm_translate_signal_group_number_on_island6(u64 subgroup, 616 u64 subsubgroup) 617 { 618 switch (subgroup) { 619 case 3: 620 case 4: 621 case 5: 622 subgroup += 1; 623 break; 624 default: 625 break; 626 } 627 628 switch (subsubgroup) { 629 case 4: 630 case 5: 631 case 6: 632 subsubgroup += 2; 633 break; 634 case 7: 635 case 8: 636 case 9: 637 case 10: 638 subsubgroup += 4; 639 break; 640 case 11: 641 case 12: 642 case 13: 643 subsubgroup += 5; 644 break; 645 default: 646 break; 647 } 648 649 if (subgroup <= 5) 650 return (PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER + subgroup); 651 else 652 return (PM_ISLAND6_BASE_SIGNAL_GROUP_NUMBER + subgroup 653 + subsubgroup - 1); 654 } 655 656 static u64 pm_translate_signal_group_number_on_island7(u64 subgroup) 657 { 658 return PM_ISLAND7_BASE_SIGNAL_GROUP_NUMBER + subgroup; 659 } 660 661 static u64 pm_translate_signal_group_number_on_island8(u64 subgroup) 662 { 663 return PM_ISLAND8_BASE_SIGNAL_GROUP_NUMBER + subgroup; 664 } 665 666 static u64 pm_signal_group_to_ps3_lv1_signal_group(u64 group) 667 { 668 u64 island; 669 u64 subgroup; 670 u64 subsubgroup; 671 672 subgroup = 0; 673 subsubgroup = 0; 674 island = 0; 675 if (group < 1000) { 676 if (group < 100) { 677 if (20 <= group && group < 30) { 678 island = 2; 679 subgroup = group - 20; 680 } else if (30 <= group && group < 40) { 681 island = 3; 682 subgroup = group - 30; 683 } else if (40 <= group && group < 50) { 684 island = 4; 685 subgroup = group - 40; 686 } else if (50 <= group && group < 60) { 687 island = 5; 688 subgroup = group - 50; 689 } else if (60 <= group && group < 70) { 690 island = 6; 691 subgroup = group - 60; 692 } else if (70 <= group && group < 80) { 693 island = 7; 694 subgroup = group - 70; 695 } else if (80 <= group && group < 90) { 696 island = 8; 697 subgroup = group - 80; 698 } 699 } else if (200 <= group && group < 300) { 700 island = 2; 701 subgroup = group - 200; 702 } else if (600 <= group && group < 700) { 703 island = 6; 704 subgroup = 5; 705 subsubgroup = group - 650; 706 } 707 } else if (6000 <= group && group < 7000) { 708 island = 6; 709 subgroup = 5; 710 subsubgroup = group - 6500; 711 } 712 713 switch (island) { 714 case 2: 715 return pm_translate_signal_group_number_on_island2(subgroup); 716 case 3: 717 return pm_translate_signal_group_number_on_island3(subgroup); 718 case 4: 719 return pm_translate_signal_group_number_on_island4(subgroup); 720 case 5: 721 return pm_translate_signal_group_number_on_island5(subgroup); 722 case 6: 723 return pm_translate_signal_group_number_on_island6(subgroup, 724 subsubgroup); 725 case 7: 726 return pm_translate_signal_group_number_on_island7(subgroup); 727 case 8: 728 return pm_translate_signal_group_number_on_island8(subgroup); 729 default: 730 dev_dbg(sbd_core(), "%s:%u: island not found: %lu\n", __func__, 731 __LINE__, group); 732 BUG(); 733 break; 734 } 735 return 0; 736 } 737 738 static u64 pm_bus_word_to_ps3_lv1_bus_word(u8 word) 739 { 740 741 switch (word) { 742 case 1: 743 return 0xF000; 744 case 2: 745 return 0x0F00; 746 case 4: 747 return 0x00F0; 748 case 8: 749 default: 750 return 0x000F; 751 } 752 } 753 754 static int __ps3_set_signal(u64 lv1_signal_group, u64 bus_select, 755 u64 signal_select, u64 attr1, u64 attr2, u64 attr3) 756 { 757 int ret; 758 759 ret = lv1_set_lpm_signal(lpm_priv->lpm_id, lv1_signal_group, bus_select, 760 signal_select, attr1, attr2, attr3); 761 if (ret) 762 dev_err(sbd_core(), 763 "%s:%u: error:%d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", 764 __func__, __LINE__, ret, lv1_signal_group, bus_select, 765 signal_select, attr1, attr2, attr3); 766 767 return ret; 768 } 769 770 int ps3_set_signal(u64 signal_group, u8 signal_bit, u16 sub_unit, 771 u8 bus_word) 772 { 773 int ret; 774 u64 lv1_signal_group; 775 u64 bus_select; 776 u64 signal_select; 777 u64 attr1, attr2, attr3; 778 779 if (signal_group == 0) 780 return __ps3_set_signal(0, 0, 0, 0, 0, 0); 781 782 lv1_signal_group = 783 pm_signal_group_to_ps3_lv1_signal_group(signal_group); 784 bus_select = pm_bus_word_to_ps3_lv1_bus_word(bus_word); 785 786 switch (signal_group) { 787 case PM_SIG_GROUP_SPU_TRIGGER: 788 signal_select = 1; 789 signal_select = signal_select << (63 - signal_bit); 790 break; 791 case PM_SIG_GROUP_SPU_EVENT: 792 signal_select = 1; 793 signal_select = (signal_select << (63 - signal_bit)) | 0x3; 794 break; 795 default: 796 signal_select = 0; 797 break; 798 } 799 800 /* 801 * 0: physical object. 802 * 1: logical object. 803 * This parameter is only used for the PPE and SPE signals. 804 */ 805 attr1 = 1; 806 807 /* 808 * This parameter is used to specify the target physical/logical 809 * PPE/SPE object. 810 */ 811 if (PM_SIG_GROUP_SPU <= signal_group && 812 signal_group < PM_SIG_GROUP_MFC_MAX) 813 attr2 = sub_unit; 814 else 815 attr2 = lpm_priv->pu_id; 816 817 /* 818 * This parameter is only used for setting the SPE signal. 819 */ 820 attr3 = 0; 821 822 ret = __ps3_set_signal(lv1_signal_group, bus_select, signal_select, 823 attr1, attr2, attr3); 824 if (ret) 825 dev_err(sbd_core(), "%s:%u: __ps3_set_signal failed: %d\n", 826 __func__, __LINE__, ret); 827 828 return ret; 829 } 830 EXPORT_SYMBOL_GPL(ps3_set_signal); 831 832 u32 ps3_get_hw_thread_id(int cpu) 833 { 834 return get_hard_smp_processor_id(cpu); 835 } 836 EXPORT_SYMBOL_GPL(ps3_get_hw_thread_id); 837 838 /** 839 * ps3_enable_pm - Enable the entire performance monitoring unit. 840 * 841 * When we enable the LPM, all pending writes to counters get committed. 842 */ 843 844 void ps3_enable_pm(u32 cpu) 845 { 846 int result; 847 u64 tmp; 848 int insert_bookmark = 0; 849 850 lpm_priv->tb_count = 0; 851 852 if (use_start_stop_bookmark) { 853 if (!(lpm_priv->shadow.pm_start_stop & 854 (PS3_PM_START_STOP_START_MASK 855 | PS3_PM_START_STOP_STOP_MASK))) { 856 result = lv1_set_lpm_trigger_control(lpm_priv->lpm_id, 857 (PS3_PM_START_STOP_PPU_TH0_BOOKMARK_START | 858 PS3_PM_START_STOP_PPU_TH1_BOOKMARK_START | 859 PS3_PM_START_STOP_PPU_TH0_BOOKMARK_STOP | 860 PS3_PM_START_STOP_PPU_TH1_BOOKMARK_STOP), 861 0xFFFFFFFFFFFFFFFFULL, &tmp); 862 863 if (result) 864 dev_err(sbd_core(), "%s:%u: " 865 "lv1_set_lpm_trigger_control failed: " 866 "%s\n", __func__, __LINE__, 867 ps3_result(result)); 868 869 insert_bookmark = !result; 870 } 871 } 872 873 result = lv1_start_lpm(lpm_priv->lpm_id); 874 875 if (result) 876 dev_err(sbd_core(), "%s:%u: lv1_start_lpm failed: %s\n", 877 __func__, __LINE__, ps3_result(result)); 878 879 if (use_start_stop_bookmark && !result && insert_bookmark) 880 ps3_set_bookmark(get_tb() | PS3_PM_BOOKMARK_START); 881 } 882 EXPORT_SYMBOL_GPL(ps3_enable_pm); 883 884 /** 885 * ps3_disable_pm - Disable the entire performance monitoring unit. 886 */ 887 888 void ps3_disable_pm(u32 cpu) 889 { 890 int result; 891 u64 tmp; 892 893 ps3_set_bookmark(get_tb() | PS3_PM_BOOKMARK_STOP); 894 895 result = lv1_stop_lpm(lpm_priv->lpm_id, &tmp); 896 897 if (result) { 898 if(result != LV1_WRONG_STATE) 899 dev_err(sbd_core(), "%s:%u: lv1_stop_lpm failed: %s\n", 900 __func__, __LINE__, ps3_result(result)); 901 return; 902 } 903 904 lpm_priv->tb_count = tmp; 905 906 dev_dbg(sbd_core(), "%s:%u: tb_count %lu (%lxh)\n", __func__, __LINE__, 907 lpm_priv->tb_count, lpm_priv->tb_count); 908 } 909 EXPORT_SYMBOL_GPL(ps3_disable_pm); 910 911 /** 912 * ps3_lpm_copy_tb - Copy data from the trace buffer to a kernel buffer. 913 * @offset: Offset in bytes from the start of the trace buffer. 914 * @buf: Copy destination. 915 * @count: Maximum count of bytes to copy. 916 * @bytes_copied: Pointer to a variable that will recieve the number of 917 * bytes copied to @buf. 918 * 919 * On error @buf will contain any successfully copied trace buffer data 920 * and bytes_copied will be set to the number of bytes successfully copied. 921 */ 922 923 int ps3_lpm_copy_tb(unsigned long offset, void *buf, unsigned long count, 924 unsigned long *bytes_copied) 925 { 926 int result; 927 928 *bytes_copied = 0; 929 930 if (!lpm_priv->tb_cache) 931 return -EPERM; 932 933 if (offset >= lpm_priv->tb_count) 934 return 0; 935 936 count = min(count, lpm_priv->tb_count - offset); 937 938 while (*bytes_copied < count) { 939 const unsigned long request = count - *bytes_copied; 940 u64 tmp; 941 942 result = lv1_copy_lpm_trace_buffer(lpm_priv->lpm_id, offset, 943 request, &tmp); 944 if (result) { 945 dev_dbg(sbd_core(), "%s:%u: 0x%lx bytes at 0x%lx\n", 946 __func__, __LINE__, request, offset); 947 948 dev_err(sbd_core(), "%s:%u: lv1_copy_lpm_trace_buffer " 949 "failed: %s\n", __func__, __LINE__, 950 ps3_result(result)); 951 return result == LV1_WRONG_STATE ? -EBUSY : -EINVAL; 952 } 953 954 memcpy(buf, lpm_priv->tb_cache, tmp); 955 buf += tmp; 956 *bytes_copied += tmp; 957 offset += tmp; 958 } 959 dev_dbg(sbd_core(), "%s:%u: copied %lxh bytes\n", __func__, __LINE__, 960 *bytes_copied); 961 962 return 0; 963 } 964 EXPORT_SYMBOL_GPL(ps3_lpm_copy_tb); 965 966 /** 967 * ps3_lpm_copy_tb_to_user - Copy data from the trace buffer to a user buffer. 968 * @offset: Offset in bytes from the start of the trace buffer. 969 * @buf: A __user copy destination. 970 * @count: Maximum count of bytes to copy. 971 * @bytes_copied: Pointer to a variable that will recieve the number of 972 * bytes copied to @buf. 973 * 974 * On error @buf will contain any successfully copied trace buffer data 975 * and bytes_copied will be set to the number of bytes successfully copied. 976 */ 977 978 int ps3_lpm_copy_tb_to_user(unsigned long offset, void __user *buf, 979 unsigned long count, unsigned long *bytes_copied) 980 { 981 int result; 982 983 *bytes_copied = 0; 984 985 if (!lpm_priv->tb_cache) 986 return -EPERM; 987 988 if (offset >= lpm_priv->tb_count) 989 return 0; 990 991 count = min(count, lpm_priv->tb_count - offset); 992 993 while (*bytes_copied < count) { 994 const unsigned long request = count - *bytes_copied; 995 u64 tmp; 996 997 result = lv1_copy_lpm_trace_buffer(lpm_priv->lpm_id, offset, 998 request, &tmp); 999 if (result) { 1000 dev_dbg(sbd_core(), "%s:%u: 0x%lx bytes at 0x%lx\n", 1001 __func__, __LINE__, request, offset); 1002 dev_err(sbd_core(), "%s:%u: lv1_copy_lpm_trace_buffer " 1003 "failed: %s\n", __func__, __LINE__, 1004 ps3_result(result)); 1005 return result == LV1_WRONG_STATE ? -EBUSY : -EINVAL; 1006 } 1007 1008 result = copy_to_user(buf, lpm_priv->tb_cache, tmp); 1009 1010 if (result) { 1011 dev_dbg(sbd_core(), "%s:%u: 0x%lx bytes at 0x%p\n", 1012 __func__, __LINE__, tmp, buf); 1013 dev_err(sbd_core(), "%s:%u: copy_to_user failed: %d\n", 1014 __func__, __LINE__, result); 1015 return -EFAULT; 1016 } 1017 1018 buf += tmp; 1019 *bytes_copied += tmp; 1020 offset += tmp; 1021 } 1022 dev_dbg(sbd_core(), "%s:%u: copied %lxh bytes\n", __func__, __LINE__, 1023 *bytes_copied); 1024 1025 return 0; 1026 } 1027 EXPORT_SYMBOL_GPL(ps3_lpm_copy_tb_to_user); 1028 1029 /** 1030 * ps3_get_and_clear_pm_interrupts - 1031 * 1032 * Clearing interrupts for the entire performance monitoring unit. 1033 * Reading pm_status clears the interrupt bits. 1034 */ 1035 1036 u32 ps3_get_and_clear_pm_interrupts(u32 cpu) 1037 { 1038 return ps3_read_pm(cpu, pm_status); 1039 } 1040 EXPORT_SYMBOL_GPL(ps3_get_and_clear_pm_interrupts); 1041 1042 /** 1043 * ps3_enable_pm_interrupts - 1044 * 1045 * Enabling interrupts for the entire performance monitoring unit. 1046 * Enables the interrupt bits in the pm_status register. 1047 */ 1048 1049 void ps3_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask) 1050 { 1051 if (mask) 1052 ps3_write_pm(cpu, pm_status, mask); 1053 } 1054 EXPORT_SYMBOL_GPL(ps3_enable_pm_interrupts); 1055 1056 /** 1057 * ps3_enable_pm_interrupts - 1058 * 1059 * Disabling interrupts for the entire performance monitoring unit. 1060 */ 1061 1062 void ps3_disable_pm_interrupts(u32 cpu) 1063 { 1064 ps3_get_and_clear_pm_interrupts(cpu); 1065 ps3_write_pm(cpu, pm_status, 0); 1066 } 1067 EXPORT_SYMBOL_GPL(ps3_disable_pm_interrupts); 1068 1069 /** 1070 * ps3_lpm_open - Open the logical performance monitor device. 1071 * @tb_type: Specifies the type of trace buffer lv1 sould use for this lpm 1072 * instance, specified by one of enum ps3_lpm_tb_type. 1073 * @tb_cache: Optional user supplied buffer to use as the trace buffer cache. 1074 * If NULL, the driver will allocate and manage an internal buffer. 1075 * Unused when when @tb_type is PS3_LPM_TB_TYPE_NONE. 1076 * @tb_cache_size: The size in bytes of the user supplied @tb_cache buffer. 1077 * Unused when @tb_cache is NULL or @tb_type is PS3_LPM_TB_TYPE_NONE. 1078 */ 1079 1080 int ps3_lpm_open(enum ps3_lpm_tb_type tb_type, void *tb_cache, 1081 u64 tb_cache_size) 1082 { 1083 int result; 1084 u64 tb_size; 1085 1086 BUG_ON(!lpm_priv); 1087 BUG_ON(tb_type != PS3_LPM_TB_TYPE_NONE 1088 && tb_type != PS3_LPM_TB_TYPE_INTERNAL); 1089 1090 if (tb_type == PS3_LPM_TB_TYPE_NONE && tb_cache) 1091 dev_dbg(sbd_core(), "%s:%u: bad in vals\n", __func__, __LINE__); 1092 1093 if (!atomic_add_unless(&lpm_priv->open, 1, 1)) { 1094 dev_dbg(sbd_core(), "%s:%u: busy\n", __func__, __LINE__); 1095 return -EBUSY; 1096 } 1097 1098 /* Note tb_cache needs 128 byte alignment. */ 1099 1100 if (tb_type == PS3_LPM_TB_TYPE_NONE) { 1101 lpm_priv->tb_cache_size = 0; 1102 lpm_priv->tb_cache_internal = NULL; 1103 lpm_priv->tb_cache = NULL; 1104 } else if (tb_cache) { 1105 if (tb_cache != (void *)_ALIGN_UP((unsigned long)tb_cache, 128) 1106 || tb_cache_size != _ALIGN_UP(tb_cache_size, 128)) { 1107 dev_err(sbd_core(), "%s:%u: unaligned tb_cache\n", 1108 __func__, __LINE__); 1109 result = -EINVAL; 1110 goto fail_align; 1111 } 1112 lpm_priv->tb_cache_size = tb_cache_size; 1113 lpm_priv->tb_cache_internal = NULL; 1114 lpm_priv->tb_cache = tb_cache; 1115 } else { 1116 lpm_priv->tb_cache_size = PS3_LPM_DEFAULT_TB_CACHE_SIZE; 1117 lpm_priv->tb_cache_internal = kzalloc( 1118 lpm_priv->tb_cache_size + 127, GFP_KERNEL); 1119 if (!lpm_priv->tb_cache_internal) { 1120 dev_err(sbd_core(), "%s:%u: alloc internal tb_cache " 1121 "failed\n", __func__, __LINE__); 1122 result = -ENOMEM; 1123 goto fail_malloc; 1124 } 1125 lpm_priv->tb_cache = (void *)_ALIGN_UP( 1126 (unsigned long)lpm_priv->tb_cache_internal, 128); 1127 } 1128 1129 result = lv1_construct_lpm(lpm_priv->node_id, tb_type, 0, 0, 1130 ps3_mm_phys_to_lpar(__pa(lpm_priv->tb_cache)), 1131 lpm_priv->tb_cache_size, &lpm_priv->lpm_id, 1132 &lpm_priv->outlet_id, &tb_size); 1133 1134 if (result) { 1135 dev_err(sbd_core(), "%s:%u: lv1_construct_lpm failed: %s\n", 1136 __func__, __LINE__, ps3_result(result)); 1137 result = -EINVAL; 1138 goto fail_construct; 1139 } 1140 1141 lpm_priv->shadow.pm_control = PS3_LPM_SHADOW_REG_INIT; 1142 lpm_priv->shadow.pm_start_stop = PS3_LPM_SHADOW_REG_INIT; 1143 lpm_priv->shadow.pm_interval = PS3_LPM_SHADOW_REG_INIT; 1144 lpm_priv->shadow.group_control = PS3_LPM_SHADOW_REG_INIT; 1145 lpm_priv->shadow.debug_bus_control = PS3_LPM_SHADOW_REG_INIT; 1146 1147 dev_dbg(sbd_core(), "%s:%u: lpm_id 0x%lx, outlet_id 0x%lx, " 1148 "tb_size 0x%lx\n", __func__, __LINE__, lpm_priv->lpm_id, 1149 lpm_priv->outlet_id, tb_size); 1150 1151 return 0; 1152 1153 fail_construct: 1154 kfree(lpm_priv->tb_cache_internal); 1155 lpm_priv->tb_cache_internal = NULL; 1156 fail_malloc: 1157 fail_align: 1158 atomic_dec(&lpm_priv->open); 1159 return result; 1160 } 1161 EXPORT_SYMBOL_GPL(ps3_lpm_open); 1162 1163 /** 1164 * ps3_lpm_close - Close the lpm device. 1165 * 1166 */ 1167 1168 int ps3_lpm_close(void) 1169 { 1170 dev_dbg(sbd_core(), "%s:%u\n", __func__, __LINE__); 1171 1172 lv1_destruct_lpm(lpm_priv->lpm_id); 1173 lpm_priv->lpm_id = 0; 1174 1175 kfree(lpm_priv->tb_cache_internal); 1176 lpm_priv->tb_cache_internal = NULL; 1177 1178 atomic_dec(&lpm_priv->open); 1179 return 0; 1180 } 1181 EXPORT_SYMBOL_GPL(ps3_lpm_close); 1182 1183 static int __devinit ps3_lpm_probe(struct ps3_system_bus_device *dev) 1184 { 1185 dev_dbg(&dev->core, " -> %s:%u\n", __func__, __LINE__); 1186 1187 if (lpm_priv) { 1188 dev_info(&dev->core, "%s:%u: called twice\n", 1189 __func__, __LINE__); 1190 return -EBUSY; 1191 } 1192 1193 lpm_priv = kzalloc(sizeof(*lpm_priv), GFP_KERNEL); 1194 1195 if (!lpm_priv) 1196 return -ENOMEM; 1197 1198 lpm_priv->sbd = dev; 1199 lpm_priv->node_id = dev->lpm.node_id; 1200 lpm_priv->pu_id = dev->lpm.pu_id; 1201 lpm_priv->rights = dev->lpm.rights; 1202 1203 dev_info(&dev->core, " <- %s:%u:\n", __func__, __LINE__); 1204 1205 return 0; 1206 } 1207 1208 static int ps3_lpm_remove(struct ps3_system_bus_device *dev) 1209 { 1210 dev_dbg(&dev->core, " -> %s:%u:\n", __func__, __LINE__); 1211 1212 ps3_lpm_close(); 1213 1214 kfree(lpm_priv); 1215 lpm_priv = NULL; 1216 1217 dev_info(&dev->core, " <- %s:%u:\n", __func__, __LINE__); 1218 return 0; 1219 } 1220 1221 static struct ps3_system_bus_driver ps3_lpm_driver = { 1222 .match_id = PS3_MATCH_ID_LPM, 1223 .core.name = "ps3-lpm", 1224 .core.owner = THIS_MODULE, 1225 .probe = ps3_lpm_probe, 1226 .remove = ps3_lpm_remove, 1227 .shutdown = ps3_lpm_remove, 1228 }; 1229 1230 static int __init ps3_lpm_init(void) 1231 { 1232 pr_debug("%s:%d:\n", __func__, __LINE__); 1233 return ps3_system_bus_driver_register(&ps3_lpm_driver); 1234 } 1235 1236 static void __exit ps3_lpm_exit(void) 1237 { 1238 pr_debug("%s:%d:\n", __func__, __LINE__); 1239 ps3_system_bus_driver_unregister(&ps3_lpm_driver); 1240 } 1241 1242 module_init(ps3_lpm_init); 1243 module_exit(ps3_lpm_exit); 1244 1245 MODULE_LICENSE("GPL v2"); 1246 MODULE_DESCRIPTION("PS3 Logical Performance Monitor Driver"); 1247 MODULE_AUTHOR("Sony Corporation"); 1248 MODULE_ALIAS(PS3_MODULE_ALIAS_LPM); 1249