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

Madhavan Srinivasan maddy at linux.vnet.ibm.com
Sun Jun 18 22:35:38 AEST 2017


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>
---
 hw/imc.c           | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/imc.h      |   9 +++
 include/opal-api.h |  12 +++-
 3 files changed, 228 insertions(+), 1 deletion(-)

diff --git a/hw/imc.c b/hw/imc.c
index 696805ae23d2..48c940f7ee99 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,191 @@ 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);
+	struct proc_chip *chip;
+	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;
+
+		chip = get_chip(c->chip_id);
+		if (chip)
+			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(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(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(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;
+	struct proc_chip *chip;
+	int port_id, phys_core_id;
+
+	if (!c)
+		return OPAL_PARAMETER;
+
+	chip = get_chip(c->chip_id);
+	if (chip)
+		return OPAL_PARAMETER;
+
+	switch (type) {
+	case OPAL_IMC_COUNTERS_NEST:
+		/* Fetch the IMC control block structure */
+		cb = get_imc_cb(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(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);
+	struct proc_chip *chip;
+	int port_id, phys_core_id;
+
+	if (!c)
+		return OPAL_PARAMETER;
+
+	chip = get_chip(c->chip_id);
+	if (chip)
+		return OPAL_PARAMETER;
+
+	switch (type) {
+	case OPAL_IMC_COUNTERS_NEST:
+		/* Fetch the IMC control block structure */
+		cb = get_imc_cb(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(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 */
-- 
2.7.4



More information about the Skiboot mailing list