aboutsummaryrefslogtreecommitdiff
path: root/hw/sbe-p9.c
diff options
context:
space:
mode:
authorVasant Hegde <hegdevasant@linux.vnet.ibm.com>2019-07-12 16:47:52 +0530
committerOliver O'Halloran <oohall@gmail.com>2019-08-15 17:53:43 +1000
commit0a17e674616413b7a3182643cfa0fda292141bb1 (patch)
tree670a972e93540e6f7f079109c12b3bb972e081a7 /hw/sbe-p9.c
parent166eda4e0aa886658280956b479a92bfc0d1c572 (diff)
downloadskiboot-0a17e674616413b7a3182643cfa0fda292141bb1.zip
skiboot-0a17e674616413b7a3182643cfa0fda292141bb1.tar.gz
skiboot-0a17e674616413b7a3182643cfa0fda292141bb1.tar.bz2
MPIPL: Add support to trigger MPIPL on BMC system
On FSP based system we call 'attn' instruction. FSP detects attention and initiates memory preserving IPL. On BMC system we have to call SBE S0 interrupt to initiate memory preserving IPL. This patch adds support to call SBE S0 interrupt in assert path. Sequence : - S0 interrupt on secondary chip SBE - S0 interrupt on primary chip SBE Note that this is hooked to ipmi_terminate path. We have HDAT flag for MPIPL support. If MPIPL is not supported then we don't create 'ibm,opal/dump' node and we will fall back to existing termination flow. Finally we want to log error log to BMC before triggerring MPIPL. Hence this patch re-organizes ipmi_terminate() such that we call ipmi_log_terminate_event() before triggering MPIPL. Note: - At present we do not have a proper way to detect SBE is alive or not. So we wait for predefined time and then call normal reboot. Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com> [oliver: rebased] Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'hw/sbe-p9.c')
-rw-r--r--hw/sbe-p9.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/hw/sbe-p9.c b/hw/sbe-p9.c
index 786351a..a9810a1 100644
--- a/hw/sbe-p9.c
+++ b/hw/sbe-p9.c
@@ -938,3 +938,66 @@ void p9_sbe_init(void)
/* Initiate SBE timeout poller */
opal_add_poller(p9_sbe_timeout_poll, NULL);
}
+
+/* Terminate and initiate MPIPL */
+void p9_sbe_terminate(void)
+{
+ uint32_t primary_chip = -1;
+ int rc;
+ u64 wait_tb;
+ struct proc_chip *chip;
+
+ /* Return if MPIPL is not supported */
+ if (!dt_find_by_path(opal_node, "dump"))
+ return;
+
+ /*
+ * Send S0 interrupt to all SBE. Sequence:
+ * - S0 interrupt on secondary chip SBE
+ * - S0 interrupt on Primary chip SBE
+ */
+ for_each_chip(chip) {
+ if (dt_has_node_property(chip->devnode, "primary", NULL)) {
+ primary_chip = chip->id;
+ continue;
+ }
+
+ rc = xscom_write(chip->id,
+ SBE_CONTROL_REG_RW, SBE_CONTROL_REG_S0);
+ /* Initiate normal reboot */
+ if (rc) {
+ prlog(PR_ERR, "Failed to write S0 interrupt [chip id = %x]\n",
+ chip->id);
+ return;
+ }
+ }
+
+ /* Initiate normal reboot */
+ if (primary_chip == -1) {
+ prlog(PR_ERR, "Primary chip ID not found.\n");
+ return;
+ }
+
+ rc = xscom_write(primary_chip,
+ SBE_CONTROL_REG_RW, SBE_CONTROL_REG_S0);
+ if (rc) {
+ prlog(PR_ERR, "Failed to write S0 interrupt [chip id = %x]\n",
+ primary_chip);
+ return;
+ }
+
+ /* XXX We expect SBE to act on interrupt, quiesce the system and start
+ * MPIPL flow. Currently we do not have a way to detect SBE state.
+ * Hence wait for max time SBE takes to respond and then trigger
+ * normal reboot.
+ */
+ prlog(PR_NOTICE, "Initiated MPIPL, waiting for SBE to respond...\n");
+ wait_tb = mftb() + msecs_to_tb(SBE_CMD_TIMEOUT_MAX);
+ while (mftb() < wait_tb) {
+ cpu_relax();
+ }
+
+ prlog(PR_ERR, "SBE did not respond within timeout period (%d secs).\n",
+ SBE_CMD_TIMEOUT_MAX / 1000);
+ prlog(PR_ERR, "Falling back to normal reboot\n");
+}