[Skiboot] [BACKPORT PATCH 1/2] opal-api: Add OPAL call to handle abnormal reboots.

Mahesh J Salgaonkar mahesh at linux.vnet.ibm.com
Thu Aug 6 16:43:08 AEST 2015


From: Vipin K Parashar <vipin at linux.vnet.ibm.com>

This patch adds a new OPAL call OPAL_CEC_REBOOT2 which will
be used to handle abnormal reboot/termination by kernel host.

This call will allow host kernel to pass reboot type and additional
debug data which needs to be captured/saved somewhere (for later
analysis) before going down.

Currently it will support two reboot types (0). normal reboot, that
will behave similar to that of opal_cec_reboot() call, and
(1). platform error reboot, that will trigger a system checkstop
using xscom address and FIR bit information obtained via device-tree
property 'ibm,sw-checkstop-fir'.

For unsupported reboot type, this call will do nothing and return
with OPAL_UNSUPPORTED.

In future, we can overload this call to support additional reboot types.

Signed-off-by: Vipin K Parashar <vipin at linux.vnet.ibm.com>
Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
Hi Stewart, This patch is for stable tree.

 core/platform.c    |   36 ++++++++++++++++++++++++++++++++++++
 hw/xscom.c         |   32 ++++++++++++++++++++++++++++++++
 include/errorlog.h |    3 +++
 include/opal-api.h |    9 ++++++++-
 include/xscom.h    |    1 +
 5 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/core/platform.c b/core/platform.c
index 2a29a7e..b8ee061 100644
--- a/core/platform.c
+++ b/core/platform.c
@@ -21,9 +21,18 @@
 #include <timebase.h>
 #include <cpu.h>
 #include <chip.h>
+#include <xscom.h>
+#include <errorlog.h>
 
 struct platform	platform;
 
+static void reboot_err_info_dump(struct errorlog *buf, void *data,
+				 uint16_t size);
+
+DEFINE_LOG_ENTRY(OPAL_RC_ABNORMAL_REBOOT, OPAL_PLATFORM_ERR_EVT, OPAL_CEC,
+		 OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT,
+		 OPAL_ABNORMAL_POWER_OFF, reboot_err_info_dump);
+
 /*
  * Various wrappers for platform functions
  */
@@ -53,6 +62,33 @@ static int64_t opal_cec_reboot(void)
 }
 opal_call(OPAL_CEC_REBOOT, opal_cec_reboot, 0);
 
+static void reboot_err_info_dump(struct errorlog *buf, void *data,
+				 uint16_t size)
+{
+	if (data)
+		opal_elog_update_user_dump(buf, data, 0x44455350, size);
+}
+
+static int64_t opal_cec_reboot2(uint32_t reboot_type, char *diag)
+{
+	switch (reboot_type) {
+	case OPAL_REBOOT_NORMAL:
+		return opal_cec_reboot();
+	case OPAL_REBOOT_PLATFORM_ERROR:
+		prlog(PR_EMERG,
+			  "OPAL: Reboot requested due to Platform error.");
+		log_error(&e_info(OPAL_RC_ABNORMAL_REBOOT),
+			  (void *)diag, strlen(diag),
+			  "OPAL: Reboot requested due to Platform error.");
+		return xscom_trigger_xstop();
+	default:
+		printf("OPAL: Unsupported reboot request %d\n", reboot_type);
+		return OPAL_UNSUPPORTED;
+	}
+	return OPAL_SUCCESS;
+}
+opal_call(OPAL_CEC_REBOOT2, opal_cec_reboot2, 2);
+
 static void generic_platform_init(void)
 {
 	force_dummy_console();
diff --git a/hw/xscom.c b/hw/xscom.c
index 9fb7dba..6e62a8d 100644
--- a/hw/xscom.c
+++ b/hw/xscom.c
@@ -53,6 +53,12 @@ DEFINE_LOG_ENTRY(OPAL_RC_XSCOM_RESET, OPAL_PLATFORM_ERR_EVT, OPAL_XSCOM,
 		OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL,
 		OPAL_NA, NULL);
 
+/* xscom details to trigger xstop */
+static struct {
+	uint64_t addr;
+	uint64_t fir_bit;
+} xstop_xscom;
+
 /*
  * Locking notes:
  *
@@ -478,9 +484,25 @@ static void xscom_init_chip_info(struct proc_chip *chip)
 	chip->ec_level |= (val >> 8) & 0xf;
 }
 
+/*
+* This function triggers xstop by writing to XSCOM.
+* Machine would enter xstop state post completion of this.
+*/
+int64_t xscom_trigger_xstop(void)
+{
+	int rc = OPAL_UNSUPPORTED;
+
+	if (xstop_xscom.addr)
+		rc = xscom_writeme(xstop_xscom.addr,
+				PPC_BIT(xstop_xscom.fir_bit));
+
+	return rc;
+}
+
 void xscom_init(void)
 {
 	struct dt_node *xn;
+	const struct dt_property *p;
 
 	dt_for_each_compatible(dt_root, xn, "ibm,xscom") {
 		uint32_t gcid = dt_get_chip_id(xn);
@@ -513,6 +535,16 @@ void xscom_init(void)
 		       chip->ec_level >> 4,
 		       chip->ec_level & 0xf);
 	}
+
+	/* Collect details to trigger xstop via XSCOM write */
+	p = dt_find_property(dt_root, "ibm,sw-checkstop-fir");
+	if (p) {
+		xstop_xscom.addr = dt_property_get_cell(p, 0);
+		xstop_xscom.fir_bit = dt_property_get_cell(p, 1);
+		prlog(PR_INFO, "XSTOP: XSCOM addr = 0x%llx, FIR bit = %lld\n",
+					xstop_xscom.addr, xstop_xscom.fir_bit);
+	} else
+		prlog(PR_INFO, "XSTOP: ibm,sw-checkstop-fir prop not found\n");
 }
 
 void xscom_used_by_console(void)
diff --git a/include/errorlog.h b/include/errorlog.h
index 49c60cf..6cb0b2a 100644
--- a/include/errorlog.h
+++ b/include/errorlog.h
@@ -317,6 +317,9 @@ enum opal_reasoncode {
 	OPAL_RC_I2C_TIMEOUT	= OPAL_IC | 0x12,
 	OPAL_RC_I2C_TRANSFER	= OPAL_IC | 0x13,
 	OPAL_RC_I2C_RESET	= OPAL_IC | 0x14,
+
+/* Platform error */
+	OPAL_RC_ABNORMAL_REBOOT	= OPAL_CE | 0x10,
 };
 
 #define DEFINE_LOG_ENTRY(reason, type, id, subsys,			\
diff --git a/include/opal-api.h b/include/opal-api.h
index 5be548c..be351fd 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -161,7 +161,8 @@
 #define OPAL_PRD_MSG				113
 #define OPAL_LEDS_GET_INDICATOR			114
 #define OPAL_LEDS_SET_INDICATOR			115
-#define OPAL_LAST				115
+#define OPAL_CEC_REBOOT2			116
+#define OPAL_LAST				116
 
 /* Device tree flags */
 
@@ -946,6 +947,12 @@ struct opal_i2c_request {
 	__be64 buffer_ra;		/* Buffer real address */
 };
 
+/* Argument to OPAL_CEC_REBOOT2() */
+enum {
+	OPAL_REBOOT_NORMAL = 0,
+	OPAL_REBOOT_PLATFORM_ERROR,
+};
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __OPAL_API_H */
diff --git a/include/xscom.h b/include/xscom.h
index a841261..09db99b 100644
--- a/include/xscom.h
+++ b/include/xscom.h
@@ -179,5 +179,6 @@ extern void xscom_used_by_console(void);
 extern bool xscom_ok(void);
 
 extern int64_t xscom_read_cfam_chipid(uint32_t partid, uint32_t *chip_id);
+extern int64_t xscom_trigger_xstop(void);
 
 #endif /* __XSCOM_H */



More information about the Skiboot mailing list