[RFC,16/16] Add support to trigger memory preserving IPL on BMC system

Message ID 20180403120447.24364-17-hegdevasant@linux.vnet.ibm.com
State New
Headers show
Series
  • MPIPL support
Related show

Commit Message

Vasant Hegde April 3, 2018, 12:04 p.m.
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/s1
interrupt to initiate memory preserving IPL.

This patch adds support to call s0/s1 interrupt.

Flow:
  - s1 interrupt on slave chip SBE
  - s0 interrupt on master chip SBE

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
---
 hw/ipmi/ipmi-attn.c |  4 ++++
 hw/sbe-p9.c         | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/sbe-p9.h    | 10 ++++++++++
 3 files changed, 62 insertions(+)

Patch

diff --git a/hw/ipmi/ipmi-attn.c b/hw/ipmi/ipmi-attn.c
index 8ff872c62..15aeace56 100644
--- a/hw/ipmi/ipmi-attn.c
+++ b/hw/ipmi/ipmi-attn.c
@@ -19,6 +19,7 @@ 
 #include <pel.h>
 #include <platform.h>
 #include <processor.h>
+#include <sbe-p9.h>
 #include <skiboot.h>
 #include <stack.h>
 #include <timebase.h>
@@ -65,6 +66,9 @@  static void ipmi_log_terminate_event(const char *msg)
 
 void __attribute__((noreturn)) ipmi_terminate(const char *msg)
 {
+	/* On P9 BMC system this will trigger fadump */
+	p9_sbe_terminate();
+
 	/* Terminate called before initializing IPMI (early abort) */
 	if (!ipmi_present()) {
 		if (platform.cec_reboot)
diff --git a/hw/sbe-p9.c b/hw/sbe-p9.c
index e2566bf26..9c8253b28 100644
--- a/hw/sbe-p9.c
+++ b/hw/sbe-p9.c
@@ -828,3 +828,51 @@  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 chip_id;
+	uint32_t primary_chip = -1;
+	int rc;
+	struct dt_node *xn;
+
+	if (proc_gen < proc_gen_p9)
+		return;
+
+	dt_for_each_compatible(dt_root, xn, "ibm,xscom") {
+		chip_id = dt_get_chip_id(xn);
+
+		if (dt_has_node_property(xn, "primary", NULL)) {
+			primary_chip = chip_id;
+			continue;
+		}
+
+		rc = xscom_write(chip_id,
+				 SBE_CONTROL_REG_RW, SBE_CONTROL_REG_S1);
+		/* Initiate normal reboot */
+		if (rc) {
+			prlog(PR_ERR, "Failed to write S1 interrupt [chip id = %x]\n",
+			      chip_id);
+			return;
+		}
+	}
+
+	if (primary_chip == -1) {
+		prlog(PR_ERR, "Master chip ID not found.\n");
+		return;
+	}
+
+	/* Write S0 interrupt on master SBE */
+	rc = xscom_write(primary_chip,
+			 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",
+		      primary_chip);
+		return;
+	}
+
+	while (1)
+		time_wait_ms(100);
+}
diff --git a/include/sbe-p9.h b/include/sbe-p9.h
index b7ca8dba8..4df799cd5 100644
--- a/include/sbe-p9.h
+++ b/include/sbe-p9.h
@@ -103,6 +103,13 @@ 
 #define SBE_HOST_TIMER_EXPIRY		PPC_BIT(14)
 #define SBE_HOST_RESPONSE_MASK		(PPC_BITMASK(0, 4) | SBE_HOST_TIMER_EXPIRY)
 
+/* SBE Control Register */
+#define SBE_CONTROL_REG_RW		0x00050008
+
+/* SBE interrupt s0/s1 bits */
+#define SBE_CONTROL_REG_S0		PPC_BIT(14)
+#define SBE_CONTROL_REG_S1		PPC_BIT(15)
+
 /* SBE Target Type */
 #define SBE_TARGET_TYPE_PROC		0x00
 #define SBE_TARGET_TYPE_EX		0x01
@@ -242,4 +249,7 @@  extern void p9_sbe_update_timer_expiry(uint64_t new_target);
 /* Send skiboot relocated base address to SBE */
 extern void p9_sbe_send_relocated_base(uint64_t val);
 
+/* Terminate and trigger MPIPL */
+extern void p9_sbe_terminate(void);
+
 #endif	/* __SBE_P9_H */