[Pdbg] [PATCH 01/10] sbefifo: Refactor ffdc parsing code to store ffdc data
Amitay Isaacs
amitay at ozlabs.org
Wed Jul 3 13:46:10 AEST 2019
Instead of dumping ffdc data, store it so an application can query it in
case of chip-op failures.
FFDC data is stored only for the last chip-op.
Signed-off-by: Amitay Isaacs <amitay at ozlabs.org>
---
libpdbg/hwunit.h | 3 ++
libpdbg/sbefifo.c | 116 +++++++++++++++++++++++++++++++++++-----------
2 files changed, 91 insertions(+), 28 deletions(-)
diff --git a/libpdbg/hwunit.h b/libpdbg/hwunit.h
index b816ae3..0b0c62b 100644
--- a/libpdbg/hwunit.h
+++ b/libpdbg/hwunit.h
@@ -71,6 +71,9 @@ struct sbefifo {
int (*mem_read)(struct sbefifo *, uint64_t, uint8_t *, uint64_t, bool);
int (*mem_write)(struct sbefifo *, uint64_t, uint8_t *, uint64_t, bool);
int fd;
+ uint32_t status;
+ uint8_t *ffdc;
+ uint32_t ffdc_len;
};
#define target_to_sbefifo(x) container_of(x, struct sbefifo, target)
diff --git a/libpdbg/sbefifo.c b/libpdbg/sbefifo.c
index 284d3d5..a23d0b4 100644
--- a/libpdbg/sbefifo.c
+++ b/libpdbg/sbefifo.c
@@ -69,22 +69,76 @@ static int sbefifo_op_write(struct sbefifo *sbefifo, void *buf, size_t buflen)
return 0;
}
-static int sbefifo_op_ffdc_read(uint8_t *buf, uint32_t buflen)
+static void sbefifo_ffdc_clear(struct sbefifo *sbefifo)
{
- int offset = 0;
+ sbefifo->status = 0;
+ if (sbefifo->ffdc) {
+ free(sbefifo->ffdc);
+ sbefifo->ffdc = NULL;
+ sbefifo->ffdc_len = 0;
+ }
+}
+
+static void sbefifo_ffdc_set(struct sbefifo *sbefifo, uint8_t *buf, uint32_t buflen, uint32_t status)
+{
+ sbefifo->status = status;
+
+ sbefifo->ffdc = malloc(buflen);
+ if (!sbefifo->ffdc) {
+ PR_ERROR("sbefifo: Failed to store FFDC data\n");
+ return;
+ }
+
+ memcpy(sbefifo->ffdc, buf, buflen);
+ sbefifo->ffdc_len = buflen;
+}
+
+static int sbefifo_ffdc_get_uint32(struct sbefifo *sbefifo, uint32_t offset, uint32_t *value)
+{
+ uint32_t v;
+
+ if (offset + 4 > sbefifo->ffdc_len)
+ return -1;
+
+ memcpy(&v, sbefifo->ffdc + offset, 4);
+ *value = be32toh(v);
+
+ return 0;
+}
+
+static int sbefifo_ffdc_dump_pkg(struct sbefifo *sbefifo, uint32_t offset)
+{
+ uint32_t offset2 = offset;
uint32_t header, value;
uint16_t magic, len_words;
- int i;
+ int i, rc;
- if (buflen < 4)
+ rc = sbefifo_ffdc_get_uint32(sbefifo, offset2, &header);
+ if (rc < 0)
return -1;
+ offset2 += 4;
- /* End of ffdc data */
- if (buflen == 4)
- return 0;
-
- header = be32toh(*(uint32_t *)(buf + offset));
- offset += 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) {
@@ -93,44 +147,47 @@ static int sbefifo_op_ffdc_read(uint8_t *buf, uint32_t buflen)
}
len_words = header & 0xffff;
- if (offset + len_words * 4 > buflen)
- return -1;
- value = be32toh(*(uint32_t *)(buf + offset));
- offset += 4;
+ rc = sbefifo_ffdc_get_uint32(sbefifo, offset2, &value);
+ if (rc < 0)
+ return -1;
+ offset2 += 4;
PR_ERROR("FFDC: Sequence = %u\n", value >> 16);
PR_ERROR("FFDC: Command = 0x%08x\n", value & 0xffff);
- value = be32toh(*(uint32_t *)(buf + offset));
- offset += 4;
+ rc = sbefifo_ffdc_get_uint32(sbefifo, offset2, &value);
+ if (rc < 0)
+ return -1;
+ offset2 += 4;
PR_ERROR("FFDC: RC = 0x%08x\n", value);
for (i=0; i<len_words-3; i++) {
- value = be32toh(*(uint32_t *)(buf + offset));
- offset += 4;
+ rc = sbefifo_ffdc_get_uint32(sbefifo, offset2, &value);
+ if (rc < 0)
+ return -1;
+ offset2 += 4;
PR_ERROR("FFDC: Data: 0x%08x\n", value);
}
- return offset;
+ return offset2 - offset;
}
-static int sbefifo_op_ffdc(uint8_t *buf, uint32_t buflen)
+static void sbefifo_ffdc_dump(struct sbefifo *sbefifo)
{
uint32_t offset = 0;
- int rc;
- while (1) {
- rc = sbefifo_op_ffdc_read(buf + offset, buflen - offset);
- if (rc <= 0)
+ while (offset < sbefifo->ffdc_len) {
+ int n;
+
+ n = sbefifo_ffdc_dump_pkg(sbefifo, offset);
+ if (n <= 0)
break;
- offset += rc;
+ offset += n;
}
-
- return rc;
}
static int sbefifo_op(struct sbefifo *sbefifo,
@@ -144,6 +201,8 @@ static int sbefifo_op(struct sbefifo *sbefifo,
uint16_t value;
int rc;
+ sbefifo_ffdc_clear(sbefifo);
+
assert(msg_len > 0);
/* Allocate extra memory for FFDC (SBEFIFO_MAX_FFDC_SIZE = 0x2000) */
@@ -200,7 +259,8 @@ static int sbefifo_op(struct sbefifo *sbefifo,
return 0;
} else {
PR_ERROR("sbefifo: Operation failed, response=0x%08x\n", resp[1]);
- sbefifo_op_ffdc(buf + offset, buflen - offset);
+ sbefifo_ffdc_set(sbefifo, buf + offset, buflen - offset - 4, resp[1]);
+ sbefifo_ffdc_dump(sbefifo);
}
fail:
--
2.21.0
More information about the Pdbg
mailing list