cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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);