[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