[Skiboot] [PATCH 6/7] prd: Implement generic FSP - HBRT interface

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Thu Mar 28 22:18:20 AEDT 2019


This patch implements generic interface to pass data from FSP to HBRT during
runtime (FSP -> OPAL -> opal-prd -> HBRT).

OPAL gets notification from FSP for new HBRT messages. We will convert MBOX
message to firmware_notify format and send it to HBRT.

Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
 core/hostservices.c    | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/fsp/fsp.c           |  2 ++
 hw/prd.c               | 55 +++++++++++++++++++++++++++++++++++++++++++++
 include/fsp.h          |  6 ++++-
 include/hostservices.h |  2 ++
 include/skiboot.h      |  1 +
 platforms/ibm-fsp/zz.c |  1 +
 7 files changed, 126 insertions(+), 1 deletion(-)

diff --git a/core/hostservices.c b/core/hostservices.c
index cb307e848..fbb399b9d 100644
--- a/core/hostservices.c
+++ b/core/hostservices.c
@@ -879,3 +879,63 @@ out_tce_unmap:
 	fsp_tce_unmap(PSI_DMA_HBRT_FSP_MSG, PSI_DMA_HBRT_FSP_MSG_SIZE);
 	return rc;
 }
+
+void hservice_hbrt_msg_response(uint32_t rc)
+{
+	struct fsp_msg *resp;
+
+	resp = fsp_mkmsg(FSP_RSP_FSP_TO_HBRT | rc, 0);
+	if (!resp) {
+		prlog(PR_DEBUG,
+		      "HBRT: Failed to allocate FSP - HBRT response message\n");
+		return;
+	}
+
+	if (fsp_queue_msg(resp, fsp_freemsg)) {
+		prlog(PR_DEBUG,
+		      "HBRT: Failed to send FSP - HBRT response message\n");
+		fsp_freemsg(resp);
+		return;
+	}
+}
+
+/* FSP sends HBRT message notification. Pass this message to HBRT */
+static bool hservice_hbrt_msg_notify(uint32_t cmd_sub_mod, struct fsp_msg *msg)
+{
+	u32 tce_token, len;
+	void *buf;
+
+	if (cmd_sub_mod != FSP_CMD_FSP_TO_HBRT)
+		return false;
+
+	prlog(PR_TRACE, "HBRT: FSP - HBRT message generated\n");
+
+	tce_token = msg->data.words[1];
+	len = msg->data.words[2];
+	buf = fsp_inbound_buf_from_tce(tce_token);
+	if (!buf) {
+		prlog(PR_DEBUG, "HBRT: Invalid inbound data\n");
+		hservice_hbrt_msg_response(FSP_STATUS_INVALID_DATA);
+		return true;
+	}
+
+	prd_hbrt_fsp_msg_notify(buf, len);
+	return true;
+}
+
+static struct fsp_client fsp_hbrt_msg_client = {
+	.message = hservice_hbrt_msg_notify,
+};
+
+/* Register for FSP 0xF2 class messages */
+void hservice_fsp_init(void)
+{
+	if (proc_gen < proc_gen_p9)
+		return;
+
+	if (!fsp_present())
+		return;
+
+	/* Register for Class F2 */
+	fsp_register_client(&fsp_hbrt_msg_client, FSP_MCLASS_HBRT);
+}
diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c
index f7e674830..8fe2aed2d 100644
--- a/hw/fsp/fsp.c
+++ b/hw/fsp/fsp.c
@@ -178,6 +178,8 @@ static struct fsp_cmdclass fsp_cmdclass[FSP_MCLASS_LAST - FSP_MCLASS_FIRST + 1]
 	DEF_CLASS(FSP_MCLASS_DIAG,		16),
 	DEF_CLASS(FSP_MCLASS_PCIE_LINK_TOPO,	16),
 	DEF_CLASS(FSP_MCLASS_OCC,		16),
+	DEF_CLASS(FSP_MCLASS_TRUSTED_BOOT,	2),
+	DEF_CLASS(FSP_MCLASS_HBRT,		2),
 };
 
 static void fsp_trace_msg(struct fsp_msg *msg, u8 dir __unused)
diff --git a/hw/prd.c b/hw/prd.c
index d032d42ca..8333dbf3b 100644
--- a/hw/prd.c
+++ b/hw/prd.c
@@ -40,6 +40,7 @@ static uint8_t _prd_msg_buf[sizeof(struct opal_prd_msg) +
 			    sizeof(struct prd_fw_msg)];
 static struct opal_prd_msg *prd_msg = (struct opal_prd_msg *)&_prd_msg_buf;
 static struct opal_prd_msg *prd_msg_fsp_req;
+static struct opal_prd_msg *prd_msg_fsp_notify;
 static bool prd_msg_inuse, prd_active;
 static struct dt_node *prd_node;
 static bool prd_enabled = false;
@@ -118,6 +119,13 @@ static void prd_msg_consumed(void *data)
 			prd_msg_fsp_req = NULL;
 		}
 		break;
+	case OPAL_PRD_MSG_TYPE_FIRMWARE_NOTIFY:
+		if (prd_msg_fsp_notify) {
+			free(prd_msg_fsp_notify);
+			prd_msg_fsp_notify = NULL;
+		}
+		hservice_hbrt_msg_response(OPAL_SUCCESS);
+		break;
 	case OPAL_PRD_MSG_TYPE_SBE_PASSTHROUGH:
 		proc = msg->sbe_passthrough.chip;
 		event = EVENT_SBE_PASSTHROUGH;
@@ -344,6 +352,53 @@ void prd_fw_resp_fsp_response(int status)
 	unlock(&events_lock);
 }
 
+void prd_hbrt_fsp_msg_notify(void *data, u32 dsize)
+{
+	int size, rc;
+
+	if (!prd_enabled || !prd_active) {
+		prlog(PR_NOTICE, "PRD: PRD daemon is not ready\n");
+		hservice_hbrt_msg_response(FSP_STATUS_GENERIC_FAILURE);
+		return;
+	}
+
+	/* Calculate prd message size */
+	size =  sizeof(prd_msg->hdr) + sizeof(prd_msg->token) +
+		sizeof(prd_msg->fw_notify) + dsize;
+
+	lock(&events_lock);
+
+	/* Handle message allocation part */
+	if (prd_msg_fsp_notify) {
+		prlog(PR_DEBUG, "PRD: FSP - HBRT notify message is busy\n");
+		hservice_hbrt_msg_response(FSP_STATUS_GENERIC_FAILURE);
+		goto unlock_events;
+	}
+
+	prd_msg_fsp_notify = zalloc(size);
+	if (!prd_msg_fsp_notify) {
+		prlog(PR_DEBUG,
+		      "PRD: %s: Failed to allocate memory\n", __func__);
+		hservice_hbrt_msg_response(FSP_STATUS_GENERIC_FAILURE);
+		goto unlock_events;
+	}
+
+	prd_msg_fsp_notify->hdr.size = size;
+	prd_msg_fsp_notify->hdr.type = OPAL_PRD_MSG_TYPE_FIRMWARE_NOTIFY;
+	prd_msg_fsp_notify->token = 0;
+	prd_msg_fsp_notify->fw_notify.len = cpu_to_be64(dsize);
+	memcpy(&(prd_msg_fsp_notify->fw_notify.data), data, dsize);
+
+	rc = opal_queue_msg_extended(OPAL_MSG_PRD, prd_msg_fsp_notify,
+				     prd_msg_consumed, size,
+				     prd_msg_fsp_notify);
+	if (!rc)
+		prd_msg_inuse = true;
+
+unlock_events:
+	unlock(&events_lock);
+}
+
 /* incoming message handlers */
 static int prd_msg_handle_attn_ack(struct opal_prd_msg *msg)
 {
diff --git a/include/fsp.h b/include/fsp.h
index 751886703..cfa51afbc 100644
--- a/include/fsp.h
+++ b/include/fsp.h
@@ -296,7 +296,9 @@
 #define FSP_MCLASS_DIAG			0xee
 #define FSP_MCLASS_PCIE_LINK_TOPO	0xef
 #define FSP_MCLASS_OCC			0xf0
-#define FSP_MCLASS_LAST			0xf0
+#define FSP_MCLASS_TRUSTED_BOOT		0xf1
+#define FSP_MCLASS_HBRT			0xf2
+#define FSP_MCLASS_LAST			0xf2
 
 /*
  * Commands are provided in rxxyyzz form where:
@@ -584,6 +586,8 @@
  * Class F2
  */
 #define FSP_CMD_HBRT_TO_FSP	0x1f20100 /* HV->FSP: HBRT message */
+#define FSP_CMD_FSP_TO_HBRT	0x0f20200 /* FSP->HV: HBRT message */
+#define FSP_RSP_FSP_TO_HBRT	0x0f28200 /* HV->FSP: HBRT message */
 
 
 /*
diff --git a/include/hostservices.h b/include/hostservices.h
index 8c54935d7..bdff9daec 100644
--- a/include/hostservices.h
+++ b/include/hostservices.h
@@ -43,5 +43,7 @@ int hservice_wakeup(uint32_t i_core, uint32_t i_mode);
 int fsp_occ_reset_status(u64 chipid, s64 status);
 int fsp_occ_load_start_status(u64 chipid, s64 status);
 int hservice_send_hbrt_msg(void *data, u64 dsize);
+void hservice_hbrt_msg_response(uint32_t rc);
+void hservice_fsp_init(void);
 
 #endif /* __HOSTSERVICES_H */
diff --git a/include/skiboot.h b/include/skiboot.h
index 0a7c84a8b..68a983080 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -292,6 +292,7 @@ extern void prd_register_reserved_memory(void);
 extern void prd_fsp_occ_reset(uint32_t proc);
 extern void prd_fsp_occ_load_start(u32 proc);
 extern void prd_fw_resp_fsp_response(int status);
+extern void prd_hbrt_fsp_msg_notify(void *data, u32 dsize);
 
 /* Flatten device-tree */
 extern void *create_dtb(const struct dt_node *root, bool exclusive);
diff --git a/platforms/ibm-fsp/zz.c b/platforms/ibm-fsp/zz.c
index 29dd6089d..705906a04 100644
--- a/platforms/ibm-fsp/zz.c
+++ b/platforms/ibm-fsp/zz.c
@@ -66,6 +66,7 @@ static uint32_t ibm_fsp_occ_timeout(void)
 static void zz_init(void)
 {
 	ibm_fsp_init();
+	hservice_fsp_init();
 }
 
 DECLARE_PLATFORM(zz) = {
-- 
2.14.3



More information about the Skiboot mailing list