[Skiboot] [PATCH] prd: Fix prd message queuing interface

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Tue Oct 22 22:28:30 AEDT 2019


OPAL_MSG_PRD interface can handle message size <= OPAL_MSG_FIXED_PARAMS_SIZE.
But kernel prd driver had a bug where it will not copy partial data to user
space. This will create problem as opal-prd daemon tries to read message
continuously.

Commit 9cae036fa fixed this issue by enhancing opal-prd to allocate bigger
message size based on device tree.

For backward compatability (new OPAL and old kernel/userspace) lets restrict
OPAL_MSG_PRD messaging interface to send upto 32 bytes data. This is fine
as most of the messages are less than 32 bytes except FSP - HBRT messages
...which is new feature.

Cc: Jeremy Kerr <jk at ozlabs.org>
Cc: Vaidyanathan Srinivasan <svaidy at linux.vnet.ibm.com>
Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
 hw/prd.c | 46 ++++++++++++++++++++--------------------------
 1 file changed, 20 insertions(+), 26 deletions(-)

diff --git a/hw/prd.c b/hw/prd.c
index d9198f0eb..9c4cb1f45 100644
--- a/hw/prd.c
+++ b/hw/prd.c
@@ -149,6 +149,22 @@ static void prd_msg_consumed(void *data, int status)
 	unlock(&events_lock);
 }
 
+/*
+ * OPAL_MSG_PRD interface can handle message size <= OPAL_MSG_FIXED_PARAMS_SIZE.
+ * But kernel prd driver had a bug where it will not copy partial data to user
+ * space. Use OPAL_MSG_PRD interface only if size is <= sizeof(opal_prg_msg).
+ */
+static inline int opal_queue_prd_msg(struct opal_prd_msg *msg)
+{
+	enum opal_msg_type msg_type = OPAL_MSG_PRD2;
+
+	if (be16_to_cpu(msg->hdr.size) <= 0x20)
+		msg_type = OPAL_MSG_PRD;
+
+	return _opal_queue_msg(msg_type, msg, prd_msg_consumed,
+			       be16_to_cpu(msg->hdr.size), msg);
+}
+
 static int populate_ipoll_msg(struct opal_prd_msg *msg, uint32_t proc)
 {
 	uint64_t ipoll_mask;
@@ -224,8 +240,7 @@ static void send_next_pending_event(void)
 	 * disabled then we shouldn't propagate PRD events to the host.
 	 */
 	if (prd_enabled) {
-		rc = _opal_queue_msg(OPAL_MSG_PRD, prd_msg, prd_msg_consumed,
-				     prd_msg->hdr.size, prd_msg);
+		rc = opal_queue_prd_msg(prd_msg);
 		if (!rc)
 			prd_msg_inuse = true;
 	}
@@ -327,7 +342,6 @@ void prd_fw_resp_fsp_response(int status)
 	uint64_t fw_resp_len_old;
 	int rc;
 	uint16_t hdr_size;
-	enum opal_msg_type msg_type = OPAL_MSG_PRD2;
 
 	lock(&events_lock);
 
@@ -348,16 +362,7 @@ void prd_fw_resp_fsp_response(int status)
 		prd_msg_fsp_req->hdr.size = cpu_to_be16(hdr_size);
 	}
 
-	/*
-	 * If prd message size is <= OPAL_MSG_FIXED_PARAMS_SIZE then use
-	 * OPAL_MSG_PRD to pass data to kernel. So that it works fine on
-	 * older kernel (which does not support OPAL_MSG_PRD2).
-	 */
-	if (prd_msg_fsp_req->hdr.size < OPAL_MSG_FIXED_PARAMS_SIZE)
-		msg_type = OPAL_MSG_PRD;
-
-	rc = _opal_queue_msg(msg_type, prd_msg_fsp_req, prd_msg_consumed,
-			     prd_msg_fsp_req->hdr.size, prd_msg_fsp_req);
+	rc = opal_queue_prd_msg(prd_msg_fsp_req);
 	if (!rc)
 		prd_msg_inuse = true;
 	unlock(&events_lock);
@@ -367,7 +372,6 @@ int prd_hbrt_fsp_msg_notify(void *data, u32 dsize)
 {
 	int size;
 	int rc = FSP_STATUS_GENERIC_FAILURE;
-	enum opal_msg_type msg_type = OPAL_MSG_PRD2;
 
 	if (!prd_enabled || !prd_active) {
 		prlog(PR_NOTICE, "PRD: %s: PRD daemon is not ready\n",
@@ -407,16 +411,7 @@ int prd_hbrt_fsp_msg_notify(void *data, u32 dsize)
 	prd_msg_fsp_notify->fw_notify.len = cpu_to_be64(dsize);
 	memcpy(&(prd_msg_fsp_notify->fw_notify.data), data, dsize);
 
-	/*
-	 * If prd message size is <= OPAL_MSG_FIXED_PARAMS_SIZE then use
-	 * OPAL_MSG_PRD to pass data to kernel. So that it works fine on
-	 * older kernel (which does not support OPAL_MSG_PRD2).
-	 */
-	if (prd_msg_fsp_notify->hdr.size < OPAL_MSG_FIXED_PARAMS_SIZE)
-		msg_type = OPAL_MSG_PRD;
-
-	rc = _opal_queue_msg(msg_type, prd_msg_fsp_notify,
-			     prd_msg_consumed, size, prd_msg_fsp_notify);
+	rc = opal_queue_prd_msg(prd_msg_fsp_notify);
 	if (!rc)
 		prd_msg_inuse = true;
 
@@ -625,8 +620,7 @@ static int prd_msg_handle_firmware_req(struct opal_prd_msg *msg)
 	}
 
 	if (!rc) {
-		rc = _opal_queue_msg(OPAL_MSG_PRD, prd_msg, prd_msg_consumed,
-				     prd_msg->hdr.size, prd_msg);
+		rc = opal_queue_prd_msg(prd_msg);
 		if (rc)
 			prd_msg_inuse = false;
 	} else {
-- 
2.21.0



More information about the Skiboot mailing list