[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