Skip to content

Commit

Permalink
MPIPL: Add support to trigger MPIPL on BMC system
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vasant Hegde authored and oohal committed Aug 15, 2019
1 parent 166eda4 commit 0a17e67
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
14 changes: 11 additions & 3 deletions hw/ipmi/ipmi-attn.c
Expand Up @@ -10,6 +10,7 @@
#include <pel.h>
#include <platform.h>
#include <processor.h>
#include <sbe-p9.h>
#include <skiboot.h>
#include <stack.h>
#include <timebase.h>
Expand Down Expand Up @@ -56,16 +57,23 @@ static void ipmi_log_terminate_event(const char *msg)

void __attribute__((noreturn)) ipmi_terminate(const char *msg)
{
/* Log eSEL event */
if (ipmi_present())
ipmi_log_terminate_event(msg);

/*
* If mpipl is supported then trigger SBE interrupt
* to initiate mpipl
*/
p9_sbe_terminate();

/* Terminate called before initializing IPMI (early abort) */
if (!ipmi_present()) {
if (platform.cec_reboot)
platform.cec_reboot();
goto out;
}

/* Log eSEL event */
ipmi_log_terminate_event(msg);

/* Reboot call */
if (platform.cec_reboot)
platform.cec_reboot();
Expand Down
63 changes: 63 additions & 0 deletions hw/sbe-p9.c
Expand Up @@ -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");
}
10 changes: 10 additions & 0 deletions include/sbe-p9.h
Expand Up @@ -90,6 +90,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
Expand Down Expand Up @@ -230,4 +237,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 reloc_base);

/* Terminate and trigger MPIPL */
extern void p9_sbe_terminate(void);

#endif /* __SBE_P9_H */

0 comments on commit 0a17e67

Please sign in to comment.