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