/** * struct ps3_lpm_shadow_regs - Performance monitor shadow registers. * * @pm_control: Shadow of the processor's pm_control register. * @pm_start_stop: Shadow of the processor's pm_start_stop register. * @group_control: Shadow of the processor's group_control register. * @debug_bus_control: Shadow of the processor's debug_bus_control register. * * The logical performance monitor provides a write-only interface to * these processor registers. These shadow variables cache the processor * register values for reading. * * The initial value of the shadow registers at lpm creation is * PS3_LPM_SHADOW_REG_INIT.
*/
/** * struct ps3_lpm_priv - Private lpm device data. * * @open: An atomic variable indicating the lpm driver has been opened. * @rights: The lpm rights granted by the system policy module. A logical * OR of enum ps3_lpm_rights. * @node_id: The node id of a BE processor whose performance monitor this * lpar has the right to use. * @pu_id: The lv1 id of the logical PU. * @lpm_id: The lv1 id of this lpm instance. * @outlet_id: The outlet created by lv1 for this lpm instance. * @tb_count: The number of bytes of data held in the lv1 trace buffer. * @tb_cache: Kernel buffer to receive the data from the lv1 trace buffer. * Must be 128 byte aligned. * @tb_cache_size: Size of the kernel @tb_cache buffer. Must be 128 byte * aligned. * @tb_cache_internal: An unaligned buffer allocated by this driver to be * used for the trace buffer cache when ps3_lpm_open() is called with a * NULL tb_cache argument. Otherwise unused. * @shadow: Processor register shadow of type struct ps3_lpm_shadow_regs. * @sbd: The struct ps3_system_bus_device attached to this driver. * * The trace buffer is a buffer allocated and used internally to the lv1 * hypervisor to collect trace data. The trace buffer cache is a guest * buffer that accepts the trace data from the trace buffer.
*/
/** * lpm_priv - Static instance of the lpm data. * * Since the exported routines don't support the notion of a device * instance we need to hold the instance in this static variable * and then only allow at most one instance at a time to be created.
*/
/** * use_start_stop_bookmark - Enable the PPU bookmark trace. * * And it enables PPU bookmark triggers ONLY if the other triggers are not set. * The start/stop bookmarks are inserted at ps3_enable_pm() and ps3_disable_pm() * to start/stop LPM. * * Used to get good quality of the performance counter.
*/
enum {use_start_stop_bookmark = 1,};
void ps3_set_bookmark(u64 bookmark)
{ /* * As per the PPE book IV, to avoid bookmark loss there must * not be a traced branch within 10 cycles of setting the * SPRN_BKMK register. The actual text is unclear if 'within' * includes cycles before the call.
*/
if (ps3_get_ctr_size(cpu, phys_ctr) == 16)
val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff);
return val;
}
EXPORT_SYMBOL_GPL(ps3_read_ctr);
/** * ps3_write_ctr - Write counter. * * Write 16 or 32 bits depending on the current size of the counter. * Counters 4, 5, 6 & 7 are always 16 bit.
*/
static u64 pm_translate_signal_group_number_on_island6(u64 subgroup,
u64 subsubgroup)
{ switch (subgroup) { case 3: case 4: case 5:
subgroup += 1; break; default: break;
}
switch (subsubgroup) { case 4: case 5: case 6:
subsubgroup += 2; break; case 7: case 8: case 9: case 10:
subsubgroup += 4; break; case 11: case 12: case 13:
subsubgroup += 5; break; default: break;
}
subgroup = 0;
subsubgroup = 0;
island = 0; if (group < 1000) { if (group < 100) { if (20 <= group && group < 30) {
island = 2;
subgroup = group - 20;
} elseif (30 <= group && group < 40) {
island = 3;
subgroup = group - 30;
} elseif (40 <= group && group < 50) {
island = 4;
subgroup = group - 40;
} elseif (50 <= group && group < 60) {
island = 5;
subgroup = group - 50;
} elseif (60 <= group && group < 70) {
island = 6;
subgroup = group - 60;
} elseif (70 <= group && group < 80) {
island = 7;
subgroup = group - 70;
} elseif (80 <= group && group < 90) {
island = 8;
subgroup = group - 80;
}
} elseif (200 <= group && group < 300) {
island = 2;
subgroup = group - 200;
} elseif (600 <= group && group < 700) {
island = 6;
subgroup = 5;
subsubgroup = group - 650;
}
} elseif (6000 <= group && group < 7000) {
island = 6;
subgroup = 5;
subsubgroup = group - 6500;
}
switch (island) { case 2: return pm_translate_signal_group_number_on_island2(subgroup); case 3: return pm_translate_signal_group_number_on_island3(subgroup); case 4: return pm_translate_signal_group_number_on_island4(subgroup); case 5: return pm_translate_signal_group_number_on_island5(subgroup); case 6: return pm_translate_signal_group_number_on_island6(subgroup,
subsubgroup); case 7: return pm_translate_signal_group_number_on_island7(subgroup); case 8: return pm_translate_signal_group_number_on_island8(subgroup); default:
dev_dbg(sbd_core(), "%s:%u: island not found: %llu\n", __func__,
__LINE__, group);
BUG(); break;
} return 0;
}
/* * 0: physical object. * 1: logical object. * This parameter is only used for the PPE and SPE signals.
*/
attr1 = 1;
/* * This parameter is used to specify the target physical/logical * PPE/SPE object.
*/ if (PM_SIG_GROUP_SPU <= signal_group &&
signal_group < PM_SIG_GROUP_MFC_MAX)
attr2 = sub_unit; else
attr2 = lpm_priv->pu_id;
/* * This parameter is only used for setting the SPE signal.
*/
attr3 = 0;
ret = __ps3_set_signal(lv1_signal_group, bus_select, signal_select,
attr1, attr2, attr3); if (ret)
dev_err(sbd_core(), "%s:%u: __ps3_set_signal failed: %d\n",
__func__, __LINE__, ret);
/** * ps3_lpm_copy_tb - Copy data from the trace buffer to a kernel buffer. * @offset: Offset in bytes from the start of the trace buffer. * @buf: Copy destination. * @count: Maximum count of bytes to copy. * @bytes_copied: Pointer to a variable that will receive the number of * bytes copied to @buf. * * On error @buf will contain any successfully copied trace buffer data * and bytes_copied will be set to the number of bytes successfully copied.
*/
int ps3_lpm_copy_tb(unsignedlong offset, void *buf, unsignedlong count, unsignedlong *bytes_copied)
{ int result;
/** * ps3_lpm_copy_tb_to_user - Copy data from the trace buffer to a user buffer. * @offset: Offset in bytes from the start of the trace buffer. * @buf: A __user copy destination. * @count: Maximum count of bytes to copy. * @bytes_copied: Pointer to a variable that will receive the number of * bytes copied to @buf. * * On error @buf will contain any successfully copied trace buffer data * and bytes_copied will be set to the number of bytes successfully copied.
*/
int ps3_lpm_copy_tb_to_user(unsignedlong offset, void __user *buf, unsignedlong count, unsignedlong *bytes_copied)
{ int result;
/** * ps3_enable_pm_interrupts - * * Enabling interrupts for the entire performance monitoring unit. * Enables the interrupt bits in the pm_status register.
*/
/** * ps3_lpm_open - Open the logical performance monitor device. * @tb_type: Specifies the type of trace buffer lv1 should use for this lpm * instance, specified by one of enum ps3_lpm_tb_type. * @tb_cache: Optional user supplied buffer to use as the trace buffer cache. * If NULL, the driver will allocate and manage an internal buffer. * Unused when @tb_type is PS3_LPM_TB_TYPE_NONE. * @tb_cache_size: The size in bytes of the user supplied @tb_cache buffer. * Unused when @tb_cache is NULL or @tb_type is PS3_LPM_TB_TYPE_NONE.
*/
int ps3_lpm_open(enum ps3_lpm_tb_type tb_type, void *tb_cache,
u64 tb_cache_size)
{ int result;
u64 tb_size;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.