From patchwork Wed Aug 21 06:08:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amitay Isaacs X-Patchwork-Id: 1150581 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Cy013F85z9sN1 for ; Wed, 21 Aug 2019 16:08:33 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ozlabs.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.b="ScpBF503"; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 46Cy004PVmzDqV8 for ; Wed, 21 Aug 2019 16:08:32 +1000 (AEST) X-Original-To: pdbg@lists.ozlabs.org Delivered-To: pdbg@lists.ozlabs.org Received: from ozlabs.org (bilbo.ozlabs.org [203.11.71.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 46Cxzp1pplzDqXM for ; Wed, 21 Aug 2019 16:08:22 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=ozlabs.org Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.b="ScpBF503"; dkim-atps=neutral Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 46Cxzn2sRWz9sDQ; Wed, 21 Aug 2019 16:08:21 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; t=1566367701; bh=yC1bFPAVCU6yQrUwKxStqxw/asejmb16fReA6V+glyg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ScpBF503IV/Hy6FmnLhXZm9E+8YAfYY74itn9mhIIXedJo3pIGS8+fBkEz3BuQG8v /ORJrCPQ0JxvIfZYP6UTUv36HBJK2xYn87SAvOQMNsEwncBEoWAuPUNBor7Sd65HSd 03QWZLIt2xvv/ATdkrvidtqefKTcmhrQLCn4Q8SoWXQe+KQJ860XhdCwfYvinPkm4C w7y+PX2GjVGmFo54FP6yk4L3MXWOSlMdzWkyFwCWp+u9hofquLbvIYvUy8ge3K0MzU KxdT0Y3LR1m7WLYYn+QvuaCC5StLZw/ZvVwvLfyIMFec+4tv8Xh/b0VOi+d2sGJavj V91dMFy6UaxNQ== From: Amitay Isaacs To: pdbg@lists.ozlabs.org Date: Wed, 21 Aug 2019 16:08:14 +1000 Message-Id: <20190821060817.31012-2-amitay@ozlabs.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190821060817.31012-1-amitay@ozlabs.org> References: <20190821060817.31012-1-amitay@ozlabs.org> MIME-Version: 1.0 Subject: [Pdbg] [PATCH v2 1/4] libsbefifo: Add a library to talk to sbefifo X-BeenThere: pdbg@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "mailing list for https://github.com/open-power/pdbg development" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Amitay Isaacs Errors-To: pdbg-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Pdbg" Signed-off-by: Amitay Isaacs --- 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 +#include +#include +#include +#include + +#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 +#include +#include +#include + +#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 +#include +#include +#include +#include + +#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 +#include +#include +#include + +#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 +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include + +#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 +#include +#include +#include + +#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 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> 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 +#include +#include +#include +#include + +#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 +#include +#include +#include + +#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 +#include +#include +#include +#include +#include + +#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 +#include +#include + +#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; iffdc_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 + +#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 +#include +#include +#include +#include +#include + +#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 + +#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__ */