[Skiboot] [PATCH v3 1/2] opal-api: Add OPAL call to handle abnormal reboots.
Mahesh J Salgaonkar
mahesh at linux.vnet.ibm.com
Wed Jul 29 04:05:07 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>
---
core/platform.c | 37 +++++++++++++++++++++++++++++++++++++
hw/xscom.c | 32 ++++++++++++++++++++++++++++++++
include/errorlog.h | 3 +++
include/opal-api.h | 9 ++++++++-
include/xscom.h | 1 +
5 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/core/platform.c b/core/platform.c
index dec7e96..272f2db 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,34 @@ 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, uint64_t diag,
+ uint64_t size)
+{
+ switch (reboot_type) {
+ case OPAL_REBOOT_NORMAL:
+ return opal_cec_reboot();
+ case OPAL_REBOOT_PLATFORM_ERROR:
+ log_error(&e_info(OPAL_RC_ABNORMAL_REBOOT),
+ (void *)diag, size,
+ "OPAL: Reboot requested due to Platform error.");
+ return xscom_trigger_xstop();
+ default:
+ printf("OPAL: Unsupported reboot request %d\n", reboot_type);
+ /* Should we call normal reboot for default case ? */
+ return OPAL_UNSUPPORTED;
+ break;
+ }
+ return OPAL_SUCCESS;
+}
+opal_call(OPAL_CEC_REBOOT2, opal_cec_reboot2, 3);
+
static void generic_platform_init(void)
{
force_dummy_console();
diff --git a/hw/xscom.c b/hw/xscom.c
index 9d3523c..8a363b1 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:
*
@@ -483,9 +489,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);
@@ -521,6 +543,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 af9b441..ec3b071 100644
--- a/include/errorlog.h
+++ b/include/errorlog.h
@@ -323,6 +323,9 @@ enum opal_reasoncode {
/* IPMI */
OPAL_RC_IPMI_REQ = OPAL_IP | 0x10,
OPAL_RC_IPMI_RESP = OPAL_IP | 0x11,
+
+/* 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 bfad589..e22370f 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 */
@@ -972,6 +973,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