[Skiboot] [PATCH v10 10/11] skiboot: Add core IMC related counter configuration
Madhavan Srinivasan
maddy at linux.vnet.ibm.com
Thu May 4 14:42:13 AEST 2017
From: Anju T Sudhakar <anju at linux.vnet.ibm.com>
Add support to start, stop and initialize the core IMC counters.
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 also initializes the event_mask with time interval to posted the
core imc counter data to the given memory location. Finally, htc_mode
scom bits controls core imc engine (start/stop).
Signed-off-by: Hemant Kumar <hemant at linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
Signed-off-by: Anju T Sudhakar <anju at linux.vnet.ibm.com>
---
hw/imc.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++----
include/imc.h | 10 ++++
include/opal-api.h | 1 +
3 files changed, 144 insertions(+), 11 deletions(-)
diff --git a/hw/imc.c b/hw/imc.c
index 67f199c04949..183d0eab8923 100644
--- a/hw/imc.c
+++ b/hw/imc.c
@@ -83,6 +83,26 @@ size_t imc_catalog_size;
const char **imc_prop_to_fix(struct dt_node *node);
const char *prop_to_fix[] = {"events", NULL};
+
+/*
+ * A Quad contains 4 cores in Power 9, and there are 4 addresses for
+ * the 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 PDBAR and HTM mode.
+ */
+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(void)
{
uint64_t cb_loc;
@@ -158,7 +178,9 @@ err:
*/
const char **imc_prop_to_fix(struct dt_node *node)
{
- if (dt_node_is_compatible(node, "ibm,imc-counters-nest"))
+ if (dt_node_is_compatible(node, "ibm,imc-counters-nest") ||
+ dt_node_is_compatible(node, "ibm,imc-counters-core") ||
+ dt_node_is_compatible(node, "ibm,imc-counters-thread"))
return prop_to_fix;
return NULL;
@@ -282,26 +304,84 @@ err:
}
/*
- * opal_imc_counters_init : This call initialize the IMC engine.
- *
+ * opal_imc_counters_init : This call initializes core IMC Engine for the
+ * current core, by initializing the pdbars, htm_mode,
+ * and the event_mask.
* This call is not being used in case of NEST IMC.
- * Additional arguments will be added to this call in the following patch.
*/
-static int64_t opal_imc_counters_init(uint32_t type)
+static int64_t opal_imc_counters_init(uint32_t type, uint64_t addr)
{
- if (type == OPAL_IMC_COUNTERS_NEST)
+ struct proc_chip *chip;
+ int core_id, phys_core_id, ret = OPAL_PARAMETER;
+
+ switch (type) {
+ case OPAL_IMC_COUNTERS_NEST:
prerror("IMC: unknown operation for nest imc\n");
+ break;
+ case OPAL_IMC_COUNTERS_CORE:
+ chip = get_chip(this_cpu()->chip_id);
+ phys_core_id = cpu_get_core_index(this_cpu());
+ core_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.
+ */
+ ret = xscom_write(chip->id,
+ XSCOM_ADDR_P9_EP(phys_core_id,
+ pdbar_scom_index[core_id]),
+ (u64)(CORE_IMC_PDBAR_MASK & addr));
+ if (ret < 0) {
+ prerror("IMC: error in xscom_write for pdbar\n");
+ goto hw_err;
+ }
- return OPAL_SUCCESS;
+ ret = xscom_write(chip->id,
+ XSCOM_ADDR_P9_EC(phys_core_id,
+ CORE_IMC_EVENT_MASK_ADDR),
+ (u64)CORE_IMC_EVENT_MASK);
+ if (ret < 0) {
+ prerror("IMC: error in xscom_write for event mask\n");
+ goto hw_err;
+ }
+
+ ret = xscom_write(chip->id,
+ XSCOM_ADDR_P9_EP(phys_core_id,
+ htm_scom_index[core_id]),
+ (u64)CORE_IMC_HTM_MODE_DISABLE);
+ if (ret < 0) {
+ prerror("IMC: error in xscom_write for htm mode\n");
+ goto hw_err;
+ }
+
+ ret = OPAL_SUCCESS;
+ break;
+ default:
+ return ret;
+ }
+
+ return ret;
+hw_err:
+ return OPAL_HARDWARE;
}
-opal_call(OPAL_IMC_COUNTERS_INIT, opal_imc_counters_init, 1);
+opal_call(OPAL_IMC_COUNTERS_INIT, opal_imc_counters_init, 2);
-/* opal_imc_counters_control_start: This call starts the nest imc engine. */
+/* opal_imc_counters_control_start: This call starts the nest/core imc engine. */
static int64_t opal_imc_counters_start(uint32_t type)
{
u64 op, status;
struct imc_chip_cb *cb;
- int ret = OPAL_SUCCESS;
+ struct proc_chip *chip;
+ int core_id, phys_core_id, ret = OPAL_SUCCESS;
switch (type) {
case OPAL_IMC_COUNTERS_NEST:
@@ -320,6 +400,28 @@ static int64_t opal_imc_counters_start(uint32_t type)
cb->imc_chip_command = op;
break;
+ case OPAL_IMC_COUNTERS_CORE:
+ /*
+ * 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.
+ */
+ chip = get_chip(this_cpu()->chip_id);
+ phys_core_id = cpu_get_core_index(this_cpu());
+ core_id = phys_core_id % 4;
+
+ ret = xscom_write(chip->id,
+ XSCOM_ADDR_P9_EP(phys_core_id,
+ htm_scom_index[core_id]),
+ (u64) CORE_IMC_HTM_MODE_ENABLE);
+
+ if (ret < 0) {
+ prerror("IMC: error in xscom_write for htm_mode\n");
+ return OPAL_HARDWARE;
+ }
+
+ break;
default:
prerror("IMC: Unknown Domain \n");
return OPAL_PARAMETER;
@@ -334,7 +436,8 @@ static int64_t opal_imc_counters_stop(uint32_t type)
{
u64 op, status;
struct imc_chip_cb *cb;
- int ret = OPAL_SUCCESS;
+ struct proc_chip *chip;
+ int core_id, phys_core_id, ret = OPAL_SUCCESS;
switch (type) {
case OPAL_IMC_COUNTERS_NEST:
@@ -353,6 +456,25 @@ static int64_t opal_imc_counters_stop(uint32_t type)
cb->imc_chip_command = op;
break;
+ case OPAL_IMC_COUNTERS_CORE:
+ /*
+ * Disables the core imc engine by clearing
+ * bits 4-9 of the HTM_MODE scom port.
+ */
+ chip = get_chip(this_cpu()->chip_id);
+ phys_core_id = cpu_get_core_index(this_cpu());
+ core_id = phys_core_id % 4;
+
+ ret = xscom_write(chip->id,
+ XSCOM_ADDR_P9_EP(phys_core_id,
+ htm_scom_index[core_id]),
+ (u64) CORE_IMC_HTM_MODE_DISABLE);
+ if (ret < 0) {
+ prerror("IMC: error in xscom_write for htm_mode\n");
+ return OPAL_HARDWARE;
+ }
+
+ break;
default:
prerror("IMC: Unknown Domain \n");
return OPAL_PARAMETER;
diff --git a/include/imc.h b/include/imc.h
index c7ad5fa933b7..5a3d53c22ca1 100644
--- a/include/imc.h
+++ b/include/imc.h
@@ -116,6 +116,16 @@ 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_NCU_MODE 0x0800000000000000ull
+#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 e22358a1bbab..6497c94cd46a 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -1221,6 +1221,7 @@ enum {
/* Operation argument to IMC Microcode */
enum {
OPAL_IMC_COUNTERS_NEST = 1,
+ OPAL_IMC_COUNTERS_CORE = 2,
};
--
2.7.4
More information about the Skiboot
mailing list