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