From 3ee0933d7b318c8272ca91bf070f54bfc121a0ed Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Mallo Date: Tue, 3 Sep 2024 13:06:33 +0200 Subject: [PATCH] Add plictool to dump PLIC state --- lagarto-ox.nix | 1 + overlay.nix | 16 ++++++ tools/plictool.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 tools/plictool.c diff --git a/lagarto-ox.nix b/lagarto-ox.nix index 7a8b9ff..c168b65 100644 --- a/lagarto-ox.nix +++ b/lagarto-ox.nix @@ -166,6 +166,7 @@ extraUtilsCommands = '' cp -a ${pkgs.csrtool}/bin/csrtool $out/bin cp -a ${pkgs.memtool}/bin/memtool $out/bin + cp -a ${pkgs.plictool}/bin/plictool $out/bin ''; # Write a counter to the DMA region, so we can check the kernel is not diff --git a/overlay.nix b/overlay.nix index 49c8f83..bc60e91 100644 --- a/overlay.nix +++ b/overlay.nix @@ -69,6 +69,22 @@ final: prev: ''; }; + plictool = prev.pkgsStatic.stdenv.mkDerivation { + name = "plictool"; + src = ./tools/plictool.c; + unpackPhase = '' + cp ${./tools/plictool.c} plictool.c + ''; + dontConfigure = true; + buildPhase = '' + $CC -static plictool.c -o plictool + ''; + installPhase = '' + mkdir -p $out/bin + cp plictool $out/bin/ + ''; + }; + bitstreams = builtins.fetchGit { url = "git@bscpm03.bsc.es:rarias/bitstreams.git"; rev = "097dad3e888f630ad6ec7e7056ee1b3fcb03400b"; diff --git a/tools/plictool.c b/tools/plictool.c new file mode 100644 index 0000000..08f267e --- /dev/null +++ b/tools/plictool.c @@ -0,0 +1,131 @@ +/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: MIT + * Author: Rodrigo Arias Mallo */ + +/* Small utility to dump the state of the PLIC. */ + +/* Changelog: + * v0.0.1 (2024-09-03): Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +const char *plic_address_str = "0x40800000"; +long ncontexts = 15872L; +long maxsources = 1024L; +long nsources = 1024L; + +static void +usage(void) +{ + printf("plictool v0.0.1 - Rodrigo Arias Mallo \n"); + + printf( +"Usage: plictool [-a addr] [-s nsources] [-c ncontexts]\n"); + exit(1); +} + +void dump_sources(void *base) +{ + for (long s = 0; s < nsources; s++) { + int printed_source = 0; + + uint32_t *pending_reg = base + 0x1000L + (s / 32L) * 4L; + long shift = s % 32L; + uint32_t pending = ((*pending_reg) >> shift) & 1; + uint32_t *priority_reg = base + 0x0000L + (s * 4L); + uint32_t priority = *priority_reg; + + const char *fmt = + "src=%ld pend=%u prio=%u"; + + if (pending || priority) { + printf(fmt, s, pending, priority); + printed_source = 1; + } + + int first_context = 1; + for (long c = 0; c < ncontexts; c++) { + uint32_t *enable_reg = base + 0x2000L + 0x80L * c + (s / 32L) * 4L; + uint32_t enabled = ((*enable_reg) >> shift) & 1; + uint32_t *threshold_reg = base + 0x200000L + (c * 0x1000L); + uint32_t threshold = *threshold_reg; + + if (!enabled) + continue; + + if (!printed_source) { + printf(fmt, s, pending, priority); + printed_source = 1; + } + + printf(" ctx=%ld thre=%u", c, threshold); + } + + if (printed_source) + printf("\n"); + } +} + +int main(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "a:hs:c:")) != -1) { + switch (opt) { + case 'a': + plic_address_str = optarg; + break; + case 's': + nsources = atol(optarg); + break; + case 'c': + ncontexts = atol(optarg); + break; + case 'h': + default: /* '?' */ + usage(); + } + } + + off_t plic_address = (off_t) strtoll(plic_address_str, NULL, 16); + + printf("plic=0x%08x nsources=%ld ncontexts=%ld\n", + plic_address, nsources, ncontexts); + + int fd = open("/dev/mem", O_RDWR | O_SYNC); + + if (fd == -1) { + perror("cannot open /dev/mem"); + exit(1); + } + + size_t map_size = 0x4000000UL; + void *map_base = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, plic_address); + + if (map_base == MAP_FAILED) { + perror("mmap failed"); + if (errno == EPERM) { + fprintf(stderr, "Have you disabled 'CONFIG_STRICT_DEVMEM' and " + "'CONFIG_IO_STRICT_DEVMEM' in the kernel config?\n" + "Hint: zgrep STRICT_DEVMEM /proc/config.gz\n"); + } + exit(1); + } + + dump_sources(map_base); + + munmap(map_base, map_size); + + close(fd); + + return 0; +}