summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2017-08-14 14:54:46 +1000
committerAlistair Popple <alistair@popple.id.au>2017-08-14 16:27:19 +1000
commit0bf4a14b4c9765ca3ddb4256bbfdc529d7f9bb95 (patch)
tree44f04b0154e7b84e17195b21b7bcd9aa15a23e1b
parent03a3c429598f530cf765cefd845ab2f05ceca1af (diff)
downloadpdbg-0bf4a14b4c9765ca3ddb4256bbfdc529d7f9bb95.tar.gz
pdbg-0bf4a14b4c9765ca3ddb4256bbfdc529d7f9bb95.zip
Add backend for host based debugfs
Linux kernels configured with CONFIG_SCOM_DEBUGFS can be used to access SCOM registers on the PowerPC machine running pdbg. Add a backend which can be use to access SCOM registers via debugfs. Signed-off-by: Alistair Popple <alistair@popple.id.au>
-rw-r--r--Makefile.am4
-rw-r--r--libpdbg/host.c118
-rw-r--r--p8-host.dts.m425
-rw-r--r--p9-host.dts.m421
-rw-r--r--p9-kernel.dts.m4 (renamed from p9-kernel.dts)0
-rw-r--r--src/main.c20
6 files changed, 186 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index 9a6e508..4f78546 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,8 +11,9 @@ AM_CFLAGS = -I$(top_srcdir)/ccan/array_size -Wall -Werror
pdbg_SOURCES = \
src/main.c
-pdbg_LDADD = fake.dtb.o p8-fsi.dtb.o p8-i2c.dtb.o p9w-fsi.dtb.o \
+pdbg_LDADD = fake.dtb.o p8-fsi.dtb.o p8-i2c.dtb.o p9w-fsi.dtb.o p8-host.dtb.o \
p9z-fsi.dtb.o p9r-fsi.dtb.o p9-kernel.dtb.o libpdbg.la libfdt.la \
+ p9-host.dtb.o \
-L.libs
pdbg_LDFLAGS = -Wl,--whole-archive,-lpdbg,--no-whole-archive
@@ -35,6 +36,7 @@ libfdt_la_SOURCES = \
libfdt/fdt_overlay.c
libpdbg_la_SOURCES = \
+ libpdbg/host.c \
libpdbg/kernel.c \
libpdbg/fake.c \
libpdbg/chip.c \
diff --git a/libpdbg/host.c b/libpdbg/host.c
new file mode 100644
index 0000000..592816c
--- /dev/null
+++ b/libpdbg/host.c
@@ -0,0 +1,118 @@
+/* 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.
+ */
+#define _LARGEFILE64_SOURCE
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <err.h>
+#include <inttypes.h>
+
+#include "bitutils.h"
+#include "operations.h"
+#include "target.h"
+
+#define XSCOM_BASE_PATH "/sys/kernel/debug/powerpc/scom"
+
+static uint64_t xscom_mangle_addr(uint64_t addr)
+{
+ uint64_t tmp;
+
+ /*
+ * Shift the top 4 bits (indirect mode) down by 4 bits so we
+ * don't lose going through the debugfs interfaces.
+ */
+ tmp = (addr & 0xf000000000000000) >> 4;
+ addr &= 0x00ffffffffffffff;
+ addr |= tmp;
+
+ /* Shift up by 3 for debugfs */
+ return addr << 3;
+}
+
+static int xscom_read(struct pib *pib, uint64_t addr, uint64_t *val)
+{
+ int rc;
+ int fd = *(int *) pib->priv;
+
+ addr = xscom_mangle_addr(addr);
+ lseek64(fd, addr, SEEK_SET);
+ rc = read(fd, val, 8);
+ if (rc != 8)
+ return -1;
+
+ return 0;
+}
+
+static int xscom_write(struct pib *pib, uint64_t addr, uint64_t val)
+{
+ int rc;
+ int fd = *(int *) pib->priv;
+
+ addr = xscom_mangle_addr(addr);
+ lseek64(fd, addr, SEEK_SET);
+ rc = write(fd, &val, 8);
+ if (rc != 8)
+ return -1;
+
+ return 0;
+}
+
+static int host_pib_probe(struct target *target)
+{
+ struct pib *pib = target_to_pib(target);
+ int *fd;
+ char *access_fn;
+ uint32_t chip_id;
+
+ fd = malloc(sizeof(fd));
+ if (!fd)
+ return -1;
+
+ chip_id = dt_prop_get_u32(target->dn, "chip-id");
+ if (asprintf(&access_fn, "%s/%08d/access", XSCOM_BASE_PATH, chip_id) < 0) {
+ free(fd);
+ return -1;
+ }
+
+ *fd = open(access_fn, O_RDWR);
+ free(access_fn);
+ if (fd < 0)
+ return -1;
+
+ pib->priv = fd;
+
+ return 0;
+}
+
+struct pib host_pib = {
+ .target = {
+ .name = "Host based debugfs SCOM",
+ .compatible = "ibm,host-pib",
+ .class = "pib",
+ .probe = host_pib_probe,
+ },
+ .read = xscom_read,
+ .write = xscom_write,
+};
+DECLARE_HW_UNIT(host_pib);
diff --git a/p8-host.dts.m4 b/p8-host.dts.m4
new file mode 100644
index 0000000..3197da7
--- /dev/null
+++ b/p8-host.dts.m4
@@ -0,0 +1,25 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ /* Host based debugfs access */
+ pib@0 {
+ #address-cells = <0x2>;
+ #size-cells = <0x1>;
+ compatible = "ibm,host-pib";
+ chip-id = <0x0>;
+ index = <0x0>;
+ include(p8-pib.dts.m4)dnl
+ };
+
+ pib@8 {
+ #address-cells = <0x2>;
+ #size-cells = <0x1>;
+ compatible = "ibm,host-pib";
+ chip-id = <0x8>;
+ index = <0x1>;
+ include(p8-pib.dts.m4)dnl
+ };
+};
diff --git a/p9-host.dts.m4 b/p9-host.dts.m4
new file mode 100644
index 0000000..5566acd
--- /dev/null
+++ b/p9-host.dts.m4
@@ -0,0 +1,21 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ /* Host based debugfs access */
+ pib@0 {
+ compatible = "ibm,host-pib";
+ chip-id = <0x0>;
+ index = <0x0>;
+ include(p9-pib.dts.m4)dnl
+ };
+
+ pib@8 {
+ compatible = "ibm,host-pib";
+ chip-id = <0x8>;
+ index = <0x1>;
+ include(p9-pib.dts.m4)dnl
+ };
+};
diff --git a/p9-kernel.dts b/p9-kernel.dts.m4
index ff19779..ff19779 100644
--- a/p9-kernel.dts
+++ b/p9-kernel.dts.m4
diff --git a/src/main.c b/src/main.c
index f1b0967..0dd52c7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -52,7 +52,7 @@ static int cmd_max_arg_count = 0;
/* At the moment all commands only take some kind of number */
static uint64_t cmd_args[MAX_CMD_ARGS];
-enum backend { FSI, I2C, KERNEL, FAKE };
+enum backend { FSI, I2C, KERNEL, FAKE, HOST };
static enum backend backend = KERNEL;
static char const *device_node;
@@ -86,6 +86,7 @@ static void print_usage(char *pname)
printf("\t\t\tbit-banging to access the host processor\n");
printf("\t\t\tvia the FSI bus.\n");
printf("\t\ti2c:\tThe P8 only backend which goes via I2C.\n");
+ printf("\t\thost:\tUse the debugfs xscom nodes.\n");
printf("\t\tkernel:\tThe default backend which goes the kernel FSI driver.\n");
printf("\t-d, --device=backend device\n");
printf("\t\tFor I2C the device node used by the backend to access the bus.\n");
@@ -291,6 +292,8 @@ static bool parse_options(int argc, char *argv[])
* other than the first? */
} else if (strcmp(optarg, "fake") == 0) {
backend = FAKE;
+ } else if (strcmp(optarg, "host") == 0) {
+ backend = HOST;
} else
opt_error = true;
break;
@@ -625,6 +628,10 @@ extern unsigned char _binary_p9_kernel_dtb_o_start;
extern unsigned char _binary_p9_kernel_dtb_o_end;
extern unsigned char _binary_fake_dtb_o_start;
extern unsigned char _binary_fake_dtb_o_end;
+extern unsigned char _binary_p8_host_dtb_o_start;
+extern unsigned char _binary_p8_host_dtb_o_end;
+extern unsigned char _binary_p9_host_dtb_o_start;
+extern unsigned char _binary_p9_host_dtb_o_end;
static int target_select(void)
{
struct target *fsi, *pib, *chip, *thread;
@@ -657,6 +664,17 @@ static int target_select(void)
targets_init(&_binary_fake_dtb_o_start);
break;
+ case HOST:
+ if (!strcmp(device_node, "p8"))
+ targets_init(&_binary_p8_host_dtb_o_start);
+ else if (!strcmp(device_node, "p9"))
+ targets_init(&_binary_p9_host_dtb_o_start);
+ else {
+ PR_ERROR("Unsupported device type for host backend\n");
+ return -1;
+ }
+ break;
+
default:
PR_ERROR("Invalid backend specified\n");
return -1;
OpenPOWER on IntegriCloud