diff options
author | Alistair Popple <alistair@popple.id.au> | 2017-08-14 14:54:46 +1000 |
---|---|---|
committer | Alistair Popple <alistair@popple.id.au> | 2017-08-14 16:27:19 +1000 |
commit | 0bf4a14b4c9765ca3ddb4256bbfdc529d7f9bb95 (patch) | |
tree | 44f04b0154e7b84e17195b21b7bcd9aa15a23e1b | |
parent | 03a3c429598f530cf765cefd845ab2f05ceca1af (diff) | |
download | pdbg-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.am | 4 | ||||
-rw-r--r-- | libpdbg/host.c | 118 | ||||
-rw-r--r-- | p8-host.dts.m4 | 25 | ||||
-rw-r--r-- | p9-host.dts.m4 | 21 | ||||
-rw-r--r-- | p9-kernel.dts.m4 (renamed from p9-kernel.dts) | 0 | ||||
-rw-r--r-- | src/main.c | 20 |
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 @@ -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; |