[PATCH] powerpc/perf: Add debugfs interface for imc run-mode and run-status

Anju T Sudhakar anju at linux.vnet.ibm.com
Mon Nov 13 16:38:55 AEDT 2017


Hi,

Kindly ignore this version

Thanks,
Anju

On Monday 13 November 2017 11:06 AM, Anju T Sudhakar wrote:
> In memory Collection (IMC) counter pmu driver controls the ucode's execution
> state. At the system boot, IMC perf driver pause the ucode. Ucode state is
> changed to "running" only when any of the nest units are monitored or profiled
> using perf tool.
>                                                                                  
> Nest units support only limited set of hardware counters and ucode is always
> programmed in the "production mode" ("accumulation") mode. This mode is
> configured to provide key performance metric data for most of the nest units.
>                                                                                  
> But ucode also supports other modes which would be used for "debug" to drill
> down specific nest units. That is, ucode when switched to "powerbus" debug
> mode (for example), will dynamically reconfigure the nest counters to target
> only "powerbus" related events in the hardware counters. This allows the IMC
> nest unit to focus on powerbus related transactions in the system in more
> detail. At this point, production mode events may or may not be counted.
>                                                                                  
> IMC nest counters has both in-band (ucode access) and out of band access to it.
> Since not all nest counter configurations are supported by ucode, out of band
> tools are used to characterize other nest counter configurations.
>                                                                                  
> Patch provides an interface via "debugfs" to enable the switching of ucode
> modes in the system. To switch ucode mode, one has to first pause the microcode
> (imc_cmd), and then write the target mode value to the "imc_mode" file.
>                                                                                  
> Proposed Approach
> ===================
>                                                                                  
> In the proposed approach, the function (export_imc_mode_and_cmd) which creates
> the debugfs interface for imc mode and command is implemented in opal-imc.c.
> Thus we can use imc_get_mem_addr() to get the homer base address for each chip.
>                                                                                  
> The interface to expose imc mode and command is required only if we have nest
> pmu units registered. Employing the existing data structures to track whether
> we have any nest units registered will require to extend data from perf side
> to opal-imc.c. Instead an integer is introduced to hold that information by
> counting successful nest unit registration. Debugfs interface is removed
> based on the integer count.
>
> Example for the interface:
>                                                                                  
> root at XXXX:/sys/kernel/debug/imc# ls
> imc_cmd_0  imc_cmd_8  imc_mode_0  imc_mode_8
>                                                                                  
> Signed-off-by: Anju T Sudhakar <anju at linux.vnet.ibm.com>
> ---
>   arch/powerpc/include/asm/imc-pmu.h        |  7 +++
>   arch/powerpc/platforms/powernv/opal-imc.c | 74 ++++++++++++++++++++++++++++++-
>   2 files changed, 79 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/imc-pmu.h b/arch/powerpc/include/asm/imc-pmu.h
> index 7f74c28..317002d 100644
> --- a/arch/powerpc/include/asm/imc-pmu.h
> +++ b/arch/powerpc/include/asm/imc-pmu.h
> @@ -40,6 +40,13 @@
>   #define THREAD_IMC_ENABLE               0x8000000000000000ULL
>
>   /*
> + * For debugfs interface for imc-mode and imc-command
> + */
> +#define IMC_CNTL_BLK_OFFSET		0x3FC00
> +#define IMC_CNTL_BLK_CMD_OFFSET		8
> +#define IMC_CNTL_BLK_MODE_OFFSET	32
> +
> +/*
>    * Structure to hold memory address information for imc units.
>    */
>   struct imc_mem_info {
> diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c
> index 21f6531..a88ddab 100644
> --- a/arch/powerpc/platforms/powernv/opal-imc.c
> +++ b/arch/powerpc/platforms/powernv/opal-imc.c
> @@ -21,6 +21,70 @@
>   #include <asm/io.h>
>   #include <asm/imc-pmu.h>
>   #include <asm/cputhreads.h>
> +#include <linux/debugfs.h>
> +
> +static struct dentry *parent;
> +
> +/* Helpers to export imc command and status via debugfs */
> +static int debugfs_imc_mem_get(void *data, u64 *val)
> +{
> +	*val = cpu_to_be64(*(u64 *)data);
> +	return 0;
> +}
> +
> +static int debugfs_imc_mem_set(void *data, u64 val)
> +{
> +	*(u64 *)data = cpu_to_be64(val);
> +	return 0;
> +}
> +DEFINE_DEBUGFS_ATTRIBUTE(fops_imc_x64, debugfs_imc_mem_get, debugfs_imc_mem_set,
> +								"0x%016llx\n");
> +
> +static struct dentry *debugfs_create_imc_x64(const char *name, umode_t mode,
> +					    struct dentry *parent, u64  *value)
> +{
> +	return debugfs_create_file_unsafe(name, mode, parent, value, &fops_imc_x64);
> +}
> +
> +/*
> + * export_imc_mode_and_cmd: Create a debugfs interface
> + *                     for imc_cmd and imc_mode
> + *                     for each node in the system.
> + *  imc_mode and imc_cmd can be changed by echo into
> + *  this interface.
> + */
> +static void export_imc_mode_and_cmd(struct imc_pmu *pmu_ptr)
> +{
> +	static u64 loc, *imc_mode_addr, *imc_cmd_addr;
> +	int i = 0, nid;
> +	char mode[16], cmd[16];
> +
> +	parent = debugfs_create_dir("imc", NULL);
> +	/*
> +	 * Return here, either because 'imc' directory already exists,
> +	 * Or failed to create a new one.
> +	 */
> +	if (!parent)
> +		return;
> +
> +	for_each_node(nid) {
> +		loc = (u64)(pmu_ptr->mem_info[i].vbase) + IMC_CNTL_BLK_OFFSET;
> +		imc_mode_addr = (u64 *)(loc + IMC_CNTL_BLK_MODE_OFFSET);
> +		sprintf(mode, "imc_mode_%d", nid);
> +		if (!debugfs_create_imc_x64(mode, 0600, parent, imc_mode_addr))
> +			goto err;
> +
> +		imc_cmd_addr = (u64 *)(loc + IMC_CNTL_BLK_CMD_OFFSET);
> +		sprintf(cmd, "imc_cmd_%d", nid);
> +		if (!debugfs_create_imc_x64(cmd, 0600, parent, imc_cmd_addr))
> +			goto err;
> +		i++;
> +	}
> +	return;
> +
> +err:
> +	debugfs_remove_recursive(parent);
> +}
>
>   /*
>    * imc_get_mem_addr_nest: Function to get nest counter memory region
> @@ -65,6 +129,7 @@ static int imc_get_mem_addr_nest(struct device_node *node,
>   	}
>
>   	pmu_ptr->imc_counter_mmaped = true;
> +	export_imc_mode_and_cmd(pmu_ptr);
>   	kfree(base_addr_arr);
>   	kfree(chipid_arr);
>   	return 0;
> @@ -156,7 +221,7 @@ static void disable_core_pmu_counters(void)
>   static int opal_imc_counters_probe(struct platform_device *pdev)
>   {
>   	struct device_node *imc_dev = pdev->dev.of_node;
> -	int pmu_count = 0, domain;
> +	int pmu_count = 0, domain, nest_pmus = 0;
>   	u32 type;
>
>   	/*
> @@ -191,9 +256,14 @@ static int opal_imc_counters_probe(struct platform_device *pdev)
>   			break;
>   		}
>
> -		if (!imc_pmu_create(imc_dev, pmu_count, domain))
> +		if (!imc_pmu_create(imc_dev, pmu_count, domain)) {
> +			if (domain == IMC_DOMAIN_NEST)
> +				nest_pmus++;
>   			pmu_count++;
> +		}
>   	}
> +	if (nest_pmus == 0)
> +		debugfs_remove_recursive(parent);
>
>   	return 0;
>   }



More information about the Linuxppc-dev mailing list