[Pdbg] [PATCH v2 1/4] libsbefifo: Add a library to talk to sbefifo
Amitay Isaacs
amitay at ozlabs.org
Wed Aug 21 16:08:14 AEST 2019
Signed-off-by: Amitay Isaacs <amitay at ozlabs.org>
---
Makefile.am | 18 ++-
libsbefifo/cmd_array.c | 100 ++++++++++++++
libsbefifo/cmd_control.c | 50 +++++++
libsbefifo/cmd_generic.c | 169 ++++++++++++++++++++++++
libsbefifo/cmd_instruction.c | 54 ++++++++
libsbefifo/cmd_memory.c | 243 +++++++++++++++++++++++++++++++++++
libsbefifo/cmd_mpipl.c | 102 +++++++++++++++
libsbefifo/cmd_register.c | 115 +++++++++++++++++
libsbefifo/cmd_ring.c | 119 +++++++++++++++++
libsbefifo/cmd_scom.c | 147 +++++++++++++++++++++
libsbefifo/connect.c | 74 +++++++++++
libsbefifo/ffdc.c | 151 ++++++++++++++++++++++
libsbefifo/libsbefifo.h | 116 +++++++++++++++++
libsbefifo/operation.c | 149 +++++++++++++++++++++
libsbefifo/sbefifo_private.h | 88 +++++++++++++
15 files changed, 1694 insertions(+), 1 deletion(-)
create mode 100644 libsbefifo/cmd_array.c
create mode 100644 libsbefifo/cmd_control.c
create mode 100644 libsbefifo/cmd_generic.c
create mode 100644 libsbefifo/cmd_instruction.c
create mode 100644 libsbefifo/cmd_memory.c
create mode 100644 libsbefifo/cmd_mpipl.c
create mode 100644 libsbefifo/cmd_register.c
create mode 100644 libsbefifo/cmd_ring.c
create mode 100644 libsbefifo/cmd_scom.c
create mode 100644 libsbefifo/connect.c
create mode 100644 libsbefifo/ffdc.c
create mode 100644 libsbefifo/libsbefifo.h
create mode 100644 libsbefifo/operation.c
create mode 100644 libsbefifo/sbefifo_private.h
diff --git a/Makefile.am b/Makefile.am
index 011e686..f850a29 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -129,7 +129,7 @@ pdbg_LDADD = libpdbg.la libccan.a \
pdbg_LDFLAGS = -Wl,--whole-archive,-lpdbg,--no-whole-archive
lib_LTLIBRARIES = libpdbg.la
-noinst_LTLIBRARIES = libcronus.la
+noinst_LTLIBRARIES = libcronus.la libsbefifo.la
libcronus_la_SOURCES = \
libcronus/buffer.c \
@@ -142,6 +142,22 @@ libcronus_la_SOURCES = \
libcronus/request.c \
libcronus/scom.c
+libsbefifo_la_SOURCES = \
+ libsbefifo/cmd_array.c \
+ libsbefifo/cmd_control.c \
+ libsbefifo/cmd_generic.c \
+ libsbefifo/cmd_instruction.c \
+ libsbefifo/cmd_memory.c \
+ libsbefifo/cmd_mpipl.c \
+ libsbefifo/cmd_register.c \
+ libsbefifo/cmd_ring.c \
+ libsbefifo/cmd_scom.c \
+ libsbefifo/connect.c \
+ libsbefifo/ffdc.c \
+ libsbefifo/libsbefifo.h \
+ libsbefifo/operation.c \
+ libsbefifo/sbefifo_private.h
+
libpdbg_la_SOURCES = \
$(DT_sources) \
libpdbg/adu.c \
diff --git a/libsbefifo/cmd_array.c b/libsbefifo/cmd_array.c
new file mode 100644
index 0000000..c5f5eec
--- /dev/null
+++ b/libsbefifo/cmd_array.c
@@ -0,0 +1,100 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <endian.h>
+#include <errno.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_control_fast_array(struct sbefifo_context *sctx, uint16_t target_type, uint8_t chiplet_id, uint8_t mode, uint64_t clock_cycle)
+{
+ uint8_t *out;
+ uint32_t msg[3];
+ uint32_t cmd, out_len;
+ uint32_t target;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_ARRAY | SBEFIFO_CMD_FAST_ARRAY;
+ target = ((uint32_t)target_type << 16) |
+ ((uint32_t)chiplet_id << 8) |
+ ((uint32_t)(mode & 0x3));
+
+ msg[0] = htobe32(3); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(target);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 3 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
+
+int sbefifo_control_trace_array(struct sbefifo_context *sctx, uint16_t target_type, uint8_t chiplet_id, uint16_t array_id, uint16_t operation, uint8_t **trace_data, uint32_t *trace_data_len)
+{
+ uint8_t *out;
+ uint32_t msg[4];
+ uint32_t cmd, out_len;
+ uint32_t target, oper;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_ARRAY | SBEFIFO_CMD_TRACE_ARRAY;
+ target = ((uint32_t)target_type << 16) | ((uint32_t)chiplet_id);
+ oper = ((uint32_t)array_id << 16) | ((uint32_t)operation);
+
+ msg[0] = htobe32(4); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(target);
+ msg[3] = htobe32(oper);
+
+ out_len = 16 * 4;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 4 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len < 4) {
+ free(out);
+ return EPROTO;
+ }
+
+ *trace_data_len = 4 * be32toh(*(uint32_t *) &out[out_len-4]);
+
+ if (out_len != *trace_data_len + 4) {
+ free(out);
+ return EPROTO;
+ }
+
+ *trace_data = malloc(*trace_data_len);
+ if (! *trace_data) {
+ free(out);
+ return ENOMEM;
+ }
+
+ memcpy(*trace_data, out, *trace_data_len);
+
+ free(out);
+ return 0;
+}
diff --git a/libsbefifo/cmd_control.c b/libsbefifo/cmd_control.c
new file mode 100644
index 0000000..abbfd73
--- /dev/null
+++ b/libsbefifo/cmd_control.c
@@ -0,0 +1,50 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <endian.h>
+#include <errno.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_istep_execute(struct sbefifo_context *sctx, uint8_t major, uint8_t minor)
+{
+ uint8_t *out;
+ uint32_t msg[3];
+ uint32_t cmd, step, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_CONTROL | SBEFIFO_CMD_EXECUTE_ISTEP;
+ step = (major << 16) | minor;
+
+ msg[0] = htobe32(3); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(step);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 3 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
diff --git a/libsbefifo/cmd_generic.c b/libsbefifo/cmd_generic.c
new file mode 100644
index 0000000..f912e92
--- /dev/null
+++ b/libsbefifo/cmd_generic.c
@@ -0,0 +1,169 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <endian.h>
+#include <errno.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_get_ffdc(struct sbefifo_context *sctx, uint8_t **ffdc, uint32_t *ffdc_len)
+{
+ uint8_t *out;
+ uint32_t msg[2];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_GENERIC | SBEFIFO_CMD_GET_FFDC;
+
+ msg[0] = htobe32(2); // number of words
+ msg[1] = htobe32(cmd);
+
+ /* We don't know how much data to expect, let's assume it's less than 32K */
+ out_len = 0x8000;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 2 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ *ffdc_len = out_len;
+ if (out_len > 0) {
+ *ffdc = malloc(out_len);
+ if (! *ffdc) {
+ free(out);
+ return ENOMEM;
+ }
+ memcpy(*ffdc, out, out_len);
+
+ free(out);
+ } else {
+ *ffdc = NULL;
+ }
+
+ return 0;
+}
+
+int sbefifo_get_capabilities(struct sbefifo_context *sctx, uint32_t *version, char **commit_id, uint32_t **caps, uint32_t *caps_count)
+{
+ uint8_t *out;
+ uint32_t msg[2];
+ uint32_t cmd, out_len;
+ uint32_t i;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_GENERIC | SBEFIFO_CMD_GET_CAPABILITY;
+
+ msg[0] = htobe32(2); // number of words
+ msg[1] = htobe32(cmd);
+
+ out_len = 23 * 4;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 2 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 23 * 4) {
+ free(out);
+ return EPROTO;
+ }
+
+ *version = be32toh(*(uint32_t *) &out[0]);
+
+ *commit_id = malloc(9);
+ if (! *commit_id) {
+ free(out);
+ return ENOMEM;
+ }
+ memcpy(*commit_id, &out[4], 8);
+ (*commit_id)[8] = '\0';
+
+ *caps = malloc(20 * 4);
+ if (! *caps) {
+ free(out);
+ return ENOMEM;
+ }
+
+ *caps_count = 20;
+ for (i=0; i<20; i++)
+ (*caps)[i] = be32toh(*(uint32_t *) &out[12+i*4]);
+
+ free(out);
+ return 0;
+}
+
+int sbefifo_get_frequencies(struct sbefifo_context *sctx, uint32_t **freq, uint32_t *freq_count)
+{
+ uint8_t *out;
+ uint32_t msg[2];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_GENERIC | SBEFIFO_CMD_GET_FREQUENCY;
+
+ msg[0] = htobe32(2); // number of words
+ msg[1] = htobe32(cmd);
+
+ out_len = 8 * 4;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 2 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ *freq_count = out_len / 4;
+ if (*freq_count > 0) {
+ uint32_t i;
+
+ *freq = malloc(*freq_count * 4);
+ if (! *freq) {
+ free(out);
+ return ENOMEM;
+ }
+
+ for (i=0; i<*freq_count; i++)
+ (*freq)[i] = be32toh(*(uint32_t *) &out[i*4]);
+
+ free(out);
+ } else {
+ *freq = NULL;
+ }
+
+ return 0;
+}
+
+int sbefifo_quiesce(struct sbefifo_context *sctx)
+{
+ uint8_t *out;
+ uint32_t msg[2];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_GENERIC | SBEFIFO_CMD_GET_FREQUENCY;
+
+ msg[0] = htobe32(2); // number of words
+ msg[1] = htobe32(cmd);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 2 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
diff --git a/libsbefifo/cmd_instruction.c b/libsbefifo/cmd_instruction.c
new file mode 100644
index 0000000..5185982
--- /dev/null
+++ b/libsbefifo/cmd_instruction.c
@@ -0,0 +1,54 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <endian.h>
+#include <errno.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_control_insn(struct sbefifo_context *sctx, uint8_t core_id, uint8_t thread_id, uint8_t thread_op, uint8_t mode)
+{
+ uint8_t *out;
+ uint32_t msg[3];
+ uint32_t cmd, out_len;
+ uint32_t oper;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_INSTRUCTION | SBEFIFO_CMD_CONTROL_INSN;
+ oper = ((uint32_t)(mode & 0xf) << 16) |
+ ((uint32_t)(core_id & 0xff) << 8) |
+ ((uint32_t)(thread_id & 0xf) << 4) |
+ ((uint32_t)(thread_op & 0xf));
+
+ msg[0] = htobe32(3); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(oper);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 3 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
diff --git a/libsbefifo/cmd_memory.c b/libsbefifo/cmd_memory.c
new file mode 100644
index 0000000..b20767f
--- /dev/null
+++ b/libsbefifo/cmd_memory.c
@@ -0,0 +1,243 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <endian.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_mem_get(struct sbefifo_context *sctx, uint64_t addr, uint32_t size, uint16_t flags, uint8_t **data)
+{
+ uint8_t *out;
+ uint64_t start_addr, end_addr;
+ uint32_t msg[6];
+ uint32_t cmd, out_len;
+ uint32_t align, offset, len, extra_bytes, i, j;
+ int rc;
+ bool do_tag = false, do_ecc = false;
+
+ if (flags & SBEFIFO_MEMORY_FLAG_PROC) {
+ align = 8;
+
+ if (flags & SBEFIFO_MEMORY_FLAG_ECC_REQ)
+ do_ecc = true;
+
+ if (flags & SBEFIFO_MEMORY_FLAG_TAG_REQ)
+ do_tag = true;
+
+ } else if (flags & SBEFIFO_MEMORY_FLAG_PBA) {
+ align = 128;
+ } else {
+ return EINVAL;
+ }
+
+ start_addr = addr & (~(uint64_t)(align-1));
+ end_addr = (addr + size + (align-1)) & (~(uint64_t)(align-1));
+
+ if (end_addr - start_addr > 0xffffffff)
+ return EINVAL;
+
+ offset = addr - start_addr;
+ len = end_addr - start_addr;
+
+ extra_bytes = 0;
+ if (do_tag)
+ extra_bytes = len / 8;
+
+ if (do_ecc)
+ extra_bytes = len / 8;
+
+ cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_GET_MEMORY;
+
+ msg[0] = htobe32(6); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(flags);
+ msg[3] = htobe32(start_addr >> 32);
+ msg[4] = htobe32(start_addr & 0xffffffff);
+ msg[5] = htobe32(len);
+
+ out_len = len + extra_bytes + 4;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 6 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != len + extra_bytes + 4) {
+ free(out);
+ return EPROTO;
+ }
+
+ len = be32toh(*(uint32_t *) &out[out_len-4]);
+ *data = malloc(len);
+ if (! *data) {
+ free(out);
+ return ENOMEM;
+ }
+
+ i = 0;
+ j = 0;
+ while (i < len) {
+ memcpy((void *)&(*data)[j], (void *)&out[i], 8);
+ i += 8;
+ j += 8;
+
+ if (do_tag)
+ i++;
+
+ if (do_ecc)
+ i++;
+ }
+ if (i < len)
+ memcpy((void *)&(*data)[j], (void *)&out[i], len - i);
+
+ memmove(*data, *data + offset, size);
+
+ free(out);
+ return 0;
+}
+
+int sbefifo_mem_put(struct sbefifo_context *sctx, uint64_t addr, uint8_t *data, uint32_t data_len, uint16_t flags)
+{
+ uint8_t *out;
+ uint32_t nwords = (data_len+3)/4;
+ uint32_t msg[6+nwords];
+ uint32_t cmd, out_len;
+ uint32_t align;
+ int rc;
+
+ if (flags & SBEFIFO_MEMORY_FLAG_PROC)
+ align = 8;
+ else if (flags & SBEFIFO_MEMORY_FLAG_PBA)
+ align = 128;
+ else
+ return EINVAL;
+
+ if (addr & (align-1))
+ return EINVAL;
+
+ cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_PUT_MEMORY;
+
+ msg[0] = htobe32(6 + nwords); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(flags);
+ msg[3] = htobe32(addr >> 32);
+ msg[4] = htobe32(addr & 0xffffffff);
+ msg[5] = htobe32(data_len);
+ memcpy(&msg[6], data, data_len);
+
+ out_len = 1 * 4;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, (6+nwords) * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 4) {
+ free(out);
+ return EPROTO;
+ }
+
+ free(out);
+ return 0;
+}
+
+int sbefifo_occsram_get(struct sbefifo_context *sctx, uint32_t addr, uint32_t size, uint8_t mode, uint8_t **data, uint32_t *data_len)
+{
+ uint8_t *out;
+ uint32_t start_addr, end_addr;
+ uint32_t msg[5];
+ uint32_t cmd, out_len;
+ uint32_t align, offset, len;
+ int rc;
+
+ align = 8;
+ start_addr = addr & (~(uint32_t)(align-1));
+ end_addr = (addr + size + (align-1)) & (~(uint32_t)(align-1));
+
+ offset = addr - start_addr;
+ len = end_addr - start_addr;
+
+ cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_GET_OCCSRAM;
+
+ msg[0] = htobe32(5); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(mode);
+ msg[3] = htobe32(start_addr);
+ msg[4] = htobe32(len);
+
+ out_len = len + 4;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 5 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != len + 4) {
+ free(out);
+ return EPROTO;
+ }
+
+ *data_len = be32toh(*(uint32_t *) &out[out_len-4]);
+ *data = malloc(*data_len);
+ if (! *data) {
+ free(out);
+ return ENOMEM;
+ }
+ memcpy(*data, out + offset, size);
+
+ free(out);
+ return 0;
+}
+
+int sbefifo_occsram_put(struct sbefifo_context *sctx, uint32_t addr, uint8_t *data, uint32_t data_len, uint8_t mode)
+{
+ uint8_t *out;
+ uint32_t nwords = (data_len+3)/4;
+ uint32_t msg[5+nwords];
+ uint32_t cmd, out_len;
+ uint32_t align;
+ int rc;
+
+ align = 8;
+
+ if (addr & (align-1))
+ return EINVAL;
+
+ if (data_len & (align-1))
+ return EINVAL;
+
+ cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_PUT_OCCSRAM;
+
+ msg[0] = htobe32(5 + nwords); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(mode);
+ msg[3] = htobe32(addr);
+ msg[4] = htobe32(data_len);
+ memcpy(&msg[6], data, data_len);
+
+ out_len = 4;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, (5+nwords) * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 4) {
+ free(out);
+ return EPROTO;
+ }
+
+ free(out);
+ return 0;
+}
diff --git a/libsbefifo/cmd_mpipl.c b/libsbefifo/cmd_mpipl.c
new file mode 100644
index 0000000..b5f9ea5
--- /dev/null
+++ b/libsbefifo/cmd_mpipl.c
@@ -0,0 +1,102 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <endian.h>
+#include <errno.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_mpipl_enter(struct sbefifo_context *sctx)
+{
+ uint8_t *out;
+ uint32_t msg[2];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_MPIPL | SBEFIFO_CMD_ENTER_MPIPL;
+
+ msg[0] = htobe32(2); // number of words
+ msg[1] = htobe32(cmd);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 2 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
+
+int sbefifo_mpipl_continue(struct sbefifo_context *sctx)
+{
+ uint8_t *out;
+ uint32_t msg[2];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_MPIPL | SBEFIFO_CMD_CONTINUE_MPIPL;
+
+ msg[0] = htobe32(2); // number of words
+ msg[1] = htobe32(cmd);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 2 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
+
+int sbefifo_mpipl_stopclocks(struct sbefifo_context *sctx, uint16_t target_type, uint8_t chiplet_id)
+{
+ uint8_t *out;
+ uint32_t msg[3];
+ uint32_t cmd, out_len;
+ uint32_t target;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_GENERIC | SBEFIFO_CMD_STOP_CLOCKS;
+ target = ((uint32_t)target_type << 16) | chiplet_id;
+
+ msg[0] = htobe32(3); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(target);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 3 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
diff --git a/libsbefifo/cmd_register.c b/libsbefifo/cmd_register.c
new file mode 100644
index 0000000..201ceb5
--- /dev/null
+++ b/libsbefifo/cmd_register.c
@@ -0,0 +1,115 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <endian.h>
+#include <errno.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_register_get(struct sbefifo_context *sctx, uint8_t core_id, uint8_t thread_id, uint8_t reg_type, uint8_t *reg_id, uint8_t reg_count, uint64_t **value)
+{
+ uint8_t *out;
+ uint32_t msg[3+reg_count];
+ uint32_t cmd, out_len;
+ uint32_t r, i;
+ int rc;
+
+ if (reg_count == 0 || reg_count > 64)
+ return EINVAL;
+
+ cmd = SBEFIFO_CMD_CLASS_REGISTER | SBEFIFO_CMD_GET_REGISTER;
+ r = ((uint32_t)(core_id & 0xff) << 16) |
+ ((uint32_t)(thread_id & 0x3) << 12) |
+ ((uint32_t)(reg_type & 0x3) << 8) |
+ ((uint32_t)(reg_count & 0xff));
+
+ msg[0] = htobe32(3+reg_count); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(r);
+ for (i=0; i<reg_count; i++) {
+ msg[3+i] = htobe32(reg_id[i] & 0xff);
+ }
+
+ out_len = reg_count * 8;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, (3+reg_count) * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != reg_count * 8) {
+ free(out);
+ return EPROTO;
+ }
+
+ *value = malloc(reg_count * 8);
+ if (! *value) {
+ free(out);
+ return ENOMEM;
+ }
+
+ for (i=0; i<reg_count; i++) {
+ uint32_t val1, val2;
+
+ val1 = be32toh(*(uint32_t *) &out[i*4]);
+ val2 = be32toh(*(uint32_t *) &out[i*4+4]);
+
+ (*value)[i] = ((uint64_t)val1 << 32) | (uint64_t)val2;
+ }
+
+ free(out);
+ return 0;
+}
+
+int sbefifo_register_put(struct sbefifo_context *sctx, uint8_t core_id, uint8_t thread_id, uint8_t reg_type, uint8_t *reg_id, uint8_t reg_count, uint64_t *value)
+{
+ uint8_t *out;
+ uint32_t msg[3+(3*reg_count)];
+ uint32_t cmd, out_len;
+ uint32_t r, i;
+ int rc;
+
+ if (reg_count == 0 || reg_count > 64)
+ return EINVAL;
+
+ cmd = SBEFIFO_CMD_CLASS_REGISTER | SBEFIFO_CMD_PUT_REGISTER;
+ r = ((uint32_t)(core_id & 0xff) << 16) |
+ ((uint32_t)(thread_id & 0x3) << 12) |
+ ((uint32_t)(reg_type & 0x3) << 8) |
+ ((uint32_t)(reg_count & 0xff));
+
+ msg[0] = htobe32(3 + 3*reg_count); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(r);
+ for (i=0; i<reg_count; i++) {
+ msg[3+i*3] = htobe32(reg_id[i] & 0xff);
+ msg[3+i*3+1] = htobe32(value[i] >> 32);
+ msg[3+i*3+2] = htobe32(value[i] & 0xffffffff);
+ }
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, (3+3*reg_count) * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
diff --git a/libsbefifo/cmd_ring.c b/libsbefifo/cmd_ring.c
new file mode 100644
index 0000000..70478e3
--- /dev/null
+++ b/libsbefifo/cmd_ring.c
@@ -0,0 +1,119 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <endian.h>
+#include <errno.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_ring_get(struct sbefifo_context *sctx, uint32_t ring_addr, uint32_t ring_len_bits, uint16_t flags, uint8_t **ring_data, uint32_t *ring_len)
+{
+ uint8_t *out;
+ uint32_t msg[5];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_RING | SBEFIFO_CMD_GET_RING;
+
+ msg[0] = htobe32(5); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(ring_addr);
+ msg[3] = htobe32(ring_len_bits);
+ msg[4] = htobe32(flags);
+
+ /* multiples of 64 bits */
+ out_len = (ring_len_bits + 63) / 8;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 5 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len*8 < ring_len_bits) {
+ free(out);
+ return EPROTO;
+ }
+
+ *ring_len = be32toh(*(uint32_t *) &out[out_len-4]);
+ *ring_data = malloc(*ring_len);
+ if (! *ring_data) {
+ free(out);
+ return ENOMEM;
+ }
+ memcpy(*ring_data, out, *ring_len);
+
+ free(out);
+ return 0;
+}
+
+int sbefifo_ring_put(struct sbefifo_context *sctx, uint16_t ring_mode, uint8_t *ring_data, uint32_t ring_data_len)
+{
+ uint8_t *out;
+ uint32_t nwords = (ring_data_len + 3) / 4;
+ uint32_t msg[3+nwords];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_RING | SBEFIFO_CMD_PUT_RING;
+
+ msg[0] = htobe32(3 + nwords); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(ring_mode);
+ memcpy(&msg[3], ring_data, ring_data_len);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, (3+nwords) * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
+
+int sbefifo_ring_put_from_image(struct sbefifo_context *sctx, uint16_t target, uint8_t chiplet_id, uint16_t ring_id, uint16_t ring_mode)
+{
+ uint8_t *out;
+ uint32_t msg[3];
+ uint32_t cmd, out_len;
+ uint32_t target_word, ring_word;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_RING | SBEFIFO_CMD_PUT_RING_IMAGE;
+ target_word = ((uint32_t)target << 16) | (uint32_t)chiplet_id;
+ ring_word = ((uint32_t)ring_id << 16) | (uint32_t)ring_mode;
+
+ msg[0] = htobe32(3); // number of words
+ msg[1] = htobe32(target_word);
+ msg[2] = htobe32(ring_word);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 3 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
diff --git a/libsbefifo/cmd_scom.c b/libsbefifo/cmd_scom.c
new file mode 100644
index 0000000..cc236ca
--- /dev/null
+++ b/libsbefifo/cmd_scom.c
@@ -0,0 +1,147 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <endian.h>
+#include <errno.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_scom_get(struct sbefifo_context *sctx, uint64_t addr, uint64_t *value)
+{
+ uint8_t *out;
+ uint32_t msg[4];
+ uint32_t cmd, out_len;
+ uint32_t val1, val2;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_SCOM | SBEFIFO_CMD_GET_SCOM;
+
+ msg[0] = htobe32(4); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(addr >> 32);
+ msg[3] = htobe32(addr & 0xffffffff);
+
+ out_len = 2 * 4;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 4 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 2 * 4) {
+ free(out);
+ return EPROTO;
+ }
+
+ val1 = be32toh(*(uint32_t *) &out[0]);
+ val2 = be32toh(*(uint32_t *) &out[4]);
+ free(out);
+
+ *value = ((uint64_t)val1 << 32) | (uint64_t)val2;
+
+ return 0;
+}
+
+int sbefifo_scom_put(struct sbefifo_context *sctx, uint64_t addr, uint64_t value)
+{
+ uint8_t *out;
+ uint32_t msg[6];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_SCOM | SBEFIFO_CMD_PUT_SCOM;
+
+ msg[0] = htobe32(6); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(addr >> 32);
+ msg[3] = htobe32(addr & 0xffffffff);
+ msg[2] = htobe32(value >> 32);
+ msg[3] = htobe32(value & 0xffffffff);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 6 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
+
+int sbefifo_scom_modify(struct sbefifo_context *sctx, uint64_t addr, uint64_t value, uint8_t operand)
+{
+ uint8_t *out;
+ uint32_t msg[7];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_SCOM | SBEFIFO_CMD_MODIFY_SCOM;
+
+ msg[0] = htobe32(7); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(operand);
+ msg[3] = htobe32(addr >> 32);
+ msg[4] = htobe32(addr & 0xffffffff);
+ msg[5] = htobe32(value >> 32);
+ msg[6] = htobe32(value & 0xffffffff);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 7 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
+
+int sbefifo_scom_put_mask(struct sbefifo_context *sctx, uint64_t addr, uint64_t value, uint64_t mask)
+{
+ uint8_t *out;
+ uint32_t msg[8];
+ uint32_t cmd, out_len;
+ int rc;
+
+ cmd = SBEFIFO_CMD_CLASS_SCOM | SBEFIFO_CMD_PUT_SCOM_MASK;
+
+ msg[0] = htobe32(8); // number of words
+ msg[1] = htobe32(cmd);
+ msg[2] = htobe32(addr >> 32);
+ msg[3] = htobe32(addr & 0xffffffff);
+ msg[4] = htobe32(value >> 32);
+ msg[5] = htobe32(value & 0xffffffff);
+ msg[6] = htobe32(mask >> 32);
+ msg[7] = htobe32(mask & 0xffffffff);
+
+ out_len = 0;
+ rc = sbefifo_operation(sctx, (uint8_t *)msg, 8 * 4, cmd, &out, &out_len);
+ if (rc)
+ return rc;
+
+ if (out_len != 0) {
+ free(out);
+ return EPROTO;
+ }
+
+ return 0;
+}
diff --git a/libsbefifo/connect.c b/libsbefifo/connect.c
new file mode 100644
index 0000000..08194e1
--- /dev/null
+++ b/libsbefifo/connect.c
@@ -0,0 +1,74 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "libsbefifo.h"
+#include "sbefifo_private.h"
+
+int sbefifo_connect(const char *fifo_path, struct sbefifo_context **out)
+{
+ struct sbefifo_context *sctx;
+ int fd, rc;
+
+ sctx = malloc(sizeof(struct sbefifo_context));
+ if (!sctx) {
+ fprintf(stderr, "Memory allocation error\n");
+ return ENOMEM;
+ }
+
+ *sctx = (struct sbefifo_context) {
+ .fd = -1,
+ };
+
+ fd = open(fifo_path, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ rc = errno;
+ fprintf(stderr, "Error opening fifo %s\n", fifo_path);
+ free(sctx);
+ return rc;
+ }
+
+ sctx->fd = fd;
+
+ *out = sctx;
+ return 0;
+}
+
+void sbefifo_disconnect(struct sbefifo_context *sctx)
+{
+ if (sctx->fd != -1)
+ close(sctx->fd);
+
+ if (sctx->ffdc)
+ free(sctx->ffdc);
+
+ free(sctx);
+}
+
+void sbefifo_debug(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
diff --git a/libsbefifo/ffdc.c b/libsbefifo/ffdc.c
new file mode 100644
index 0000000..f29afc1
--- /dev/null
+++ b/libsbefifo/ffdc.c
@@ -0,0 +1,151 @@
+/* Copyright 2016 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sbefifo_private.h"
+
+void sbefifo_ffdc_clear(struct sbefifo_context *sctx)
+{
+ sctx->status = 0;
+
+ if (sctx->ffdc) {
+ free(sctx->ffdc);
+ sctx->ffdc = NULL;
+ sctx->ffdc_len = 0;
+ }
+}
+
+void sbefifo_ffdc_set(struct sbefifo_context *sctx, uint32_t status, uint8_t *ffdc, uint32_t ffdc_len)
+{
+ sctx->status = status;
+
+ sctx->ffdc = malloc(ffdc_len);
+ if (!sctx->ffdc) {
+ fprintf(stderr, "Memory allocation error\n");
+ return;
+ }
+
+ memcpy(sctx->ffdc, ffdc, ffdc_len);
+ sctx->ffdc_len = ffdc_len;
+}
+
+uint32_t sbefifo_ffdc_get(struct sbefifo_context *sctx, const uint8_t **ffdc, uint32_t *ffdc_len)
+{
+ *ffdc = sctx->ffdc;
+ *ffdc_len = sctx->ffdc_len;
+
+ return sctx->status;
+}
+
+static int sbefifo_ffdc_get_uint32(struct sbefifo_context *sctx, uint32_t offset, uint32_t *value)
+{
+ uint32_t v;
+
+ if (offset + 4 > sctx->ffdc_len)
+ return -1;
+
+ memcpy(&v, sctx->ffdc + offset, 4);
+ *value = be32toh(v);
+
+ return 0;
+}
+
+static int sbefifo_ffdc_dump_pkg(struct sbefifo_context *sctx, uint32_t offset)
+{
+ uint32_t offset2 = offset;
+ uint32_t header, value;
+ uint16_t magic, len_words;
+ int i, rc;
+
+ rc = sbefifo_ffdc_get_uint32(sctx, offset2, &header);
+ if (rc < 0)
+ return -1;
+ offset2 += 4;
+
+ /*
+ * FFDC package structure
+ *
+ * +----------+----------+----------+----------+
+ * | Byte 0 | Byte 1 | Byte 2 | Byte 3 |
+ * +----------+----------+----------+----------+----------+
+ * | word 0 | magic | length in words (N) |
+ * +----------+---------------------+---------------------+
+ * | word 1 | sequence id | command |
+ * +----------+---------------------+---------------------+
+ * | word 2 | return code |
+ * +----------+-------------------------------------------+
+ * | word 3 | FFDC Data - word 0 |
+ * +----------+-------------------------------------------+
+ * | word 4 | FFDC Data - word 1 |
+ * +----------+-------------------------------------------+
+ * | ... | ... |
+ * +----------+-------------------------------------------+
+ * | word N | FFDC Data - word N-3 |
+ * +----------+----------+----------+----------+----------+
+ */
+
+ magic = header >> 16;
+ if (magic != 0xffdc) {
+ fprintf(stderr, "sbefifo: ffdc expected 0xffdc, got 0x%04x\n", magic);
+ return -1;
+ }
+
+ len_words = header & 0xffff;
+
+ rc = sbefifo_ffdc_get_uint32(sctx, offset2, &value);
+ if (rc < 0)
+ return -1;
+ offset2 += 4;
+
+ printf("FFDC: Sequence = %u\n", value >> 16);
+ printf("FFDC: Command = 0x%08x\n", value & 0xffff);
+
+ rc = sbefifo_ffdc_get_uint32(sctx, offset2, &value);
+ if (rc < 0)
+ return -1;
+ offset2 += 4;
+
+ printf("FFDC: RC = 0x%08x\n", value);
+
+ for (i=0; i<len_words-3; i++) {
+ rc = sbefifo_ffdc_get_uint32(sctx, offset2, &value);
+ if (rc < 0)
+ return -1;
+ offset2 += 4;
+
+ printf("FFDC: Data: 0x%08x\n", value);
+ }
+
+ return offset2 - offset;
+}
+
+void sbefifo_ffdc_dump(struct sbefifo_context *sctx)
+{
+ uint32_t offset = 0;
+
+ while (offset < sctx->ffdc_len) {
+ int n;
+
+ n = sbefifo_ffdc_dump_pkg(sctx, offset);
+ if (n <= 0)
+ break;
+
+ offset += n;
+ }
+}
diff --git a/libsbefifo/libsbefifo.h b/libsbefifo/libsbefifo.h
new file mode 100644
index 0000000..84b0169
--- /dev/null
+++ b/libsbefifo/libsbefifo.h
@@ -0,0 +1,116 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LIBSBEFIFO_H__
+#define __LIBSBEFIFO_H__
+
+#include <stdint.h>
+
+#define SBEFIFO_PRI_SUCCESS 0x00000000
+#define SBEFIFO_PRI_INVALID_COMMAND 0x00010000
+#define SBEFIFO_PRI_INVALID_DATA 0x00020000
+#define SBEFIFO_PRI_SEQUENCE_ERROR 0x00030000
+#define SBEFIFO_PRI_INTERNAL_ERROR 0x00040000
+#define SBEFIFO_PRI_UNKNOWN_ERROR 0x00FE0000
+
+#define SBEFIFO_SEC_SUCCESS 0x0000
+#define SBEFIFO_SEC_INVALID_CMD_CLASS 0x0001
+#define SBEFIFO_SEC_INVALID_CMD 0x0002
+#define SBEFIFO_SEC_INVALID_ADDRESS 0x0003
+#define SBEFIFO_SEC_INVALID_TARGET 0x0004
+#define SBEFIFO_SEC_INVALID_CHIPLET 0x0005
+#define SBEFIFO_SEC_TARGET_NOT_PRESENT 0x0006
+#define SBEFIFO_SEC_TARGET_NOT_FUNCTIONAL 0x0007
+#define SBEFIFO_SEC_CMD_NOT_ALLOWED 0x0008
+#define SBEFIFO_SEC_INVALID_FUNCTION 0x0009
+#define SBEFIFO_SEC_GENERIC_FAILURE 0x000A
+#define SBEFIFO_SEC_INVALID_ACCESS 0x000B
+#define SBEFIFO_SEC_SBE_OS_FAIL 0x000C
+#define SBEFIFO_SEC_SBE_ACCESS_FAIL 0x000D
+#define SBEFIFO_SEC_MISSING_DATA 0x000E
+#define SBEFIFO_SEC_EXTRA_DATA 0x000F
+#define SBEFIFO_SEC_HW_TIMEOUT 0x0010
+#define SBEFIFO_SEC_PIB_ERROR 0x0011
+#define SBEFIFO_SEC_PARITY_ERROR 0x0012
+
+struct sbefifo_context;
+
+int sbefifo_connect(const char *fifo_path, struct sbefifo_context **out);
+void sbefifo_disconnect(struct sbefifo_context *sctx);
+
+uint32_t sbefifo_ffdc_get(struct sbefifo_context *sctx, const uint8_t **ffdc, uint32_t *ffdc_len);
+void sbefifo_ffdc_dump(struct sbefifo_context *sctx);
+
+int sbefifo_istep_execute(struct sbefifo_context *sctx, uint8_t major, uint8_t minor);
+
+#define SBEFIFO_SCOM_OPERAND_NONE 0
+#define SBEFIFO_SCOM_OPERAND_OR 1
+#define SBEFIFO_SCOM_OPERAND_AND 2
+#define SBEFIFO_SCOM_OPERAND_XOR 3
+
+int sbefifo_scom_get(struct sbefifo_context *sctx, uint64_t addr, uint64_t *value);
+int sbefifo_scom_put(struct sbefifo_context *sctx, uint64_t addr, uint64_t value);
+int sbefifo_scom_modify(struct sbefifo_context *sctx, uint64_t addr, uint64_t value, uint8_t operand);
+int sbefifo_scom_put_mask(struct sbefifo_context *sctx, uint64_t addr, uint64_t value, uint64_t mask);
+
+int sbefifo_ring_get(struct sbefifo_context *sctx, uint32_t ring_addr, uint32_t ring_len_bits, uint16_t flags, uint8_t **ring_data, uint32_t *ring_len);
+int sbefifo_ring_put(struct sbefifo_context *sctx, uint16_t ring_mode, uint8_t *ring_data, uint32_t ring_data_len);
+int sbefifo_ring_put_from_image(struct sbefifo_context *sctx, uint16_t target, uint8_t chiplet_id, uint16_t ring_id, uint16_t ring_mode);
+
+#define SBEFIFO_MEMORY_FLAG_PROC 0x0001
+#define SBEFIFO_MEMORY_FLAG_PBA 0x0002
+#define SBEFIFO_MEMORY_FLAG_AUTO_INCR 0x0004
+#define SBEFIFO_MEMORY_FLAG_ECC_REQ 0x0008
+#define SBEFIFO_MEMORY_FLAG_TAG_REQ 0x0010
+#define SBEFIFO_MEMORY_FLAG_FAST_MODE 0x0020
+#define SBEFIFO_MEMORY_FLAG_LCO_MODE 0x0040 // only for mem_put
+#define SBEFIFO_MEMORY_FLAG_CI 0x0080
+#define SBEFIFO_MEMORY_FLAG_PASSTHRU 0x0100
+#define SBEFIFO_MEMORY_FLAG_CACHEINJECT 0x0200 // only for mem_put
+
+int sbefifo_mem_get(struct sbefifo_context *sctx, uint64_t addr, uint32_t size, uint16_t flags, uint8_t **data);
+int sbefifo_mem_put(struct sbefifo_context *sctx, uint64_t addr, uint8_t *data, uint32_t len, uint16_t flags);
+int sbefifo_occsram_get(struct sbefifo_context *sctx, uint32_t addr, uint32_t size, uint8_t mode, uint8_t **data, uint32_t *data_len);
+int sbefifo_occsram_put(struct sbefifo_context *sctx, uint32_t addr, uint8_t *data, uint32_t data_len, uint8_t mode);
+
+#define SBEFIFO_REGISTER_TYPE_GPR 0x0
+#define SBEFIFO_REGISTER_TYPE_SPR 0x1
+#define SBEFIFO_REGISTER_TYPE_FPR 0x2
+
+int sbefifo_register_get(struct sbefifo_context *sctx, uint8_t core_id, uint8_t thread_id, uint8_t reg_type, uint8_t *reg_id, uint8_t reg_count, uint64_t **value);
+int sbefifo_register_put(struct sbefifo_context *sctx, uint8_t core_id, uint8_t thread_id, uint8_t reg_type, uint8_t *reg_id, uint8_t reg_count, uint64_t *value);
+
+int sbefifo_control_fast_array(struct sbefifo_context *sctx, uint16_t target_type, uint8_t chiplet_id, uint8_t mode, uint64_t clock_cycle);
+int sbefifo_control_trace_array(struct sbefifo_context *sctx, uint16_t target_type, uint8_t chiplet_id, uint16_t array_id, uint16_t operation, uint8_t **trace_data, uint32_t *trace_data_len);
+
+#define SBEFIFO_INSN_OP_START 0x0
+#define SBEFIFO_INSN_OP_STOP 0x1
+#define SBEFIFO_INSN_OP_STEP 0x2
+#define SBEFIFO_INSN_OP_SRESET 0x3
+
+int sbefifo_control_insn(struct sbefifo_context *sctx, uint8_t core_id, uint8_t thread_id, uint8_t thread_op, uint8_t mode);
+
+int sbefifo_get_ffdc(struct sbefifo_context *sctx, uint8_t **ffdc, uint32_t *ffdc_len);
+int sbefifo_get_capabilities(struct sbefifo_context *sctx, uint32_t *version, char **commit_id, uint32_t **caps, uint32_t *caps_count);
+int sbefifo_get_frequencies(struct sbefifo_context *sctx, uint32_t **freq, uint32_t *freq_count);
+int sbefifo_quiesce(struct sbefifo_context *sctx);
+
+int sbefifo_mpipl_enter(struct sbefifo_context *sctx);
+int sbefifo_mpipl_continue(struct sbefifo_context *sctx);
+int sbefifo_mpipl_stopclocks(struct sbefifo_context *sctx, uint16_t target_type, uint8_t chiplet_id);
+
+
+#endif /* __LIBSBEFIFO_H__ */
diff --git a/libsbefifo/operation.c b/libsbefifo/operation.c
new file mode 100644
index 0000000..43418a1
--- /dev/null
+++ b/libsbefifo/operation.c
@@ -0,0 +1,149 @@
+/* Copyright 2016 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "sbefifo_private.h"
+
+static int sbefifo_read(struct sbefifo_context *sctx, void *buf, size_t *buflen)
+{
+ ssize_t n;
+
+ assert(*buflen > 0);
+
+ n = read(sctx->fd, buf, *buflen);
+ if (n < 0)
+ return errno;
+
+ *buflen = n;
+ return 0;
+}
+
+static int sbefifo_write(struct sbefifo_context *sctx, void *buf, size_t buflen)
+{
+ ssize_t n;
+
+ assert(buflen > 0);
+
+ n = write(sctx->fd, buf, buflen);
+ if (n < 0)
+ return errno;
+
+ if (n != buflen)
+ return EIO;
+
+ return 0;
+}
+
+int sbefifo_operation(struct sbefifo_context *sctx,
+ uint8_t *msg, uint32_t msg_len, uint16_t cmd,
+ uint8_t **out, uint32_t *out_len)
+{
+ uint8_t *buf;
+ size_t buflen;
+ uint32_t offset_word, header_word, status_word;
+ uint32_t offset;
+ int rc;
+
+ assert(msg);
+ assert(msg_len > 0);
+
+ sbefifo_ffdc_clear(sctx);
+
+ /*
+ * Allocate extra memory for FFDC (SBEFIFO_MAX_FFDC_SIZE = 0x2000)
+ * Use *out_len as a hint to expected reply length
+ */
+ buflen = (*out_len + 0x2000 + 3) & ~(uint32_t)3;
+ buf = malloc(buflen);
+ if (!buf)
+ return ENOMEM;
+
+ LOG("request: cmd=%08x, len=%u\n", cmd, msg_len);
+
+ rc = sbefifo_write(sctx, msg, msg_len);
+ if (rc) {
+ LOG("write: cmd=%08x, rc=%d\n", cmd, rc);
+ return rc;
+ }
+
+ rc = sbefifo_read(sctx, buf, &buflen);
+ if (rc) {
+ LOG("read: cmd=%08x, buflen=%zu, rc=%d\n", cmd, buflen, rc);
+ return rc;
+ }
+
+ /*
+ * At least 3 words are expected in response
+ * - header word
+ * - status word
+ * - header offset word
+ */
+ if (buflen < 3 * 4) {
+ LOG("reply: cmd=%08x, len=%u\n", cmd, buflen);
+ rc = EPROTO;
+ goto fail;
+ }
+
+ /* Last word is header offset (in words) */
+ offset_word = be32toh(*(uint32_t *) &buf[buflen-4]);
+ offset = buflen - (offset_word * 4);
+
+ *out_len = offset;
+
+ header_word = be32toh(*(uint32_t *) &buf[offset]);
+ offset += 4;
+
+ status_word = be32toh(*(uint32_t *) &buf[offset]);
+ offset += 4;
+
+ if (header_word != (0xc0de0000 | cmd)) {
+ LOG("reply: cmd=%08x, len=%u, header=%08x\n", cmd, buflen, header_word);
+ rc = EPROTO;
+ goto fail;
+ }
+
+ LOG("reply: cmd=%08x, len=%u, status=%08x\n", cmd, buflen, status_word);
+
+ if (status_word) {
+ sbefifo_ffdc_set(sctx, status_word, buf + offset, buflen - offset-4);
+ rc = 201;
+ goto fail;
+ }
+
+ if (*out_len > 0) {
+ *out = malloc(*out_len);
+ if (! *out) {
+ rc = ENOMEM;
+ goto fail;
+ }
+ memcpy(*out, buf, *out_len);
+ } else {
+ *out = NULL;
+ }
+
+ free(buf);
+ return 0;
+
+fail:
+ free(buf);
+ return rc;
+}
diff --git a/libsbefifo/sbefifo_private.h b/libsbefifo/sbefifo_private.h
new file mode 100644
index 0000000..87416b7
--- /dev/null
+++ b/libsbefifo/sbefifo_private.h
@@ -0,0 +1,88 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SBEFIFO_PRIVATE_H__
+#define __SBEFIFO_PRIVATE_H__
+
+#include <stdint.h>
+
+#define SBEFIFO_CMD_CLASS_CONTROL 0xA100
+#define SBEFIFO_CMD_EXECUTE_ISTEP 0x01
+
+#define SBEFIFO_CMD_CLASS_SCOM 0xA200
+#define SBEFIFO_CMD_GET_SCOM 0x01
+#define SBEFIFO_CMD_PUT_SCOM 0x02
+#define SBEFIFO_CMD_MODIFY_SCOM 0x03
+#define SBEFIFO_CMD_PUT_SCOM_MASK 0x04
+#define SBEFIFO_CMD_MULTI_SCOM 0x05
+
+#define SBEFIFO_CMD_CLASS_RING 0xA300
+#define SBEFIFO_CMD_GET_RING 0x01
+#define SBEFIFO_CMD_PUT_RING 0x02
+#define SBEFIFO_CMD_PUT_RING_IMAGE 0x03
+
+#define SBEFIFO_CMD_CLASS_MEMORY 0xA400
+#define SBEFIFO_CMD_GET_MEMORY 0x01
+#define SBEFIFO_CMD_PUT_MEMORY 0x02
+#define SBEFIFO_CMD_GET_OCCSRAM 0x03
+#define SBEFIFO_CMD_PUT_OCCSRAM 0x04
+
+#define SBEFIFO_CMD_CLASS_REGISTER 0xA500
+#define SBEFIFO_CMD_GET_REGISTER 0x01
+#define SBEFIFO_CMD_PUT_REGISTER 0x02
+
+#define SBEFIFO_CMD_CLASS_ARRAY 0xA600
+#define SBEFIFO_CMD_FAST_ARRAY 0x01
+#define SBEFIFO_CMD_TRACE_ARRAY 0x02
+
+#define SBEFIFO_CMD_CLASS_INSTRUCTION 0xA700
+#define SBEFIFO_CMD_CONTROL_INSN 0x01
+
+#define SBEFIFO_CMD_CLASS_GENERIC 0xA800
+#define SBEFIFO_CMD_GET_FFDC 0x01
+#define SBEFIFO_CMD_GET_CAPABILITY 0x02
+#define SBEFIFO_CMD_GET_FREQUENCY 0x03
+#define SBEFIFO_CMD_QUIESCE 0x05
+
+#define SBEFIFO_CMD_CLASS_MPIPL 0xA900
+#define SBEFIFO_CMD_ENTER_MPIPL 0x01
+#define SBEFIFO_CMD_CONTINUE_MPIPL 0x02
+#define SBEFIFO_CMD_STOP_CLOCKS 0x03
+
+struct sbefifo_context {
+ int fd;
+
+ uint32_t status;
+ uint8_t *ffdc;
+ uint32_t ffdc_len;
+};
+
+void sbefifo_debug(const char *fmt, ...);
+
+void sbefifo_ffdc_clear(struct sbefifo_context *sctx);
+void sbefifo_ffdc_set(struct sbefifo_context *sctx, uint32_t status, uint8_t *ffdc, uint32_t ffdc_len);
+
+int sbefifo_operation(struct sbefifo_context *sctx,
+ uint8_t *msg, uint32_t msg_len, uint16_t cmd,
+ uint8_t **out, uint32_t *out_len);
+
+#ifdef LIBSBEFIFO_DEBUG
+#define LOG(fmt, args...) sbefifo_debug(fmt, ##args)
+#else
+#define LOG(fmt, args...)
+#endif
+
+#endif /* __SBEFIFO_PRIVATE_H__ */
--
2.21.0
More information about the Pdbg
mailing list