Add plictool to dump PLIC state
This commit is contained in:
parent
1aa899c8f0
commit
3ee0933d7b
@ -166,6 +166,7 @@
|
|||||||
extraUtilsCommands = ''
|
extraUtilsCommands = ''
|
||||||
cp -a ${pkgs.csrtool}/bin/csrtool $out/bin
|
cp -a ${pkgs.csrtool}/bin/csrtool $out/bin
|
||||||
cp -a ${pkgs.memtool}/bin/memtool $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
|
# Write a counter to the DMA region, so we can check the kernel is not
|
||||||
|
16
overlay.nix
16
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 {
|
bitstreams = builtins.fetchGit {
|
||||||
url = "git@bscpm03.bsc.es:rarias/bitstreams.git";
|
url = "git@bscpm03.bsc.es:rarias/bitstreams.git";
|
||||||
rev = "097dad3e888f630ad6ec7e7056ee1b3fcb03400b";
|
rev = "097dad3e888f630ad6ec7e7056ee1b3fcb03400b";
|
||||||
|
131
tools/plictool.c
Normal file
131
tools/plictool.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
* Author: Rodrigo Arias Mallo <rodrigo.arias@bsc.es> */
|
||||||
|
|
||||||
|
/* Small utility to dump the state of the PLIC. */
|
||||||
|
|
||||||
|
/* Changelog:
|
||||||
|
* v0.0.1 (2024-09-03): Initial version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
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 <rodrigo.arias@bsc.es>\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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user