aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVipin K Parashar <vipin@linux.vnet.ibm.com>2015-07-29 23:28:43 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-07-31 15:32:43 +1000
commit36c213d95f971804388c336213d636277b0f40f5 (patch)
treed325c6ebec923a8941315a0c2122fa4e0715de16
parentc37f122d3ca2e7964f971a98c5acbec9435c5616 (diff)
downloadskiboot-36c213d95f971804388c336213d636277b0f40f5.zip
skiboot-36c213d95f971804388c336213d636277b0f40f5.tar.gz
skiboot-36c213d95f971804388c336213d636277b0f40f5.tar.bz2
opal-api: Add OPAL call to handle abnormal reboots.
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@linux.vnet.ibm.com> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Reviewed-by: Samuel Mendoza-Jonas <sam.mj@au1.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--core/platform.c39
-rw-r--r--hw/xscom.c32
-rw-r--r--include/errorlog.h3
-rw-r--r--include/opal-api.h9
-rw-r--r--include/xscom.h1
5 files changed, 83 insertions, 1 deletions
diff --git a/core/platform.c b/core/platform.c
index dec7e96..12c4ec2 100644
--- a/core/platform.c
+++ b/core/platform.c
@@ -21,9 +21,15 @@
#include <timebase.h>
#include <cpu.h>
#include <chip.h>
+#include <xscom.h>
+#include <errorlog.h>
struct platform platform;
+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);
+
/*
* Various wrappers for platform functions
*/
@@ -53,6 +59,39 @@ static int64_t opal_cec_reboot(void)
}
opal_call(OPAL_CEC_REBOOT, opal_cec_reboot, 0);
+static int64_t opal_cec_reboot2(uint32_t reboot_type, char *diag)
+{
+ struct errorlog *buf;
+
+ 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.");
+ buf = opal_elog_create(&e_info(OPAL_RC_ABNORMAL_REBOOT), 0);
+ if (buf) {
+ log_append_msg(buf,
+ "OPAL: Reboot requested due to Platform error.");
+ if (diag) {
+ /* Add user section "DESC" */
+ log_add_section(buf, 0x44455350);
+ log_append_data(buf, diag, strlen(diag));
+ log_commit(buf);
+ }
+ } else {
+ prerror("OPAL: failed to log an error\n");
+ }
+ return xscom_trigger_xstop();
+ default:
+ printf("OPAL: Unsupported reboot request %d\n", reboot_type);
+ return OPAL_UNSUPPORTED;
+ break;
+ }
+ 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 ef3ff0f..ba9130a 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);
+/* 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 b908fd4..1499587 100644
--- a/include/errorlog.h
+++ b/include/errorlog.h
@@ -322,6 +322,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 */