[Skiboot] [PATCH v13 8/9] skiboot: Add opal calls to init/start/stop IMC devices

Michael Neuling mikey at neuling.org
Mon Jun 19 21:03:58 AEST 2017


On Mon, 2017-06-19 at 12:35 +0530, Madhavan Srinivasan wrote:
> From: Anju T Sudhakar <anju at linux.vnet.ibm.com>
> 
> Add new opal calls to init, start and stop the IMC nest/core units.
> To initialize the core IMC counters, it takes a physical address per
> core as an input and writes that address to PDBAR[14:50] bits.
> It initializes the htm_mode and event_mask, where it selects the time
> interval at which the counter values must be posted to the given memory
> location and enables the counters to start running by setting the
> appropriate bits.
> 
> To disable/enable the nest IMC counters (stop or resume counting),
> writes into "command" field of the nest control block in the reserve
> memory location. To disable/enable the core IMC counters (stop or
> resume counting), writes into appropriate bits of htm_mode to
> disable the counters.
> 
> Signed-off-by: Hemant Kumar <hemant at linux.vnet.ibm.com>
> Signed-off-by: Anju T Sudhakar <anju at linux.vnet.ibm.com>
> Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>

Acked-by: Michael Neuling <mikey at neuling.org>


> ---
>  hw/imc.c           | 193
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/imc.h      |   9 +++
>  include/opal-api.h |  12 +++-
>  3 files changed, 213 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/imc.c b/hw/imc.c
> index 696805ae23d2..d36f7ff59487 100644
> --- a/hw/imc.c
> +++ b/hw/imc.c
> @@ -94,6 +94,26 @@ static bool is_nest_mem_initialized(struct imc_chip_cb
> *ptr)
>  	return true;
>  }
>  
> +/*
> + * A Quad contains 4 cores in Power 9, and there are 4 addresses for
> + * the Core Hardware Trace Macro (CHTM) attached to each core.
> + * So, for core index 0 to core index 3, we have a sequential range of
> + * SCOM port addresses in the arrays below, each for Hardware Trace Macro
> (HTM)
> + * mode and PDBAR.
> + */
> +unsigned int pdbar_scom_index[] = {
> +	0x1001220B,
> +	0x1001230B,
> +	0x1001260B,
> +	0x1001270B
> +};
> +unsigned int htm_scom_index[] = {
> +	0x10012200,
> +	0x10012300,
> +	0x10012600,
> +	0x10012700
> +};
> +
>  static struct imc_chip_cb *get_imc_cb(uint32_t chip_id)
>  {
>  	struct proc_chip *chip = get_chip(chip_id);
> @@ -427,3 +447,176 @@ err:
>  	free(decompress_buf);
>  	free(compress_buf);
>  }
> +
> +/*
> + * opal_imc_counters_init : This call initialize the IMC engine.
> + *
> + * For Nest IMC, this is no-op and returns OPAL_SUCCESS at this point.
> + * For Core IMC, this initializes core IMC Engine, by initializing
> + * these scoms "PDBAR", "HTM_MODE" and the "EVENT_MASK" in a given cpu.
> + */
> +static int64_t opal_imc_counters_init(uint32_t type, uint64_t addr, uint64_t
> cpu_pir)
> +{
> +	struct cpu_thread *c = find_cpu_by_pir(cpu_pir);
> +	int port_id, phys_core_id;
> +
> +	switch (type) {
> +	case OPAL_IMC_COUNTERS_NEST:
> +		return OPAL_SUCCESS;
> +	case OPAL_IMC_COUNTERS_CORE:
> +		if (!c)
> +			return OPAL_PARAMETER;
> +
> +		/*
> +		 * Core IMC hardware mandates setting of htm_mode and
> +		 * pdbar in specific scom ports. port_id are in
> +		 * pdbar_scom_index[] and htm_scom_index[].
> +		 */
> +		phys_core_id = cpu_get_core_index(c);
> +		port_id = phys_core_id % 4;
> +
> +		/*
> +		 * Core IMC hardware mandate initing of three scoms
> +		 * to enbale or disable of the Core IMC engine.
> +		 *
> +		 * PDBAR: Scom contains the real address to store per-core
> +		 *        counter data in memory along with other bits.
> +		 *
> +		 * EventMask: Scom contain bits to denote event to multiplex
> +		 *            at different MSR[HV PR] values, along with bits
> for
> +		 *            sampling duration.
> +		 *
> +		 * HTM Scom: scom to enable counter data movement to memory.
> +		 */
> +		 if (xscom_write(c->chip_id,
> +				XSCOM_ADDR_P9_EP(phys_core_id,
> +						pdbar_scom_index[port_id]),
> +				(u64)(CORE_IMC_PDBAR_MASK & addr))) {
> +			prerror("IMC: error in xscom_write for pdbar\n");
> +			return OPAL_HARDWARE;
> +		}
> +
> +		if (xscom_write(c->chip_id,
> +				XSCOM_ADDR_P9_EC(phys_core_id,
> +					 CORE_IMC_EVENT_MASK_ADDR),
> +				(u64)CORE_IMC_EVENT_MASK)) {
> +			prerror("IMC: error in xscom_write for event
> mask\n");
> +			return OPAL_HARDWARE;
> +		}
> +
> +		if (xscom_write(c->chip_id,
> +				XSCOM_ADDR_P9_EP(phys_core_id,
> +						htm_scom_index[port_id]),
> +				(u64)CORE_IMC_HTM_MODE_DISABLE)) {
> +			prerror("IMC: error in xscom_write for htm mode\n");
> +			return OPAL_HARDWARE;
> +		}
> +		return OPAL_SUCCESS;
> +	}
> +
> +	return OPAL_SUCCESS;
> +}
> +opal_call(OPAL_IMC_COUNTERS_INIT, opal_imc_counters_init, 3);
> +
> +/* opal_imc_counters_control_start: This call starts the nest/core imc
> engine. */
> +static int64_t opal_imc_counters_start(uint32_t type, uint64_t cpu_pir)
> +{
> +	u64 op;
> +	struct cpu_thread *c = find_cpu_by_pir(cpu_pir);
> +	struct imc_chip_cb *cb;
> +	int port_id, phys_core_id;
> +
> +	if (!c)
> +		return OPAL_PARAMETER;
> +
> +	switch (type) {
> +	case OPAL_IMC_COUNTERS_NEST:
> +		/* Fetch the IMC control block structure */
> +		cb = get_imc_cb(c->chip_id);
> +
> +		/* Set the run command */
> +		op = NEST_IMC_ENABLE;
> +
> +		/* Write the command to the control block now */
> +		cb->imc_chip_command = cpu_to_be64(op);
> +
> +		return OPAL_SUCCESS;
> +	case OPAL_IMC_COUNTERS_CORE:
> +		/*
> +		 * Core IMC hardware mandates setting of htm_mode in specific
> +		 * scom ports (port_id are in htm_scom_index[])
> +		 */
> +		phys_core_id = cpu_get_core_index(c);
> +		port_id = phys_core_id % 4;
> +
> +		/*
> +		 * Enables the core imc engine by appropriately setting
> +		 * bits 4-9 of the HTM_MODE scom port. No initialization
> +		 * is done in this call. This just enables the the counters
> +		 * to count with the previous initialization.
> +		 */
> +		if (xscom_write(c->chip_id,
> +				XSCOM_ADDR_P9_EP(phys_core_id,
> +						htm_scom_index[port_id]),
> +				(u64)CORE_IMC_HTM_MODE_ENABLE)) {
> +			prerror("IMC OPAL_start: error in xscom_write for
> htm_mode\n");
> +			return OPAL_HARDWARE;
> +		}
> +
> +		return OPAL_SUCCESS;
> +	}
> +
> +	return OPAL_SUCCESS;
> +}
> +opal_call(OPAL_IMC_COUNTERS_START, opal_imc_counters_start, 2);
> +
> +/* opal_imc_counters_control_stop: This call stops the nest imc engine. */
> +static int64_t opal_imc_counters_stop(uint32_t type, uint64_t cpu_pir)
> +{
> +	u64 op;
> +	struct imc_chip_cb *cb;
> +	struct cpu_thread *c = find_cpu_by_pir(cpu_pir);
> +	int port_id, phys_core_id;
> +
> +	if (!c)
> +		return OPAL_PARAMETER;
> +
> +	switch (type) {
> +	case OPAL_IMC_COUNTERS_NEST:
> +		/* Fetch the IMC control block structure */
> +		cb = get_imc_cb(c->chip_id);
> +
> +		/* Set the run command */
> +		op = NEST_IMC_DISABLE;
> +
> +		/* Write the command to the control block */
> +		cb->imc_chip_command = cpu_to_be64(op);
> +
> +		return OPAL_SUCCESS;
> +
> +	case OPAL_IMC_COUNTERS_CORE:
> +		/*
> +		 * Core IMC hardware mandates setting of htm_mode in specific
> +		 * scom ports (port_id are in htm_scom_index[])
> +		 */
> +		phys_core_id = cpu_get_core_index(c);
> +		port_id = phys_core_id % 4;
> +
> +		/*
> +		 * Disables the core imc engine by clearing
> +		 * bits 4-9 of the HTM_MODE scom port.
> +		 */
> +		if (xscom_write(c->chip_id,
> +				XSCOM_ADDR_P9_EP(phys_core_id,
> +						htm_scom_index[port_id]),
> +				(u64) CORE_IMC_HTM_MODE_DISABLE)) {
> +			prerror("IMC: error in xscom_write for htm_mode\n");
> +			return OPAL_HARDWARE;
> +		}
> +
> +		return OPAL_SUCCESS;
> +	}
> +
> +	return OPAL_SUCCESS;
> +}
> +opal_call(OPAL_IMC_COUNTERS_STOP, opal_imc_counters_stop, 2);
> diff --git a/include/imc.h b/include/imc.h
> index fcd220d1b316..d4381bb2adae 100644
> --- a/include/imc.h
> +++ b/include/imc.h
> @@ -121,6 +121,15 @@ struct imc_chip_cb
>  
>  #define MAX_NEST_UNITS			48
>  
> +/*
> + * Core IMC SCOMs
> + */
> +#define CORE_IMC_EVENT_MASK_ADDR	0x20010AA8ull
> +#define CORE_IMC_EVENT_MASK		0x0001020000000000ull
> +#define CORE_IMC_PDBAR_MASK		0x0003ffffffffe000ull
> +#define CORE_IMC_HTM_MODE_ENABLE	0xE800000000000000ull
> +#define CORE_IMC_HTM_MODE_DISABLE	0xE000000000000000ull
> +
>  void imc_init(void);
>  void imc_catalog_preload(void);
>  #endif /* __IMC_H */
> diff --git a/include/opal-api.h b/include/opal-api.h
> index 80033c6fa77f..6497c94cd46a 100644
> --- a/include/opal-api.h
> +++ b/include/opal-api.h
> @@ -204,7 +204,10 @@
>  #define OPAL_NPU_INIT_CONTEXT			146
>  #define OPAL_NPU_DESTROY_CONTEXT		147
>  #define OPAL_NPU_MAP_LPAR			148
> -#define OPAL_LAST				148
> +#define OPAL_IMC_COUNTERS_INIT			149
> +#define OPAL_IMC_COUNTERS_START			150
> +#define OPAL_IMC_COUNTERS_STOP			151
> +#define OPAL_LAST				151
>  
>  /* Device tree flags */
>  
> @@ -1215,6 +1218,13 @@ enum {
>  	XIVE_DUMP_EMU_STATE	= 5,
>  };
>  
> +/* Operation argument to IMC Microcode */
> +enum {
> +	OPAL_IMC_COUNTERS_NEST = 1,
> +	OPAL_IMC_COUNTERS_CORE = 2,
> +};
> +
> +
>  #endif /* __ASSEMBLY__ */
>  
>  #endif /* __OPAL_API_H */


More information about the Skiboot mailing list