[Pdbg] [PATCH v2 5/6] libpdbg: Add sbefifo driver for cronus backend

Amitay Isaacs amitay at ozlabs.org
Thu Oct 24 12:53:30 AEDT 2019


Signed-off-by: Amitay Isaacs <amitay at ozlabs.org>
---
 libpdbg/cronus.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 316 insertions(+), 4 deletions(-)

diff --git a/libpdbg/cronus.c b/libpdbg/cronus.c
index 7931611..1475622 100644
--- a/libpdbg/cronus.c
+++ b/libpdbg/cronus.c
@@ -14,15 +14,14 @@
  * limitations under the License.
  */
 #include <stdint.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+#include <errno.h>
 
 #include <libcronus/libcronus.h>
+#include <libsbefifo/libsbefifo.h>
 
 #include "hwunit.h"
 #include "debug.h"
@@ -138,6 +137,278 @@ static int cronus_fsi_write(struct fsi *fsi, uint32_t addr, uint32_t value)
 	return 0;
 }
 
+static uint32_t cronus_op_ffdc_get(struct sbefifo *sbefifo, const uint8_t **ffdc, uint32_t *ffdc_len)
+{
+	return sbefifo_ffdc_get(sbefifo->sf_ctx, ffdc, ffdc_len);
+}
+
+static int cronus_op_istep(struct sbefifo *sbefifo,
+			    uint32_t major, uint32_t minor)
+{
+	PR_NOTICE("sbefifo: istep %u.%u\n", major, minor);
+
+	return sbefifo_istep_execute(sbefifo->sf_ctx, major & 0xff, minor & 0xff);
+}
+
+static int cronus_op_getmem(struct mem *sbefifo_mem,
+			     uint64_t addr, uint8_t *data, uint64_t size,
+			     uint8_t block_size, bool ci)
+{
+	struct sbefifo *sbefifo = target_to_sbefifo(sbefifo_mem->target.parent);
+	uint8_t *out;
+	uint64_t start_addr, end_addr;
+	uint32_t align, offset, len;
+	uint16_t flags;
+	int rc;
+
+	align = 8;
+
+	if (block_size && block_size != 8) {
+		PR_ERROR("sbefifo: Only 8 byte block sizes are supported\n");
+		return -1;
+	};
+
+	start_addr = addr & (~(uint64_t)(align-1));
+	end_addr = (addr + size + (align-1)) & (~(uint64_t)(align-1));
+
+	if (end_addr - start_addr > UINT32_MAX) {
+		PR_ERROR("sbefifo: size too large\n");
+		return -EINVAL;
+	}
+
+	offset = addr - start_addr;
+	len = end_addr - start_addr;
+
+	PR_NOTICE("sbefifo: getmem addr=0x%016" PRIx64 ", len=%u\n",
+		  start_addr, len);
+
+	flags = SBEFIFO_MEMORY_FLAG_PROC;
+	if (ci)
+		flags |= SBEFIFO_MEMORY_FLAG_CI;
+
+	rc = sbefifo_mem_get(sbefifo->sf_ctx, start_addr, len, flags, &out);
+	if (rc)
+		return rc;
+
+	pdbg_progress_tick(len, len);
+
+	memcpy(data, out+offset, size);
+	free(out);
+
+	return 0;
+}
+
+static int cronus_op_putmem(struct mem *sbefifo_mem,
+			     uint64_t addr, uint8_t *data, uint64_t size,
+			     uint8_t block_size, bool ci)
+{
+	struct sbefifo *sbefifo = target_to_sbefifo(sbefifo_mem->target.parent);
+	uint32_t align, len;
+	uint16_t flags;
+	int rc;
+
+	align = 8;
+
+	if (block_size && block_size != 8) {
+		PR_ERROR("sbefifo: Only 8 byte block sizes are supported\n");
+		return -1;
+	};
+
+	if (addr & (align-1)) {
+		PR_ERROR("sbefifo: Address must be aligned to %d bytes\n", align);
+		return -1;
+	}
+
+	if (size & (align-1)) {
+		PR_ERROR("sbefifo: Data must be multiple of %d bytes\n", align);
+		return -1;
+	}
+
+	if (size > UINT32_MAX) {
+		PR_ERROR("sbefifo: size too large\n");
+		return -1;
+	}
+
+	len = size & 0xffffffff;
+
+	PR_NOTICE("sbefifo: putmem addr=0x%016"PRIx64", len=%u\n", addr, len);
+
+	flags = SBEFIFO_MEMORY_FLAG_PROC;
+	if (ci)
+		flags |= SBEFIFO_MEMORY_FLAG_CI;
+
+	rc = sbefifo_mem_put(sbefifo->sf_ctx, addr, data, len, flags);
+	if (rc)
+		return rc;
+
+	pdbg_progress_tick(len, len);
+
+	return 0;
+}
+
+static int cronus_op_getmem_pba(struct pba *sbefifo_pba,
+				uint64_t addr, uint8_t *data, uint64_t size,
+				uint8_t block_size, bool ci)
+{
+	struct sbefifo *sbefifo = target_to_sbefifo(sbefifo_pba->target.parent);
+	uint8_t *out;
+	uint64_t start_addr, end_addr;
+	uint32_t align, offset, len;
+	uint16_t flags;
+	int rc;
+
+	align = 128;
+
+	if (block_size && block_size != 8) {
+		PR_ERROR("sbefifo: Only 128 byte block sizes are supported\n");
+		return -1;
+	};
+
+	start_addr = addr & (~(uint64_t)(align-1));
+	end_addr = (addr + size + (align-1)) & (~(uint64_t)(align-1));
+
+	if (end_addr - start_addr > UINT32_MAX) {
+		PR_ERROR("sbefifo: size too large\n");
+		return -EINVAL;
+	}
+
+	offset = addr - start_addr;
+	len = end_addr - start_addr;
+
+	PR_NOTICE("sbefifo: getmempba addr=0x%016" PRIx64 ", len=%u\n",
+		  start_addr, len);
+
+	flags = SBEFIFO_MEMORY_FLAG_PBA;
+	if (ci)
+		flags |= SBEFIFO_MEMORY_FLAG_CI;
+
+	rc = sbefifo_mem_get(sbefifo->sf_ctx, start_addr, len, flags, &out);
+	if (rc)
+		return rc;
+
+	pdbg_progress_tick(len, len);
+
+	memcpy(data, out+offset, size);
+	free(out);
+
+	return 0;
+}
+
+static int cronus_op_putmem_pba(struct pba *sbefifo_pba,
+				uint64_t addr, uint8_t *data, uint64_t size,
+				uint8_t block_size, bool ci)
+{
+	struct sbefifo *sbefifo = target_to_sbefifo(sbefifo_pba->target.parent);
+	uint32_t align, len;
+	uint16_t flags;
+	int rc;
+
+	align = 128;
+
+	if (block_size && block_size != 128) {
+		PR_ERROR("sbefifo: Only 128 byte block sizes are supported\n");
+		return -1;
+	};
+
+	if (addr & (align-1)) {
+		PR_ERROR("sbefifo: Address must be aligned to %d bytes\n", align);
+		return -1;
+	}
+
+	if (size & (align-1)) {
+		PR_ERROR("sbefifo: Data must be multiple of %d bytes\n", align);
+		return -1;
+	}
+
+	if (size > UINT32_MAX) {
+		PR_ERROR("sbefifo: size too large\n");
+		return -1;
+	}
+
+	len = size & 0xffffffff;
+
+	PR_NOTICE("sbefifo: putmempba addr=0x%016"PRIx64", len=%u\n", addr, len);
+
+	flags = SBEFIFO_MEMORY_FLAG_PBA;
+	if (ci)
+		flags |= SBEFIFO_MEMORY_FLAG_CI;
+
+	rc = sbefifo_mem_put(sbefifo->sf_ctx, addr, data, len, flags);
+	if (rc)
+		return rc;
+
+	pdbg_progress_tick(len, len);
+
+	return 0;
+}
+
+static int cronus_op_control(struct sbefifo *sbefifo,
+			      uint32_t core_id, uint32_t thread_id,
+			      uint32_t oper)
+{
+	uint8_t mode = 0;
+
+	/* Enforce special-wakeup for thread stop and sreset */
+	if ((oper & 0xf) == SBEFIFO_INSN_OP_STOP ||
+	    (oper & 0xf) == SBEFIFO_INSN_OP_SRESET)
+		mode = 0x2;
+
+	PR_NOTICE("sbefifo: control c:0x%x, t:0x%x, op:%u mode:%u\n", core_id, thread_id, oper, mode);
+
+	return sbefifo_control_insn(sbefifo->sf_ctx, core_id & 0xff, thread_id & 0xff, oper & 0xff, mode);
+}
+
+static int cronus_op_thread_start(struct sbefifo *sbefifo,
+				   uint32_t core_id, uint32_t thread_id)
+{
+	return cronus_op_control(sbefifo, core_id, thread_id, SBEFIFO_INSN_OP_START);
+}
+
+static int cronus_op_thread_stop(struct sbefifo *sbefifo,
+				  uint32_t core_id, uint32_t thread_id)
+{
+	return cronus_op_control(sbefifo, core_id, thread_id, SBEFIFO_INSN_OP_STOP);
+}
+
+static int cronus_op_thread_step(struct sbefifo *sbefifo,
+				  uint32_t core_id, uint32_t thread_id)
+{
+	return cronus_op_control(sbefifo, core_id, thread_id, SBEFIFO_INSN_OP_STEP);
+}
+
+static int cronus_op_thread_sreset(struct sbefifo *sbefifo,
+				    uint32_t core_id, uint32_t thread_id)
+{
+	return cronus_op_control(sbefifo, core_id, thread_id, SBEFIFO_INSN_OP_SRESET);
+}
+
+static int cronus_transport(uint8_t *request_buf,
+			    uint32_t request_len,
+			    uint8_t *reply_buf,
+			    uint32_t *reply_len,
+			    void *priv)
+{
+	struct pdbg_target *target = (struct pdbg_target *)priv;
+
+	return cronus_submit(cctx, pdbg_target_index(target),
+			     request_buf, request_len,
+			     reply_buf, reply_len);
+}
+
+static int cronus_sbefifo_probe(struct pdbg_target *target)
+{
+	struct sbefifo *sf = target_to_sbefifo(target);
+	int rc;
+
+	rc = sbefifo_connect_transport(cronus_transport, target, &sf->sf_ctx);
+	if (rc) {
+		PR_ERROR("Unable to initialize sbefifo driver\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static struct pib cronus_pib = {
 	.target = {
 		.name =	"Cronus Client based PIB",
@@ -164,9 +435,50 @@ static struct fsi cronus_fsi = {
 };
 DECLARE_HW_UNIT(cronus_fsi);
 
+struct mem cronus_sbefifo_mem = {
+	.target = {
+		.name = "Cronus Client based SBE FIFO memory access",
+		.compatible = "ibm,cronus-sbefifo-mem",
+		.class = "mem",
+	},
+	.read = cronus_op_getmem,
+	.write = cronus_op_putmem,
+};
+DECLARE_HW_UNIT(cronus_sbefifo_mem);
+
+struct pba cronus_sbefifo_pba = {
+	.target = {
+		.name = "Cronus Client based SBE FIFO PBA memory access",
+		.compatible = "ibm,cronus-sbefifo-pba",
+		.class = "pba",
+	},
+	.read = cronus_op_getmem_pba,
+	.write = cronus_op_putmem_pba,
+};
+DECLARE_HW_UNIT(cronus_sbefifo_pba);
+
+struct sbefifo cronus_sbefifo = {
+	.target = {
+		.name =	"Cronus Client based SBE FIFO",
+		.compatible = "ibm,cronus-sbefifo",
+		.class = "sbefifo",
+		.probe = cronus_sbefifo_probe,
+	},
+	.istep = cronus_op_istep,
+	.thread_start = cronus_op_thread_start,
+	.thread_stop = cronus_op_thread_stop,
+	.thread_step = cronus_op_thread_step,
+	.thread_sreset = cronus_op_thread_sreset,
+	.ffdc_get = cronus_op_ffdc_get,
+};
+DECLARE_HW_UNIT(cronus_sbefifo);
+
 __attribute__((constructor))
 static void register_cronus(void)
 {
 	pdbg_hwunit_register(&cronus_pib_hw_unit);
 	pdbg_hwunit_register(&cronus_fsi_hw_unit);
+	pdbg_hwunit_register(&cronus_sbefifo_hw_unit);
+	pdbg_hwunit_register(&cronus_sbefifo_mem_hw_unit);
+	pdbg_hwunit_register(&cronus_sbefifo_pba_hw_unit);
 }
-- 
2.21.0



More information about the Pdbg mailing list